1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | // Context.cpp: Implements the es2::Context class, managing all GL state and performing |
16 | // rendering operations. It is the GLES2 specific implementation of EGLContext. |
17 | |
18 | #include "Context.h" |
19 | |
20 | #include "main.h" |
21 | #include "mathutil.h" |
22 | #include "utilities.h" |
23 | #include "ResourceManager.h" |
24 | #include "Buffer.h" |
25 | #include "Fence.h" |
26 | #include "Framebuffer.h" |
27 | #include "Program.h" |
28 | #include "Query.h" |
29 | #include "Renderbuffer.h" |
30 | #include "Sampler.h" |
31 | #include "Shader.h" |
32 | #include "Texture.h" |
33 | #include "TransformFeedback.h" |
34 | #include "VertexArray.h" |
35 | #include "VertexDataManager.h" |
36 | #include "IndexDataManager.h" |
37 | #include "libEGL/Display.h" |
38 | #include "common/Surface.hpp" |
39 | #include "Common/Half.hpp" |
40 | |
41 | #include <EGL/eglext.h> |
42 | |
43 | #include <algorithm> |
44 | #include <string> |
45 | |
46 | namespace es2 |
47 | { |
48 | Context::Context(egl::Display *display, const Context *shareContext, const egl::Config *config) |
49 | : egl::Context(display), config(config) |
50 | { |
51 | sw::Context *context = new sw::Context(); |
52 | device = new es2::Device(context); |
53 | |
54 | setClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
55 | |
56 | mState.depthClearValue = 1.0f; |
57 | mState.stencilClearValue = 0; |
58 | |
59 | mState.cullFaceEnabled = false; |
60 | mState.cullMode = GL_BACK; |
61 | mState.frontFace = GL_CCW; |
62 | mState.depthTestEnabled = false; |
63 | mState.depthFunc = GL_LESS; |
64 | mState.blendEnabled = false; |
65 | mState.sourceBlendRGB = GL_ONE; |
66 | mState.sourceBlendAlpha = GL_ONE; |
67 | mState.destBlendRGB = GL_ZERO; |
68 | mState.destBlendAlpha = GL_ZERO; |
69 | mState.blendEquationRGB = GL_FUNC_ADD; |
70 | mState.blendEquationAlpha = GL_FUNC_ADD; |
71 | mState.blendColor.red = 0; |
72 | mState.blendColor.green = 0; |
73 | mState.blendColor.blue = 0; |
74 | mState.blendColor.alpha = 0; |
75 | mState.stencilTestEnabled = false; |
76 | mState.stencilFunc = GL_ALWAYS; |
77 | mState.stencilRef = 0; |
78 | mState.stencilMask = 0xFFFFFFFFu; |
79 | mState.stencilWritemask = 0xFFFFFFFFu; |
80 | mState.stencilBackFunc = GL_ALWAYS; |
81 | mState.stencilBackRef = 0; |
82 | mState.stencilBackMask = 0xFFFFFFFFu; |
83 | mState.stencilBackWritemask = 0xFFFFFFFFu; |
84 | mState.stencilFail = GL_KEEP; |
85 | mState.stencilPassDepthFail = GL_KEEP; |
86 | mState.stencilPassDepthPass = GL_KEEP; |
87 | mState.stencilBackFail = GL_KEEP; |
88 | mState.stencilBackPassDepthFail = GL_KEEP; |
89 | mState.stencilBackPassDepthPass = GL_KEEP; |
90 | mState.polygonOffsetFillEnabled = false; |
91 | mState.polygonOffsetFactor = 0.0f; |
92 | mState.polygonOffsetUnits = 0.0f; |
93 | mState.sampleAlphaToCoverageEnabled = false; |
94 | mState.sampleCoverageEnabled = false; |
95 | mState.sampleCoverageValue = 1.0f; |
96 | mState.sampleCoverageInvert = false; |
97 | mState.scissorTestEnabled = false; |
98 | mState.ditherEnabled = true; |
99 | mState.primitiveRestartFixedIndexEnabled = false; |
100 | mState.rasterizerDiscardEnabled = false; |
101 | mState.generateMipmapHint = GL_DONT_CARE; |
102 | mState.fragmentShaderDerivativeHint = GL_DONT_CARE; |
103 | mState.textureFilteringHint = GL_DONT_CARE; |
104 | |
105 | mState.lineWidth = 1.0f; |
106 | |
107 | mState.viewportX = 0; |
108 | mState.viewportY = 0; |
109 | mState.viewportWidth = 0; |
110 | mState.viewportHeight = 0; |
111 | mState.zNear = 0.0f; |
112 | mState.zFar = 1.0f; |
113 | |
114 | mState.scissorX = 0; |
115 | mState.scissorY = 0; |
116 | mState.scissorWidth = 0; |
117 | mState.scissorHeight = 0; |
118 | |
119 | mState.colorMaskRed = true; |
120 | mState.colorMaskGreen = true; |
121 | mState.colorMaskBlue = true; |
122 | mState.colorMaskAlpha = true; |
123 | mState.depthMask = true; |
124 | |
125 | if(shareContext) |
126 | { |
127 | mResourceManager = shareContext->mResourceManager; |
128 | mResourceManager->addRef(); |
129 | } |
130 | else |
131 | { |
132 | mResourceManager = new ResourceManager(); |
133 | } |
134 | |
135 | // [OpenGL ES 2.0.24] section 3.7 page 83: |
136 | // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional |
137 | // and cube map texture state vectors respectively associated with them. |
138 | // In order that access to these initial textures not be lost, they are treated as texture |
139 | // objects all of whose names are 0. |
140 | |
141 | mTexture2DZero = new Texture2D(0); |
142 | mTexture3DZero = new Texture3D(0); |
143 | mTexture2DArrayZero = new Texture2DArray(0); |
144 | mTextureCubeMapZero = new TextureCubeMap(0); |
145 | mTexture2DRectZero = new Texture2DRect(0); |
146 | mTextureExternalZero = new TextureExternal(0); |
147 | |
148 | mState.activeSampler = 0; |
149 | |
150 | for(int type = 0; type < TEXTURE_TYPE_COUNT; type++) |
151 | { |
152 | bindTexture((TextureType)type, 0); |
153 | } |
154 | |
155 | bindVertexArray(0); |
156 | bindArrayBuffer(0); |
157 | bindElementArrayBuffer(0); |
158 | bindReadFramebuffer(0); |
159 | bindDrawFramebuffer(0); |
160 | bindRenderbuffer(0); |
161 | bindGenericUniformBuffer(0); |
162 | bindTransformFeedback(0); |
163 | |
164 | mState.currentProgram = 0; |
165 | |
166 | mVertexDataManager = nullptr; |
167 | mIndexDataManager = nullptr; |
168 | |
169 | mInvalidEnum = false; |
170 | mInvalidValue = false; |
171 | mInvalidOperation = false; |
172 | mOutOfMemory = false; |
173 | mInvalidFramebufferOperation = false; |
174 | |
175 | mHasBeenCurrent = false; |
176 | |
177 | markAllStateDirty(); |
178 | } |
179 | |
180 | Context::~Context() |
181 | { |
182 | if(mState.currentProgram != 0) |
183 | { |
184 | Program *programObject = mResourceManager->getProgram(mState.currentProgram); |
185 | if(programObject) |
186 | { |
187 | programObject->release(); |
188 | } |
189 | mState.currentProgram = 0; |
190 | } |
191 | |
192 | while(!mFramebufferNameSpace.empty()) |
193 | { |
194 | deleteFramebuffer(mFramebufferNameSpace.firstName()); |
195 | } |
196 | |
197 | while(!mFenceNameSpace.empty()) |
198 | { |
199 | deleteFence(mFenceNameSpace.firstName()); |
200 | } |
201 | |
202 | while(!mQueryNameSpace.empty()) |
203 | { |
204 | deleteQuery(mQueryNameSpace.firstName()); |
205 | } |
206 | |
207 | while(!mVertexArrayNameSpace.empty()) |
208 | { |
209 | deleteVertexArray(mVertexArrayNameSpace.lastName()); |
210 | } |
211 | |
212 | while(!mTransformFeedbackNameSpace.empty()) |
213 | { |
214 | deleteTransformFeedback(mTransformFeedbackNameSpace.firstName()); |
215 | } |
216 | |
217 | for(int type = 0; type < TEXTURE_TYPE_COUNT; type++) |
218 | { |
219 | for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) |
220 | { |
221 | mState.samplerTexture[type][sampler] = nullptr; |
222 | } |
223 | } |
224 | |
225 | for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) |
226 | { |
227 | mState.vertexAttribute[i].mBoundBuffer = nullptr; |
228 | } |
229 | |
230 | for(int i = 0; i < QUERY_TYPE_COUNT; i++) |
231 | { |
232 | mState.activeQuery[i] = nullptr; |
233 | } |
234 | |
235 | mState.arrayBuffer = nullptr; |
236 | mState.copyReadBuffer = nullptr; |
237 | mState.copyWriteBuffer = nullptr; |
238 | mState.pixelPackBuffer = nullptr; |
239 | mState.pixelUnpackBuffer = nullptr; |
240 | mState.genericUniformBuffer = nullptr; |
241 | mState.genericTransformFeedbackBuffer = nullptr; |
242 | |
243 | for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++) { |
244 | mState.uniformBuffers[i].set(nullptr, 0, 0); |
245 | } |
246 | |
247 | mState.renderbuffer = nullptr; |
248 | |
249 | for(int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i) |
250 | { |
251 | mState.sampler[i] = nullptr; |
252 | } |
253 | |
254 | mTexture2DZero = nullptr; |
255 | mTexture3DZero = nullptr; |
256 | mTexture2DArrayZero = nullptr; |
257 | mTextureCubeMapZero = nullptr; |
258 | mTexture2DRectZero = nullptr; |
259 | mTextureExternalZero = nullptr; |
260 | |
261 | delete mVertexDataManager; |
262 | delete mIndexDataManager; |
263 | |
264 | mResourceManager->release(); |
265 | delete device; |
266 | } |
267 | |
268 | void Context::makeCurrent(gl::Surface *surface) |
269 | { |
270 | if(!mHasBeenCurrent) |
271 | { |
272 | mVertexDataManager = new VertexDataManager(this); |
273 | mIndexDataManager = new IndexDataManager(); |
274 | |
275 | mState.viewportX = 0; |
276 | mState.viewportY = 0; |
277 | mState.viewportWidth = surface ? surface->getWidth() : 0; |
278 | mState.viewportHeight = surface ? surface->getHeight() : 0; |
279 | |
280 | mState.scissorX = 0; |
281 | mState.scissorY = 0; |
282 | mState.scissorWidth = surface ? surface->getWidth() : 0; |
283 | mState.scissorHeight = surface ? surface->getHeight() : 0; |
284 | |
285 | mHasBeenCurrent = true; |
286 | } |
287 | |
288 | if(surface) |
289 | { |
290 | // Wrap the existing resources into GL objects and assign them to the '0' names |
291 | egl::Image *defaultRenderTarget = surface->getRenderTarget(); |
292 | egl::Image *depthStencil = surface->getDepthStencil(); |
293 | |
294 | Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget); |
295 | DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil); |
296 | Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero); |
297 | |
298 | setFramebufferZero(framebufferZero); |
299 | |
300 | if(defaultRenderTarget) |
301 | { |
302 | defaultRenderTarget->release(); |
303 | } |
304 | |
305 | if(depthStencil) |
306 | { |
307 | depthStencil->release(); |
308 | } |
309 | } |
310 | else |
311 | { |
312 | setFramebufferZero(nullptr); |
313 | } |
314 | |
315 | markAllStateDirty(); |
316 | } |
317 | |
318 | EGLint Context::getClientVersion() const |
319 | { |
320 | return 3; |
321 | } |
322 | |
323 | EGLint Context::getConfigID() const |
324 | { |
325 | return config->mConfigID; |
326 | } |
327 | |
328 | // This function will set all of the state-related dirty flags, so that all state is set during next pre-draw. |
329 | void Context::markAllStateDirty() |
330 | { |
331 | mAppliedProgramSerial = 0; |
332 | |
333 | mDepthStateDirty = true; |
334 | mMaskStateDirty = true; |
335 | mBlendStateDirty = true; |
336 | mStencilStateDirty = true; |
337 | mPolygonOffsetStateDirty = true; |
338 | mSampleStateDirty = true; |
339 | mDitherStateDirty = true; |
340 | mFrontFaceDirty = true; |
341 | } |
342 | |
343 | void Context::setClearColor(float red, float green, float blue, float alpha) |
344 | { |
345 | mState.colorClearValue.red = red; |
346 | mState.colorClearValue.green = green; |
347 | mState.colorClearValue.blue = blue; |
348 | mState.colorClearValue.alpha = alpha; |
349 | } |
350 | |
351 | void Context::setClearDepth(float depth) |
352 | { |
353 | mState.depthClearValue = depth; |
354 | } |
355 | |
356 | void Context::setClearStencil(int stencil) |
357 | { |
358 | mState.stencilClearValue = stencil; |
359 | } |
360 | |
361 | void Context::setCullFaceEnabled(bool enabled) |
362 | { |
363 | mState.cullFaceEnabled = enabled; |
364 | } |
365 | |
366 | bool Context::isCullFaceEnabled() const |
367 | { |
368 | return mState.cullFaceEnabled; |
369 | } |
370 | |
371 | void Context::setCullMode(GLenum mode) |
372 | { |
373 | mState.cullMode = mode; |
374 | } |
375 | |
376 | void Context::setFrontFace(GLenum front) |
377 | { |
378 | if(mState.frontFace != front) |
379 | { |
380 | mState.frontFace = front; |
381 | mFrontFaceDirty = true; |
382 | } |
383 | } |
384 | |
385 | void Context::setDepthTestEnabled(bool enabled) |
386 | { |
387 | if(mState.depthTestEnabled != enabled) |
388 | { |
389 | mState.depthTestEnabled = enabled; |
390 | mDepthStateDirty = true; |
391 | } |
392 | } |
393 | |
394 | bool Context::isDepthTestEnabled() const |
395 | { |
396 | return mState.depthTestEnabled; |
397 | } |
398 | |
399 | void Context::setDepthFunc(GLenum depthFunc) |
400 | { |
401 | if(mState.depthFunc != depthFunc) |
402 | { |
403 | mState.depthFunc = depthFunc; |
404 | mDepthStateDirty = true; |
405 | } |
406 | } |
407 | |
408 | void Context::setDepthRange(float zNear, float zFar) |
409 | { |
410 | mState.zNear = zNear; |
411 | mState.zFar = zFar; |
412 | } |
413 | |
414 | void Context::setBlendEnabled(bool enabled) |
415 | { |
416 | if(mState.blendEnabled != enabled) |
417 | { |
418 | mState.blendEnabled = enabled; |
419 | mBlendStateDirty = true; |
420 | } |
421 | } |
422 | |
423 | bool Context::isBlendEnabled() const |
424 | { |
425 | return mState.blendEnabled; |
426 | } |
427 | |
428 | void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) |
429 | { |
430 | if(mState.sourceBlendRGB != sourceRGB || |
431 | mState.sourceBlendAlpha != sourceAlpha || |
432 | mState.destBlendRGB != destRGB || |
433 | mState.destBlendAlpha != destAlpha) |
434 | { |
435 | mState.sourceBlendRGB = sourceRGB; |
436 | mState.destBlendRGB = destRGB; |
437 | mState.sourceBlendAlpha = sourceAlpha; |
438 | mState.destBlendAlpha = destAlpha; |
439 | mBlendStateDirty = true; |
440 | } |
441 | } |
442 | |
443 | void Context::setBlendColor(float red, float green, float blue, float alpha) |
444 | { |
445 | if(mState.blendColor.red != red || |
446 | mState.blendColor.green != green || |
447 | mState.blendColor.blue != blue || |
448 | mState.blendColor.alpha != alpha) |
449 | { |
450 | mState.blendColor.red = red; |
451 | mState.blendColor.green = green; |
452 | mState.blendColor.blue = blue; |
453 | mState.blendColor.alpha = alpha; |
454 | mBlendStateDirty = true; |
455 | } |
456 | } |
457 | |
458 | void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) |
459 | { |
460 | if(mState.blendEquationRGB != rgbEquation || |
461 | mState.blendEquationAlpha != alphaEquation) |
462 | { |
463 | mState.blendEquationRGB = rgbEquation; |
464 | mState.blendEquationAlpha = alphaEquation; |
465 | mBlendStateDirty = true; |
466 | } |
467 | } |
468 | |
469 | void Context::setStencilTestEnabled(bool enabled) |
470 | { |
471 | if(mState.stencilTestEnabled != enabled) |
472 | { |
473 | mState.stencilTestEnabled = enabled; |
474 | mStencilStateDirty = true; |
475 | } |
476 | } |
477 | |
478 | bool Context::isStencilTestEnabled() const |
479 | { |
480 | return mState.stencilTestEnabled; |
481 | } |
482 | |
483 | void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) |
484 | { |
485 | if(mState.stencilFunc != stencilFunc || |
486 | mState.stencilRef != stencilRef || |
487 | mState.stencilMask != stencilMask) |
488 | { |
489 | mState.stencilFunc = stencilFunc; |
490 | mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; |
491 | mState.stencilMask = stencilMask; |
492 | mStencilStateDirty = true; |
493 | } |
494 | } |
495 | |
496 | void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) |
497 | { |
498 | if(mState.stencilBackFunc != stencilBackFunc || |
499 | mState.stencilBackRef != stencilBackRef || |
500 | mState.stencilBackMask != stencilBackMask) |
501 | { |
502 | mState.stencilBackFunc = stencilBackFunc; |
503 | mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; |
504 | mState.stencilBackMask = stencilBackMask; |
505 | mStencilStateDirty = true; |
506 | } |
507 | } |
508 | |
509 | void Context::setStencilWritemask(GLuint stencilWritemask) |
510 | { |
511 | if(mState.stencilWritemask != stencilWritemask) |
512 | { |
513 | mState.stencilWritemask = stencilWritemask; |
514 | mStencilStateDirty = true; |
515 | } |
516 | } |
517 | |
518 | void Context::setStencilBackWritemask(GLuint stencilBackWritemask) |
519 | { |
520 | if(mState.stencilBackWritemask != stencilBackWritemask) |
521 | { |
522 | mState.stencilBackWritemask = stencilBackWritemask; |
523 | mStencilStateDirty = true; |
524 | } |
525 | } |
526 | |
527 | void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) |
528 | { |
529 | if(mState.stencilFail != stencilFail || |
530 | mState.stencilPassDepthFail != stencilPassDepthFail || |
531 | mState.stencilPassDepthPass != stencilPassDepthPass) |
532 | { |
533 | mState.stencilFail = stencilFail; |
534 | mState.stencilPassDepthFail = stencilPassDepthFail; |
535 | mState.stencilPassDepthPass = stencilPassDepthPass; |
536 | mStencilStateDirty = true; |
537 | } |
538 | } |
539 | |
540 | void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) |
541 | { |
542 | if(mState.stencilBackFail != stencilBackFail || |
543 | mState.stencilBackPassDepthFail != stencilBackPassDepthFail || |
544 | mState.stencilBackPassDepthPass != stencilBackPassDepthPass) |
545 | { |
546 | mState.stencilBackFail = stencilBackFail; |
547 | mState.stencilBackPassDepthFail = stencilBackPassDepthFail; |
548 | mState.stencilBackPassDepthPass = stencilBackPassDepthPass; |
549 | mStencilStateDirty = true; |
550 | } |
551 | } |
552 | |
553 | void Context::setPolygonOffsetFillEnabled(bool enabled) |
554 | { |
555 | if(mState.polygonOffsetFillEnabled != enabled) |
556 | { |
557 | mState.polygonOffsetFillEnabled = enabled; |
558 | mPolygonOffsetStateDirty = true; |
559 | } |
560 | } |
561 | |
562 | bool Context::isPolygonOffsetFillEnabled() const |
563 | { |
564 | return mState.polygonOffsetFillEnabled; |
565 | } |
566 | |
567 | void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units) |
568 | { |
569 | if(mState.polygonOffsetFactor != factor || |
570 | mState.polygonOffsetUnits != units) |
571 | { |
572 | mState.polygonOffsetFactor = factor; |
573 | mState.polygonOffsetUnits = units; |
574 | mPolygonOffsetStateDirty = true; |
575 | } |
576 | } |
577 | |
578 | void Context::setSampleAlphaToCoverageEnabled(bool enabled) |
579 | { |
580 | if(mState.sampleAlphaToCoverageEnabled != enabled) |
581 | { |
582 | mState.sampleAlphaToCoverageEnabled = enabled; |
583 | mSampleStateDirty = true; |
584 | } |
585 | } |
586 | |
587 | bool Context::isSampleAlphaToCoverageEnabled() const |
588 | { |
589 | return mState.sampleAlphaToCoverageEnabled; |
590 | } |
591 | |
592 | void Context::setSampleCoverageEnabled(bool enabled) |
593 | { |
594 | if(mState.sampleCoverageEnabled != enabled) |
595 | { |
596 | mState.sampleCoverageEnabled = enabled; |
597 | mSampleStateDirty = true; |
598 | } |
599 | } |
600 | |
601 | bool Context::isSampleCoverageEnabled() const |
602 | { |
603 | return mState.sampleCoverageEnabled; |
604 | } |
605 | |
606 | void Context::setSampleCoverageParams(GLclampf value, bool invert) |
607 | { |
608 | if(mState.sampleCoverageValue != value || |
609 | mState.sampleCoverageInvert != invert) |
610 | { |
611 | mState.sampleCoverageValue = value; |
612 | mState.sampleCoverageInvert = invert; |
613 | mSampleStateDirty = true; |
614 | } |
615 | } |
616 | |
617 | void Context::setScissorTestEnabled(bool enabled) |
618 | { |
619 | mState.scissorTestEnabled = enabled; |
620 | } |
621 | |
622 | bool Context::isScissorTestEnabled() const |
623 | { |
624 | return mState.scissorTestEnabled; |
625 | } |
626 | |
627 | void Context::setDitherEnabled(bool enabled) |
628 | { |
629 | if(mState.ditherEnabled != enabled) |
630 | { |
631 | mState.ditherEnabled = enabled; |
632 | mDitherStateDirty = true; |
633 | } |
634 | } |
635 | |
636 | bool Context::isDitherEnabled() const |
637 | { |
638 | return mState.ditherEnabled; |
639 | } |
640 | |
641 | void Context::setPrimitiveRestartFixedIndexEnabled(bool enabled) |
642 | { |
643 | mState.primitiveRestartFixedIndexEnabled = enabled; |
644 | } |
645 | |
646 | bool Context::isPrimitiveRestartFixedIndexEnabled() const |
647 | { |
648 | return mState.primitiveRestartFixedIndexEnabled; |
649 | } |
650 | |
651 | void Context::setRasterizerDiscardEnabled(bool enabled) |
652 | { |
653 | mState.rasterizerDiscardEnabled = enabled; |
654 | } |
655 | |
656 | bool Context::isRasterizerDiscardEnabled() const |
657 | { |
658 | return mState.rasterizerDiscardEnabled; |
659 | } |
660 | |
661 | void Context::setLineWidth(GLfloat width) |
662 | { |
663 | mState.lineWidth = width; |
664 | device->setLineWidth(clamp(width, ALIASED_LINE_WIDTH_RANGE_MIN, ALIASED_LINE_WIDTH_RANGE_MAX)); |
665 | } |
666 | |
667 | void Context::setGenerateMipmapHint(GLenum hint) |
668 | { |
669 | mState.generateMipmapHint = hint; |
670 | } |
671 | |
672 | void Context::setFragmentShaderDerivativeHint(GLenum hint) |
673 | { |
674 | mState.fragmentShaderDerivativeHint = hint; |
675 | // TODO: Propagate the hint to shader translator so we can write |
676 | // ddx, ddx_coarse, or ddx_fine depending on the hint. |
677 | // Ignore for now. It is valid for implementations to ignore hint. |
678 | } |
679 | |
680 | void Context::setTextureFilteringHint(GLenum hint) |
681 | { |
682 | mState.textureFilteringHint = hint; |
683 | } |
684 | |
685 | void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) |
686 | { |
687 | mState.viewportX = x; |
688 | mState.viewportY = y; |
689 | mState.viewportWidth = std::min<GLsizei>(width, IMPLEMENTATION_MAX_RENDERBUFFER_SIZE); // GL_MAX_VIEWPORT_DIMS[0] |
690 | mState.viewportHeight = std::min<GLsizei>(height, IMPLEMENTATION_MAX_RENDERBUFFER_SIZE); // GL_MAX_VIEWPORT_DIMS[1] |
691 | } |
692 | |
693 | void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) |
694 | { |
695 | mState.scissorX = x; |
696 | mState.scissorY = y; |
697 | |
698 | // An overflow happens when (infinite precision) X + Width > INT32_MAX. We |
699 | // can change that formula to "X > INT32_MAX - Width". And when we bring it |
700 | // down to 32-bit precision, we know it's safe because width is non-negative. |
701 | if (x > INT32_MAX - width) |
702 | { |
703 | width = INT32_MAX - x; |
704 | } |
705 | |
706 | if (y > INT32_MAX - height) |
707 | { |
708 | height = INT32_MAX - y; |
709 | } |
710 | |
711 | mState.scissorWidth = width; |
712 | mState.scissorHeight = height; |
713 | } |
714 | |
715 | void Context::setColorMask(bool red, bool green, bool blue, bool alpha) |
716 | { |
717 | if(mState.colorMaskRed != red || mState.colorMaskGreen != green || |
718 | mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha) |
719 | { |
720 | mState.colorMaskRed = red; |
721 | mState.colorMaskGreen = green; |
722 | mState.colorMaskBlue = blue; |
723 | mState.colorMaskAlpha = alpha; |
724 | mMaskStateDirty = true; |
725 | } |
726 | } |
727 | |
728 | unsigned int Context::getColorMask() const |
729 | { |
730 | return (mState.colorMaskRed ? 0x1 : 0) | |
731 | (mState.colorMaskGreen ? 0x2 : 0) | |
732 | (mState.colorMaskBlue ? 0x4 : 0) | |
733 | (mState.colorMaskAlpha ? 0x8 : 0); |
734 | } |
735 | |
736 | void Context::setDepthMask(bool mask) |
737 | { |
738 | if(mState.depthMask != mask) |
739 | { |
740 | mState.depthMask = mask; |
741 | mMaskStateDirty = true; |
742 | } |
743 | } |
744 | |
745 | void Context::setActiveSampler(unsigned int active) |
746 | { |
747 | mState.activeSampler = active; |
748 | } |
749 | |
750 | GLuint Context::getReadFramebufferName() const |
751 | { |
752 | return mState.readFramebuffer; |
753 | } |
754 | |
755 | GLuint Context::getDrawFramebufferName() const |
756 | { |
757 | return mState.drawFramebuffer; |
758 | } |
759 | |
760 | GLuint Context::getRenderbufferName() const |
761 | { |
762 | return mState.renderbuffer.name(); |
763 | } |
764 | |
765 | void Context::setFramebufferReadBuffer(GLuint buf) |
766 | { |
767 | Framebuffer *framebuffer = getReadFramebuffer(); |
768 | |
769 | if(framebuffer) |
770 | { |
771 | framebuffer->setReadBuffer(buf); |
772 | } |
773 | else |
774 | { |
775 | return error(GL_INVALID_OPERATION); |
776 | } |
777 | } |
778 | |
779 | void Context::setFramebufferDrawBuffers(GLsizei n, const GLenum *bufs) |
780 | { |
781 | Framebuffer *drawFramebuffer = getDrawFramebuffer(); |
782 | |
783 | if(drawFramebuffer) |
784 | { |
785 | for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++) |
786 | { |
787 | drawFramebuffer->setDrawBuffer(i, (i < n) ? bufs[i] : GL_NONE); |
788 | } |
789 | } |
790 | else |
791 | { |
792 | return error(GL_INVALID_OPERATION); |
793 | } |
794 | } |
795 | |
796 | GLuint Context::getArrayBufferName() const |
797 | { |
798 | return mState.arrayBuffer.name(); |
799 | } |
800 | |
801 | GLuint Context::getElementArrayBufferName() const |
802 | { |
803 | Buffer* elementArrayBuffer = getCurrentVertexArray()->getElementArrayBuffer(); |
804 | return elementArrayBuffer ? elementArrayBuffer->name : 0; |
805 | } |
806 | |
807 | GLuint Context::getActiveQuery(GLenum target) const |
808 | { |
809 | Query *queryObject = nullptr; |
810 | |
811 | switch(target) |
812 | { |
813 | case GL_ANY_SAMPLES_PASSED_EXT: |
814 | queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED]; |
815 | break; |
816 | case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: |
817 | queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE]; |
818 | break; |
819 | case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: |
820 | queryObject = mState.activeQuery[QUERY_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN]; |
821 | break; |
822 | default: |
823 | ASSERT(false); |
824 | } |
825 | |
826 | if(queryObject) |
827 | { |
828 | return queryObject->name; |
829 | } |
830 | |
831 | return 0; |
832 | } |
833 | |
834 | void Context::setVertexAttribArrayEnabled(unsigned int attribNum, bool enabled) |
835 | { |
836 | getCurrentVertexArray()->enableAttribute(attribNum, enabled); |
837 | } |
838 | |
839 | void Context::setVertexAttribDivisor(unsigned int attribNum, GLuint divisor) |
840 | { |
841 | getCurrentVertexArray()->setVertexAttribDivisor(attribNum, divisor); |
842 | } |
843 | |
844 | const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) const |
845 | { |
846 | return getCurrentVertexArray()->getVertexAttribute(attribNum); |
847 | } |
848 | |
849 | void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, |
850 | bool normalized, bool pureInteger, GLsizei stride, const void *pointer) |
851 | { |
852 | getCurrentVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); |
853 | } |
854 | |
855 | const void *Context::getVertexAttribPointer(unsigned int attribNum) const |
856 | { |
857 | return getCurrentVertexArray()->getVertexAttribute(attribNum).mPointer; |
858 | } |
859 | |
860 | const VertexAttributeArray &Context::getVertexArrayAttributes() |
861 | { |
862 | return getCurrentVertexArray()->getVertexAttributes(); |
863 | } |
864 | |
865 | const VertexAttributeArray &Context::getCurrentVertexAttributes() |
866 | { |
867 | return mState.vertexAttribute; |
868 | } |
869 | |
870 | void Context::setPackAlignment(GLint alignment) |
871 | { |
872 | mState.packParameters.alignment = alignment; |
873 | } |
874 | |
875 | void Context::setUnpackAlignment(GLint alignment) |
876 | { |
877 | mState.unpackParameters.alignment = alignment; |
878 | } |
879 | |
880 | const gl::PixelStorageModes &Context::getUnpackParameters() const |
881 | { |
882 | return mState.unpackParameters; |
883 | } |
884 | |
885 | void Context::setPackRowLength(GLint rowLength) |
886 | { |
887 | mState.packParameters.rowLength = rowLength; |
888 | } |
889 | |
890 | void Context::setPackSkipPixels(GLint skipPixels) |
891 | { |
892 | mState.packParameters.skipPixels = skipPixels; |
893 | } |
894 | |
895 | void Context::setPackSkipRows(GLint skipRows) |
896 | { |
897 | mState.packParameters.skipRows = skipRows; |
898 | } |
899 | |
900 | void Context::setUnpackRowLength(GLint rowLength) |
901 | { |
902 | mState.unpackParameters.rowLength = rowLength; |
903 | } |
904 | |
905 | void Context::setUnpackImageHeight(GLint imageHeight) |
906 | { |
907 | mState.unpackParameters.imageHeight = imageHeight; |
908 | } |
909 | |
910 | void Context::setUnpackSkipPixels(GLint skipPixels) |
911 | { |
912 | mState.unpackParameters.skipPixels = skipPixels; |
913 | } |
914 | |
915 | void Context::setUnpackSkipRows(GLint skipRows) |
916 | { |
917 | mState.unpackParameters.skipRows = skipRows; |
918 | } |
919 | |
920 | void Context::setUnpackSkipImages(GLint skipImages) |
921 | { |
922 | mState.unpackParameters.skipImages = skipImages; |
923 | } |
924 | |
925 | GLuint Context::createBuffer() |
926 | { |
927 | return mResourceManager->createBuffer(); |
928 | } |
929 | |
930 | GLuint Context::createProgram() |
931 | { |
932 | return mResourceManager->createProgram(); |
933 | } |
934 | |
935 | GLuint Context::createShader(GLenum type) |
936 | { |
937 | return mResourceManager->createShader(type); |
938 | } |
939 | |
940 | GLuint Context::createTexture() |
941 | { |
942 | return mResourceManager->createTexture(); |
943 | } |
944 | |
945 | GLuint Context::createRenderbuffer() |
946 | { |
947 | return mResourceManager->createRenderbuffer(); |
948 | } |
949 | |
950 | // Returns an unused framebuffer name |
951 | GLuint Context::createFramebuffer() |
952 | { |
953 | return mFramebufferNameSpace.allocate(); |
954 | } |
955 | |
956 | GLuint Context::createFence() |
957 | { |
958 | return mFenceNameSpace.allocate(new Fence()); |
959 | } |
960 | |
961 | // Returns an unused query name |
962 | GLuint Context::createQuery() |
963 | { |
964 | return mQueryNameSpace.allocate(); |
965 | } |
966 | |
967 | // Returns an unused vertex array name |
968 | GLuint Context::createVertexArray() |
969 | { |
970 | return mVertexArrayNameSpace.allocate(); |
971 | } |
972 | |
973 | GLsync Context::createFenceSync(GLenum condition, GLbitfield flags) |
974 | { |
975 | GLuint handle = mResourceManager->createFenceSync(condition, flags); |
976 | |
977 | return reinterpret_cast<GLsync>(static_cast<uintptr_t>(handle)); |
978 | } |
979 | |
980 | // Returns an unused transform feedback name |
981 | GLuint Context::createTransformFeedback() |
982 | { |
983 | return mTransformFeedbackNameSpace.allocate(); |
984 | } |
985 | |
986 | // Returns an unused sampler name |
987 | GLuint Context::createSampler() |
988 | { |
989 | return mResourceManager->createSampler(); |
990 | } |
991 | |
992 | void Context::deleteBuffer(GLuint buffer) |
993 | { |
994 | detachBuffer(buffer); |
995 | |
996 | mResourceManager->deleteBuffer(buffer); |
997 | } |
998 | |
999 | void Context::deleteShader(GLuint shader) |
1000 | { |
1001 | mResourceManager->deleteShader(shader); |
1002 | } |
1003 | |
1004 | void Context::deleteProgram(GLuint program) |
1005 | { |
1006 | mResourceManager->deleteProgram(program); |
1007 | } |
1008 | |
1009 | void Context::deleteTexture(GLuint texture) |
1010 | { |
1011 | detachTexture(texture); |
1012 | |
1013 | mResourceManager->deleteTexture(texture); |
1014 | } |
1015 | |
1016 | void Context::deleteRenderbuffer(GLuint renderbuffer) |
1017 | { |
1018 | if(mResourceManager->getRenderbuffer(renderbuffer)) |
1019 | { |
1020 | detachRenderbuffer(renderbuffer); |
1021 | } |
1022 | |
1023 | mResourceManager->deleteRenderbuffer(renderbuffer); |
1024 | } |
1025 | |
1026 | void Context::deleteFramebuffer(GLuint framebuffer) |
1027 | { |
1028 | detachFramebuffer(framebuffer); |
1029 | |
1030 | Framebuffer *framebufferObject = mFramebufferNameSpace.remove(framebuffer); |
1031 | |
1032 | if(framebufferObject) |
1033 | { |
1034 | delete framebufferObject; |
1035 | } |
1036 | } |
1037 | |
1038 | void Context::deleteFence(GLuint fence) |
1039 | { |
1040 | Fence *fenceObject = mFenceNameSpace.remove(fence); |
1041 | |
1042 | if(fenceObject) |
1043 | { |
1044 | delete fenceObject; |
1045 | } |
1046 | } |
1047 | |
1048 | void Context::deleteQuery(GLuint query) |
1049 | { |
1050 | Query *queryObject = mQueryNameSpace.remove(query); |
1051 | |
1052 | if(queryObject) |
1053 | { |
1054 | queryObject->release(); |
1055 | } |
1056 | } |
1057 | |
1058 | void Context::deleteVertexArray(GLuint vertexArray) |
1059 | { |
1060 | // [OpenGL ES 3.0.2] section 2.10 page 43: |
1061 | // If a vertex array object that is currently bound is deleted, the binding |
1062 | // for that object reverts to zero and the default vertex array becomes current. |
1063 | if(getCurrentVertexArray()->name == vertexArray) |
1064 | { |
1065 | bindVertexArray(0); |
1066 | } |
1067 | |
1068 | VertexArray *vertexArrayObject = mVertexArrayNameSpace.remove(vertexArray); |
1069 | |
1070 | if(vertexArrayObject) |
1071 | { |
1072 | delete vertexArrayObject; |
1073 | } |
1074 | } |
1075 | |
1076 | void Context::deleteFenceSync(GLsync fenceSync) |
1077 | { |
1078 | // The spec specifies the underlying Fence object is not deleted until all current |
1079 | // wait commands finish. However, since the name becomes invalid, we cannot query the fence, |
1080 | // and since our API is currently designed for being called from a single thread, we can delete |
1081 | // the fence immediately. |
1082 | mResourceManager->deleteFenceSync(static_cast<GLuint>(reinterpret_cast<uintptr_t>(fenceSync))); |
1083 | } |
1084 | |
1085 | void Context::deleteTransformFeedback(GLuint transformFeedback) |
1086 | { |
1087 | TransformFeedback *transformFeedbackObject = mTransformFeedbackNameSpace.remove(transformFeedback); |
1088 | |
1089 | // Detach if currently bound. |
1090 | if(mState.transformFeedback == transformFeedback) |
1091 | { |
1092 | mState.transformFeedback = 0; |
1093 | } |
1094 | |
1095 | if(transformFeedbackObject) |
1096 | { |
1097 | delete transformFeedbackObject; |
1098 | } |
1099 | } |
1100 | |
1101 | void Context::deleteSampler(GLuint sampler) |
1102 | { |
1103 | detachSampler(sampler); |
1104 | |
1105 | mResourceManager->deleteSampler(sampler); |
1106 | } |
1107 | |
1108 | Buffer *Context::getBuffer(GLuint handle) const |
1109 | { |
1110 | return mResourceManager->getBuffer(handle); |
1111 | } |
1112 | |
1113 | Shader *Context::getShader(GLuint handle) const |
1114 | { |
1115 | return mResourceManager->getShader(handle); |
1116 | } |
1117 | |
1118 | Program *Context::getProgram(GLuint handle) const |
1119 | { |
1120 | return mResourceManager->getProgram(handle); |
1121 | } |
1122 | |
1123 | Texture *Context::getTexture(GLuint handle) const |
1124 | { |
1125 | return mResourceManager->getTexture(handle); |
1126 | } |
1127 | |
1128 | Renderbuffer *Context::getRenderbuffer(GLuint handle) const |
1129 | { |
1130 | return mResourceManager->getRenderbuffer(handle); |
1131 | } |
1132 | |
1133 | Framebuffer *Context::getReadFramebuffer() const |
1134 | { |
1135 | return getFramebuffer(mState.readFramebuffer); |
1136 | } |
1137 | |
1138 | Framebuffer *Context::getDrawFramebuffer() const |
1139 | { |
1140 | return getFramebuffer(mState.drawFramebuffer); |
1141 | } |
1142 | |
1143 | void Context::bindArrayBuffer(unsigned int buffer) |
1144 | { |
1145 | mResourceManager->checkBufferAllocation(buffer); |
1146 | |
1147 | mState.arrayBuffer = getBuffer(buffer); |
1148 | } |
1149 | |
1150 | void Context::bindElementArrayBuffer(unsigned int buffer) |
1151 | { |
1152 | mResourceManager->checkBufferAllocation(buffer); |
1153 | |
1154 | getCurrentVertexArray()->setElementArrayBuffer(getBuffer(buffer)); |
1155 | } |
1156 | |
1157 | void Context::bindCopyReadBuffer(GLuint buffer) |
1158 | { |
1159 | mResourceManager->checkBufferAllocation(buffer); |
1160 | |
1161 | mState.copyReadBuffer = getBuffer(buffer); |
1162 | } |
1163 | |
1164 | void Context::bindCopyWriteBuffer(GLuint buffer) |
1165 | { |
1166 | mResourceManager->checkBufferAllocation(buffer); |
1167 | |
1168 | mState.copyWriteBuffer = getBuffer(buffer); |
1169 | } |
1170 | |
1171 | void Context::bindPixelPackBuffer(GLuint buffer) |
1172 | { |
1173 | mResourceManager->checkBufferAllocation(buffer); |
1174 | |
1175 | mState.pixelPackBuffer = getBuffer(buffer); |
1176 | } |
1177 | |
1178 | void Context::bindPixelUnpackBuffer(GLuint buffer) |
1179 | { |
1180 | mResourceManager->checkBufferAllocation(buffer); |
1181 | |
1182 | mState.pixelUnpackBuffer = getBuffer(buffer); |
1183 | } |
1184 | |
1185 | void Context::bindTransformFeedbackBuffer(GLuint buffer) |
1186 | { |
1187 | mResourceManager->checkBufferAllocation(buffer); |
1188 | |
1189 | mState.genericTransformFeedbackBuffer = getBuffer(buffer); |
1190 | } |
1191 | |
1192 | void Context::bindTexture(TextureType type, GLuint texture) |
1193 | { |
1194 | mResourceManager->checkTextureAllocation(texture, type); |
1195 | |
1196 | mState.samplerTexture[type][mState.activeSampler] = getTexture(texture); |
1197 | } |
1198 | |
1199 | void Context::bindReadFramebuffer(GLuint framebuffer) |
1200 | { |
1201 | if(!getFramebuffer(framebuffer)) |
1202 | { |
1203 | if(framebuffer == 0) |
1204 | { |
1205 | mFramebufferNameSpace.insert(framebuffer, new DefaultFramebuffer()); |
1206 | } |
1207 | else |
1208 | { |
1209 | mFramebufferNameSpace.insert(framebuffer, new Framebuffer()); |
1210 | } |
1211 | } |
1212 | |
1213 | mState.readFramebuffer = framebuffer; |
1214 | } |
1215 | |
1216 | void Context::bindDrawFramebuffer(GLuint framebuffer) |
1217 | { |
1218 | if(!getFramebuffer(framebuffer)) |
1219 | { |
1220 | if(framebuffer == 0) |
1221 | { |
1222 | mFramebufferNameSpace.insert(framebuffer, new DefaultFramebuffer()); |
1223 | } |
1224 | else |
1225 | { |
1226 | mFramebufferNameSpace.insert(framebuffer, new Framebuffer()); |
1227 | } |
1228 | } |
1229 | |
1230 | mState.drawFramebuffer = framebuffer; |
1231 | } |
1232 | |
1233 | void Context::bindRenderbuffer(GLuint renderbuffer) |
1234 | { |
1235 | mResourceManager->checkRenderbufferAllocation(renderbuffer); |
1236 | |
1237 | mState.renderbuffer = getRenderbuffer(renderbuffer); |
1238 | } |
1239 | |
1240 | void Context::bindVertexArray(GLuint array) |
1241 | { |
1242 | VertexArray *vertexArray = getVertexArray(array); |
1243 | |
1244 | if(!vertexArray) |
1245 | { |
1246 | vertexArray = new VertexArray(array); |
1247 | mVertexArrayNameSpace.insert(array, vertexArray); |
1248 | } |
1249 | |
1250 | mState.vertexArray = array; |
1251 | } |
1252 | |
1253 | void Context::bindGenericUniformBuffer(GLuint buffer) |
1254 | { |
1255 | mResourceManager->checkBufferAllocation(buffer); |
1256 | |
1257 | mState.genericUniformBuffer = getBuffer(buffer); |
1258 | } |
1259 | |
1260 | void Context::bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) |
1261 | { |
1262 | mResourceManager->checkBufferAllocation(buffer); |
1263 | |
1264 | Buffer* bufferObject = getBuffer(buffer); |
1265 | mState.uniformBuffers[index].set(bufferObject, static_cast<int>(offset), static_cast<int>(size)); |
1266 | } |
1267 | |
1268 | void Context::bindGenericTransformFeedbackBuffer(GLuint buffer) |
1269 | { |
1270 | mResourceManager->checkBufferAllocation(buffer); |
1271 | |
1272 | mState.genericTransformFeedbackBuffer = getBuffer(buffer); |
1273 | } |
1274 | |
1275 | void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) |
1276 | { |
1277 | mResourceManager->checkBufferAllocation(buffer); |
1278 | |
1279 | Buffer* bufferObject = getBuffer(buffer); |
1280 | getTransformFeedback()->setBuffer(index, bufferObject, offset, size); |
1281 | mState.genericTransformFeedbackBuffer = bufferObject; |
1282 | } |
1283 | |
1284 | void Context::bindTransformFeedback(GLuint id) |
1285 | { |
1286 | if(!getTransformFeedback(id)) |
1287 | { |
1288 | mTransformFeedbackNameSpace.insert(id, new TransformFeedback(id)); |
1289 | } |
1290 | |
1291 | mState.transformFeedback = id; |
1292 | } |
1293 | |
1294 | bool Context::bindSampler(GLuint unit, GLuint sampler) |
1295 | { |
1296 | mResourceManager->checkSamplerAllocation(sampler); |
1297 | |
1298 | Sampler* samplerObject = getSampler(sampler); |
1299 | |
1300 | mState.sampler[unit] = samplerObject; |
1301 | |
1302 | return !!samplerObject; |
1303 | } |
1304 | |
1305 | void Context::useProgram(GLuint program) |
1306 | { |
1307 | GLuint priorProgram = mState.currentProgram; |
1308 | mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged. |
1309 | |
1310 | if(priorProgram != program) |
1311 | { |
1312 | Program *newProgram = mResourceManager->getProgram(program); |
1313 | Program *oldProgram = mResourceManager->getProgram(priorProgram); |
1314 | |
1315 | if(newProgram) |
1316 | { |
1317 | newProgram->addRef(); |
1318 | } |
1319 | |
1320 | if(oldProgram) |
1321 | { |
1322 | oldProgram->release(); |
1323 | } |
1324 | } |
1325 | } |
1326 | |
1327 | void Context::beginQuery(GLenum target, GLuint query) |
1328 | { |
1329 | // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id> |
1330 | // of zero, if the active query object name for <target> is non-zero (for the |
1331 | // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if |
1332 | // the active query for either target is non-zero), if <id> is the name of an |
1333 | // existing query object whose type does not match <target>, or if <id> is the |
1334 | // active query object name for any query type, the error INVALID_OPERATION is |
1335 | // generated. |
1336 | |
1337 | // Ensure no other queries are active |
1338 | // NOTE: If other queries than occlusion are supported, we will need to check |
1339 | // separately that: |
1340 | // a) The query ID passed is not the current active query for any target/type |
1341 | // b) There are no active queries for the requested target (and in the case |
1342 | // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, |
1343 | // no query may be active for either if glBeginQuery targets either. |
1344 | for(int i = 0; i < QUERY_TYPE_COUNT; i++) |
1345 | { |
1346 | if(mState.activeQuery[i]) |
1347 | { |
1348 | switch(mState.activeQuery[i]->getType()) |
1349 | { |
1350 | case GL_ANY_SAMPLES_PASSED_EXT: |
1351 | case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: |
1352 | if((target == GL_ANY_SAMPLES_PASSED_EXT) || |
1353 | (target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT)) |
1354 | { |
1355 | return error(GL_INVALID_OPERATION); |
1356 | } |
1357 | break; |
1358 | case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: |
1359 | if(target == GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) |
1360 | { |
1361 | return error(GL_INVALID_OPERATION); |
1362 | } |
1363 | break; |
1364 | default: |
1365 | break; |
1366 | } |
1367 | } |
1368 | } |
1369 | |
1370 | QueryType qType; |
1371 | switch(target) |
1372 | { |
1373 | case GL_ANY_SAMPLES_PASSED_EXT: |
1374 | qType = QUERY_ANY_SAMPLES_PASSED; |
1375 | break; |
1376 | case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: |
1377 | qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; |
1378 | break; |
1379 | case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: |
1380 | qType = QUERY_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN; |
1381 | break; |
1382 | default: |
1383 | UNREACHABLE(target); |
1384 | return error(GL_INVALID_ENUM); |
1385 | } |
1386 | |
1387 | Query *queryObject = createQuery(query, target); |
1388 | |
1389 | // Check that name was obtained with glGenQueries |
1390 | if(!queryObject) |
1391 | { |
1392 | return error(GL_INVALID_OPERATION); |
1393 | } |
1394 | |
1395 | // Check for type mismatch |
1396 | if(queryObject->getType() != target) |
1397 | { |
1398 | return error(GL_INVALID_OPERATION); |
1399 | } |
1400 | |
1401 | // Set query as active for specified target |
1402 | mState.activeQuery[qType] = queryObject; |
1403 | |
1404 | // Begin query |
1405 | queryObject->begin(); |
1406 | } |
1407 | |
1408 | void Context::endQuery(GLenum target) |
1409 | { |
1410 | QueryType qType; |
1411 | |
1412 | switch(target) |
1413 | { |
1414 | case GL_ANY_SAMPLES_PASSED_EXT: qType = QUERY_ANY_SAMPLES_PASSED; break; |
1415 | case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; break; |
1416 | case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: qType = QUERY_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN; break; |
1417 | default: UNREACHABLE(target); return; |
1418 | } |
1419 | |
1420 | Query *queryObject = mState.activeQuery[qType]; |
1421 | |
1422 | if(!queryObject) |
1423 | { |
1424 | return error(GL_INVALID_OPERATION); |
1425 | } |
1426 | |
1427 | queryObject->end(); |
1428 | |
1429 | mState.activeQuery[qType] = nullptr; |
1430 | } |
1431 | |
1432 | void Context::setFramebufferZero(Framebuffer *buffer) |
1433 | { |
1434 | delete mFramebufferNameSpace.remove(0); |
1435 | mFramebufferNameSpace.insert(0, buffer); |
1436 | } |
1437 | |
1438 | void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer) |
1439 | { |
1440 | Renderbuffer *renderbufferObject = mState.renderbuffer; |
1441 | renderbufferObject->setStorage(renderbuffer); |
1442 | } |
1443 | |
1444 | Framebuffer *Context::getFramebuffer(unsigned int handle) const |
1445 | { |
1446 | return mFramebufferNameSpace.find(handle); |
1447 | } |
1448 | |
1449 | Fence *Context::getFence(unsigned int handle) const |
1450 | { |
1451 | return mFenceNameSpace.find(handle); |
1452 | } |
1453 | |
1454 | FenceSync *Context::getFenceSync(GLsync handle) const |
1455 | { |
1456 | return mResourceManager->getFenceSync(static_cast<GLuint>(reinterpret_cast<uintptr_t>(handle))); |
1457 | } |
1458 | |
1459 | Query *Context::getQuery(unsigned int handle) const |
1460 | { |
1461 | return mQueryNameSpace.find(handle); |
1462 | } |
1463 | |
1464 | Query *Context::createQuery(unsigned int handle, GLenum type) |
1465 | { |
1466 | if(!mQueryNameSpace.isReserved(handle)) |
1467 | { |
1468 | return nullptr; |
1469 | } |
1470 | else |
1471 | { |
1472 | Query *query = mQueryNameSpace.find(handle); |
1473 | if(!query) |
1474 | { |
1475 | query = new Query(handle, type); |
1476 | query->addRef(); |
1477 | mQueryNameSpace.insert(handle, query); |
1478 | } |
1479 | |
1480 | return query; |
1481 | } |
1482 | } |
1483 | |
1484 | VertexArray *Context::getVertexArray(GLuint array) const |
1485 | { |
1486 | return mVertexArrayNameSpace.find(array); |
1487 | } |
1488 | |
1489 | VertexArray *Context::getCurrentVertexArray() const |
1490 | { |
1491 | return getVertexArray(mState.vertexArray); |
1492 | } |
1493 | |
1494 | bool Context::isVertexArray(GLuint array) const |
1495 | { |
1496 | return mVertexArrayNameSpace.isReserved(array); |
1497 | } |
1498 | |
1499 | bool Context::hasZeroDivisor() const |
1500 | { |
1501 | // Verify there is at least one active attribute with a divisor of zero |
1502 | es2::Program *programObject = getCurrentProgram(); |
1503 | for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) |
1504 | { |
1505 | bool active = (programObject->getAttributeStream(attributeIndex) != -1); |
1506 | if(active && getCurrentVertexArray()->getVertexAttribute(attributeIndex).mDivisor == 0) |
1507 | { |
1508 | return true; |
1509 | } |
1510 | } |
1511 | |
1512 | return false; |
1513 | } |
1514 | |
1515 | TransformFeedback *Context::getTransformFeedback(GLuint transformFeedback) const |
1516 | { |
1517 | return mTransformFeedbackNameSpace.find(transformFeedback); |
1518 | } |
1519 | |
1520 | bool Context::isTransformFeedback(GLuint array) const |
1521 | { |
1522 | return mTransformFeedbackNameSpace.isReserved(array); |
1523 | } |
1524 | |
1525 | Sampler *Context::getSampler(GLuint sampler) const |
1526 | { |
1527 | return mResourceManager->getSampler(sampler); |
1528 | } |
1529 | |
1530 | bool Context::isSampler(GLuint sampler) const |
1531 | { |
1532 | return mResourceManager->isSampler(sampler); |
1533 | } |
1534 | |
1535 | Buffer *Context::getArrayBuffer() const |
1536 | { |
1537 | return mState.arrayBuffer; |
1538 | } |
1539 | |
1540 | Buffer *Context::getElementArrayBuffer() const |
1541 | { |
1542 | return getCurrentVertexArray()->getElementArrayBuffer(); |
1543 | } |
1544 | |
1545 | Buffer *Context::getCopyReadBuffer() const |
1546 | { |
1547 | return mState.copyReadBuffer; |
1548 | } |
1549 | |
1550 | Buffer *Context::getCopyWriteBuffer() const |
1551 | { |
1552 | return mState.copyWriteBuffer; |
1553 | } |
1554 | |
1555 | Buffer *Context::getPixelPackBuffer() const |
1556 | { |
1557 | return mState.pixelPackBuffer; |
1558 | } |
1559 | |
1560 | Buffer *Context::getPixelUnpackBuffer() const |
1561 | { |
1562 | return mState.pixelUnpackBuffer; |
1563 | } |
1564 | |
1565 | Buffer *Context::getGenericUniformBuffer() const |
1566 | { |
1567 | return mState.genericUniformBuffer; |
1568 | } |
1569 | |
1570 | // The "required buffer size" is the number of bytes from the start of the |
1571 | // buffer to the last byte referenced within the buffer. If the caller of this |
1572 | // function has to worry about offsets within the buffer, it only needs to add |
1573 | // that byte offset to this function's return value to get its required buffer |
1574 | // size. |
1575 | size_t Context::getRequiredBufferSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type) const |
1576 | { |
1577 | // 0-dimensional images have no bytes in them. |
1578 | if (width == 0 || height == 0 || depth == 0) |
1579 | { |
1580 | return 0; |
1581 | } |
1582 | |
1583 | GLint pixelsPerRow = (mState.unpackParameters.rowLength) > 0 ? mState.unpackParameters.rowLength : width; |
1584 | GLint rowsPerImage = (mState.unpackParameters.imageHeight) > 0 ? mState.unpackParameters.imageHeight : height; |
1585 | |
1586 | GLint bytesPerPixel = gl::ComputePixelSize(format, type); |
1587 | GLint bytesPerRow = gl::ComputePitch(pixelsPerRow, format, type, mState.unpackParameters.alignment); |
1588 | GLint bytesPerImage = rowsPerImage * bytesPerRow; |
1589 | |
1590 | // Depth and height are subtracted by 1, while width is not, because we're not |
1591 | // reading the full last row or image, but we are reading the full last pixel. |
1592 | return (mState.unpackParameters.skipImages + (depth - 1)) * bytesPerImage |
1593 | + (mState.unpackParameters.skipRows + (height - 1)) * bytesPerRow |
1594 | + (mState.unpackParameters.skipPixels + (width)) * bytesPerPixel; |
1595 | } |
1596 | |
1597 | GLenum Context::getPixels(const GLvoid **pixels, GLenum type, size_t imageSize) const |
1598 | { |
1599 | if(mState.pixelUnpackBuffer) |
1600 | { |
1601 | ASSERT(mState.pixelUnpackBuffer->name != 0); |
1602 | |
1603 | if(mState.pixelUnpackBuffer->isMapped()) |
1604 | { |
1605 | return GL_INVALID_OPERATION; |
1606 | } |
1607 | |
1608 | size_t offset = static_cast<size_t>((ptrdiff_t)(*pixels)); |
1609 | |
1610 | if(offset % GetTypeSize(type) != 0) |
1611 | { |
1612 | return GL_INVALID_OPERATION; |
1613 | } |
1614 | |
1615 | if(offset > mState.pixelUnpackBuffer->size()) |
1616 | { |
1617 | return GL_INVALID_OPERATION; |
1618 | } |
1619 | |
1620 | if(mState.pixelUnpackBuffer->size() - offset < imageSize) |
1621 | { |
1622 | return GL_INVALID_OPERATION; |
1623 | } |
1624 | |
1625 | *pixels = static_cast<const unsigned char*>(mState.pixelUnpackBuffer->data()) + offset; |
1626 | } |
1627 | |
1628 | return GL_NO_ERROR; |
1629 | } |
1630 | |
1631 | bool Context::getBuffer(GLenum target, es2::Buffer **buffer) const |
1632 | { |
1633 | switch(target) |
1634 | { |
1635 | case GL_ARRAY_BUFFER: |
1636 | *buffer = getArrayBuffer(); |
1637 | break; |
1638 | case GL_ELEMENT_ARRAY_BUFFER: |
1639 | *buffer = getElementArrayBuffer(); |
1640 | break; |
1641 | case GL_COPY_READ_BUFFER: |
1642 | *buffer = getCopyReadBuffer(); |
1643 | break; |
1644 | case GL_COPY_WRITE_BUFFER: |
1645 | *buffer = getCopyWriteBuffer(); |
1646 | break; |
1647 | case GL_PIXEL_PACK_BUFFER: |
1648 | *buffer = getPixelPackBuffer(); |
1649 | break; |
1650 | case GL_PIXEL_UNPACK_BUFFER: |
1651 | *buffer = getPixelUnpackBuffer(); |
1652 | break; |
1653 | case GL_TRANSFORM_FEEDBACK_BUFFER: |
1654 | *buffer = static_cast<es2::Buffer*>(mState.genericTransformFeedbackBuffer); |
1655 | break; |
1656 | case GL_UNIFORM_BUFFER: |
1657 | *buffer = getGenericUniformBuffer(); |
1658 | break; |
1659 | default: |
1660 | return false; |
1661 | } |
1662 | return true; |
1663 | } |
1664 | |
1665 | TransformFeedback *Context::getTransformFeedback() const |
1666 | { |
1667 | return getTransformFeedback(mState.transformFeedback); |
1668 | } |
1669 | |
1670 | Program *Context::getCurrentProgram() const |
1671 | { |
1672 | return mResourceManager->getProgram(mState.currentProgram); |
1673 | } |
1674 | |
1675 | Texture *Context::getTargetTexture(GLenum target) const |
1676 | { |
1677 | Texture *texture = nullptr; |
1678 | |
1679 | switch(target) |
1680 | { |
1681 | case GL_TEXTURE_2D: texture = getTexture2D(); break; |
1682 | case GL_TEXTURE_2D_ARRAY: texture = getTexture2DArray(); break; |
1683 | case GL_TEXTURE_3D: texture = getTexture3D(); break; |
1684 | case GL_TEXTURE_CUBE_MAP: texture = getTextureCubeMap(); break; |
1685 | case GL_TEXTURE_EXTERNAL_OES: texture = getTextureExternal(); break; |
1686 | case GL_TEXTURE_RECTANGLE_ARB: texture = getTexture2DRect(); break; |
1687 | default: |
1688 | return error(GL_INVALID_ENUM, nullptr); |
1689 | } |
1690 | |
1691 | ASSERT(texture); // Must always have a default texture to fall back to. |
1692 | |
1693 | return texture; |
1694 | } |
1695 | |
1696 | Texture2D *Context::getTexture2D() const |
1697 | { |
1698 | return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D)); |
1699 | } |
1700 | |
1701 | Texture2D *Context::getTexture2D(GLenum target) const |
1702 | { |
1703 | switch(target) |
1704 | { |
1705 | case GL_TEXTURE_2D: return getTexture2D(); |
1706 | case GL_TEXTURE_RECTANGLE_ARB: return getTexture2DRect(); |
1707 | case GL_TEXTURE_EXTERNAL_OES: return getTextureExternal(); |
1708 | default: UNREACHABLE(target); |
1709 | } |
1710 | |
1711 | return nullptr; |
1712 | } |
1713 | |
1714 | Texture3D *Context::getTexture3D() const |
1715 | { |
1716 | return static_cast<Texture3D*>(getSamplerTexture(mState.activeSampler, TEXTURE_3D)); |
1717 | } |
1718 | |
1719 | Texture2DArray *Context::getTexture2DArray() const |
1720 | { |
1721 | return static_cast<Texture2DArray*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D_ARRAY)); |
1722 | } |
1723 | |
1724 | TextureCubeMap *Context::getTextureCubeMap() const |
1725 | { |
1726 | return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE)); |
1727 | } |
1728 | |
1729 | Texture2DRect *Context::getTexture2DRect() const |
1730 | { |
1731 | return static_cast<Texture2DRect*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D_RECT)); |
1732 | } |
1733 | |
1734 | TextureExternal *Context::getTextureExternal() const |
1735 | { |
1736 | return static_cast<TextureExternal*>(getSamplerTexture(mState.activeSampler, TEXTURE_EXTERNAL)); |
1737 | } |
1738 | |
1739 | Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) const |
1740 | { |
1741 | GLuint texid = mState.samplerTexture[type][sampler].name(); |
1742 | |
1743 | if(texid == 0) // Special case: 0 refers to different initial textures based on the target |
1744 | { |
1745 | switch(type) |
1746 | { |
1747 | case TEXTURE_2D: return mTexture2DZero; |
1748 | case TEXTURE_3D: return mTexture3DZero; |
1749 | case TEXTURE_2D_ARRAY: return mTexture2DArrayZero; |
1750 | case TEXTURE_CUBE: return mTextureCubeMapZero; |
1751 | case TEXTURE_2D_RECT: return mTexture2DRectZero; |
1752 | case TEXTURE_EXTERNAL: return mTextureExternalZero; |
1753 | default: UNREACHABLE(type); |
1754 | } |
1755 | } |
1756 | |
1757 | return mState.samplerTexture[type][sampler]; |
1758 | } |
1759 | |
1760 | void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) |
1761 | { |
1762 | mResourceManager->checkSamplerAllocation(sampler); |
1763 | |
1764 | Sampler *samplerObject = getSampler(sampler); |
1765 | ASSERT(samplerObject); |
1766 | |
1767 | switch(pname) |
1768 | { |
1769 | case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast<GLenum>(param)); break; |
1770 | case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast<GLenum>(param)); break; |
1771 | case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast<GLenum>(param)); break; |
1772 | case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast<GLenum>(param)); break; |
1773 | case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast<GLenum>(param)); break; |
1774 | case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(static_cast<GLfloat>(param)); break; |
1775 | case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(static_cast<GLfloat>(param)); break; |
1776 | case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(static_cast<GLenum>(param)); break; |
1777 | case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(static_cast<GLenum>(param)); break; |
1778 | case GL_TEXTURE_MAX_ANISOTROPY_EXT: samplerObject->setMaxAnisotropy(static_cast<GLfloat>(param)); break; |
1779 | default: UNREACHABLE(pname); break; |
1780 | } |
1781 | } |
1782 | |
1783 | void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param) |
1784 | { |
1785 | mResourceManager->checkSamplerAllocation(sampler); |
1786 | |
1787 | Sampler *samplerObject = getSampler(sampler); |
1788 | ASSERT(samplerObject); |
1789 | |
1790 | switch(pname) |
1791 | { |
1792 | case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast<GLenum>(roundf(param))); break; |
1793 | case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast<GLenum>(roundf(param))); break; |
1794 | case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast<GLenum>(roundf(param))); break; |
1795 | case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast<GLenum>(roundf(param))); break; |
1796 | case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast<GLenum>(roundf(param))); break; |
1797 | case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; |
1798 | case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; |
1799 | case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(static_cast<GLenum>(roundf(param))); break; |
1800 | case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(static_cast<GLenum>(roundf(param))); break; |
1801 | case GL_TEXTURE_MAX_ANISOTROPY_EXT: samplerObject->setMaxAnisotropy(param); break; |
1802 | default: UNREACHABLE(pname); break; |
1803 | } |
1804 | } |
1805 | |
1806 | GLint Context::getSamplerParameteri(GLuint sampler, GLenum pname) |
1807 | { |
1808 | mResourceManager->checkSamplerAllocation(sampler); |
1809 | |
1810 | Sampler *samplerObject = getSampler(sampler); |
1811 | ASSERT(samplerObject); |
1812 | |
1813 | switch(pname) |
1814 | { |
1815 | case GL_TEXTURE_MIN_FILTER: return static_cast<GLint>(samplerObject->getMinFilter()); |
1816 | case GL_TEXTURE_MAG_FILTER: return static_cast<GLint>(samplerObject->getMagFilter()); |
1817 | case GL_TEXTURE_WRAP_S: return static_cast<GLint>(samplerObject->getWrapS()); |
1818 | case GL_TEXTURE_WRAP_T: return static_cast<GLint>(samplerObject->getWrapT()); |
1819 | case GL_TEXTURE_WRAP_R: return static_cast<GLint>(samplerObject->getWrapR()); |
1820 | case GL_TEXTURE_MIN_LOD: return static_cast<GLint>(roundf(samplerObject->getMinLod())); |
1821 | case GL_TEXTURE_MAX_LOD: return static_cast<GLint>(roundf(samplerObject->getMaxLod())); |
1822 | case GL_TEXTURE_COMPARE_MODE: return static_cast<GLint>(samplerObject->getCompareMode()); |
1823 | case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLint>(samplerObject->getCompareFunc()); |
1824 | case GL_TEXTURE_MAX_ANISOTROPY_EXT: return static_cast<GLint>(samplerObject->getMaxAnisotropy()); |
1825 | default: UNREACHABLE(pname); return 0; |
1826 | } |
1827 | } |
1828 | |
1829 | GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname) |
1830 | { |
1831 | mResourceManager->checkSamplerAllocation(sampler); |
1832 | |
1833 | Sampler *samplerObject = getSampler(sampler); |
1834 | ASSERT(samplerObject); |
1835 | |
1836 | switch(pname) |
1837 | { |
1838 | case GL_TEXTURE_MIN_FILTER: return static_cast<GLfloat>(samplerObject->getMinFilter()); |
1839 | case GL_TEXTURE_MAG_FILTER: return static_cast<GLfloat>(samplerObject->getMagFilter()); |
1840 | case GL_TEXTURE_WRAP_S: return static_cast<GLfloat>(samplerObject->getWrapS()); |
1841 | case GL_TEXTURE_WRAP_T: return static_cast<GLfloat>(samplerObject->getWrapT()); |
1842 | case GL_TEXTURE_WRAP_R: return static_cast<GLfloat>(samplerObject->getWrapR()); |
1843 | case GL_TEXTURE_MIN_LOD: return samplerObject->getMinLod(); |
1844 | case GL_TEXTURE_MAX_LOD: return samplerObject->getMaxLod(); |
1845 | case GL_TEXTURE_COMPARE_MODE: return static_cast<GLfloat>(samplerObject->getCompareMode()); |
1846 | case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLfloat>(samplerObject->getCompareFunc()); |
1847 | case GL_TEXTURE_MAX_ANISOTROPY_EXT: return samplerObject->getMaxAnisotropy(); |
1848 | default: UNREACHABLE(pname); return 0; |
1849 | } |
1850 | } |
1851 | |
1852 | bool Context::getBooleanv(GLenum pname, GLboolean *params) const |
1853 | { |
1854 | switch(pname) |
1855 | { |
1856 | case GL_SHADER_COMPILER: *params = GL_TRUE; break; |
1857 | case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; |
1858 | case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break; |
1859 | case GL_COLOR_WRITEMASK: |
1860 | params[0] = mState.colorMaskRed; |
1861 | params[1] = mState.colorMaskGreen; |
1862 | params[2] = mState.colorMaskBlue; |
1863 | params[3] = mState.colorMaskAlpha; |
1864 | break; |
1865 | case GL_CULL_FACE: *params = mState.cullFaceEnabled; break; |
1866 | case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFillEnabled; break; |
1867 | case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverageEnabled; break; |
1868 | case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverageEnabled; break; |
1869 | case GL_SCISSOR_TEST: *params = mState.scissorTestEnabled; break; |
1870 | case GL_STENCIL_TEST: *params = mState.stencilTestEnabled; break; |
1871 | case GL_DEPTH_TEST: *params = mState.depthTestEnabled; break; |
1872 | case GL_BLEND: *params = mState.blendEnabled; break; |
1873 | case GL_DITHER: *params = mState.ditherEnabled; break; |
1874 | case GL_PRIMITIVE_RESTART_FIXED_INDEX: *params = mState.primitiveRestartFixedIndexEnabled; break; |
1875 | case GL_RASTERIZER_DISCARD: *params = mState.rasterizerDiscardEnabled; break; |
1876 | case GL_TRANSFORM_FEEDBACK_ACTIVE: |
1877 | { |
1878 | TransformFeedback* transformFeedback = getTransformFeedback(mState.transformFeedback); |
1879 | if(transformFeedback) |
1880 | { |
1881 | *params = transformFeedback->isActive(); |
1882 | break; |
1883 | } |
1884 | else return false; |
1885 | } |
1886 | case GL_TRANSFORM_FEEDBACK_PAUSED: |
1887 | { |
1888 | TransformFeedback* transformFeedback = getTransformFeedback(mState.transformFeedback); |
1889 | if(transformFeedback) |
1890 | { |
1891 | *params = transformFeedback->isPaused(); |
1892 | break; |
1893 | } |
1894 | else return false; |
1895 | } |
1896 | default: |
1897 | return false; |
1898 | } |
1899 | |
1900 | return true; |
1901 | } |
1902 | |
1903 | bool Context::getFloatv(GLenum pname, GLfloat *params) const |
1904 | { |
1905 | // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation |
1906 | // because it is stored as a float, despite the fact that the GL ES 2.0 spec names |
1907 | // GetIntegerv as its native query function. As it would require conversion in any |
1908 | // case, this should make no difference to the calling application. |
1909 | switch(pname) |
1910 | { |
1911 | case GL_LINE_WIDTH: *params = mState.lineWidth; break; |
1912 | case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; |
1913 | case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; |
1914 | case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break; |
1915 | case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break; |
1916 | case GL_ALIASED_LINE_WIDTH_RANGE: |
1917 | params[0] = ALIASED_LINE_WIDTH_RANGE_MIN; |
1918 | params[1] = ALIASED_LINE_WIDTH_RANGE_MAX; |
1919 | break; |
1920 | case GL_ALIASED_POINT_SIZE_RANGE: |
1921 | params[0] = ALIASED_POINT_SIZE_RANGE_MIN; |
1922 | params[1] = ALIASED_POINT_SIZE_RANGE_MAX; |
1923 | break; |
1924 | case GL_DEPTH_RANGE: |
1925 | params[0] = mState.zNear; |
1926 | params[1] = mState.zFar; |
1927 | break; |
1928 | case GL_COLOR_CLEAR_VALUE: |
1929 | params[0] = mState.colorClearValue.red; |
1930 | params[1] = mState.colorClearValue.green; |
1931 | params[2] = mState.colorClearValue.blue; |
1932 | params[3] = mState.colorClearValue.alpha; |
1933 | break; |
1934 | case GL_BLEND_COLOR: |
1935 | params[0] = mState.blendColor.red; |
1936 | params[1] = mState.blendColor.green; |
1937 | params[2] = mState.blendColor.blue; |
1938 | params[3] = mState.blendColor.alpha; |
1939 | break; |
1940 | case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: |
1941 | *params = MAX_TEXTURE_MAX_ANISOTROPY; |
1942 | break; |
1943 | default: |
1944 | return false; |
1945 | } |
1946 | |
1947 | return true; |
1948 | } |
1949 | |
1950 | template bool Context::getIntegerv<GLint>(GLenum pname, GLint *params) const; |
1951 | template bool Context::getIntegerv<GLint64>(GLenum pname, GLint64 *params) const; |
1952 | |
1953 | template<typename T> bool Context::getIntegerv(GLenum pname, T *params) const |
1954 | { |
1955 | // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation |
1956 | // because it is stored as a float, despite the fact that the GL ES 2.0 spec names |
1957 | // GetIntegerv as its native query function. As it would require conversion in any |
1958 | // case, this should make no difference to the calling application. You may find it in |
1959 | // Context::getFloatv. |
1960 | switch(pname) |
1961 | { |
1962 | case GL_MAX_VERTEX_ATTRIBS: *params = MAX_VERTEX_ATTRIBS; return true; |
1963 | case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = MAX_VERTEX_UNIFORM_VECTORS; return true; |
1964 | case GL_MAX_VARYING_VECTORS: *params = MAX_VARYING_VECTORS; return true; |
1965 | case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = MAX_COMBINED_TEXTURE_IMAGE_UNITS; return true; |
1966 | case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = MAX_VERTEX_TEXTURE_IMAGE_UNITS; return true; |
1967 | case GL_MAX_TEXTURE_IMAGE_UNITS: *params = MAX_TEXTURE_IMAGE_UNITS; return true; |
1968 | case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = MAX_FRAGMENT_UNIFORM_VECTORS; return true; |
1969 | case GL_MAX_RENDERBUFFER_SIZE: *params = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE; return true; |
1970 | case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; return true; |
1971 | case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ return true; |
1972 | case GL_ARRAY_BUFFER_BINDING: *params = getArrayBufferName(); return true; |
1973 | case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getElementArrayBufferName(); return true; |
1974 | // case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE |
1975 | case GL_DRAW_FRAMEBUFFER_BINDING: *params = mState.drawFramebuffer; return true; |
1976 | case GL_READ_FRAMEBUFFER_BINDING: *params = mState.readFramebuffer; return true; |
1977 | case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.name(); return true; |
1978 | case GL_CURRENT_PROGRAM: *params = mState.currentProgram; return true; |
1979 | case GL_PACK_ALIGNMENT: *params = mState.packParameters.alignment; return true; |
1980 | case GL_UNPACK_ALIGNMENT: *params = mState.unpackParameters.alignment; return true; |
1981 | case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; return true; |
1982 | case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; return true; |
1983 | case GL_TEXTURE_FILTERING_HINT_CHROMIUM: *params = mState.textureFilteringHint; return true; |
1984 | case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); return true; |
1985 | case GL_STENCIL_FUNC: *params = mState.stencilFunc; return true; |
1986 | case GL_STENCIL_REF: *params = mState.stencilRef; return true; |
1987 | case GL_STENCIL_VALUE_MASK: *params = sw::clampToSignedInt(mState.stencilMask); return true; |
1988 | case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; return true; |
1989 | case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; return true; |
1990 | case GL_STENCIL_BACK_VALUE_MASK: *params = sw::clampToSignedInt(mState.stencilBackMask); return true; |
1991 | case GL_STENCIL_FAIL: *params = mState.stencilFail; return true; |
1992 | case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; return true; |
1993 | case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; return true; |
1994 | case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; return true; |
1995 | case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; return true; |
1996 | case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; return true; |
1997 | case GL_DEPTH_FUNC: *params = mState.depthFunc; return true; |
1998 | case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; return true; |
1999 | case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; return true; |
2000 | case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; return true; |
2001 | case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; return true; |
2002 | case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; return true; |
2003 | case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; return true; |
2004 | case GL_STENCIL_WRITEMASK: *params = sw::clampToSignedInt(mState.stencilWritemask); return true; |
2005 | case GL_STENCIL_BACK_WRITEMASK: *params = sw::clampToSignedInt(mState.stencilBackWritemask); return true; |
2006 | case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; return true; |
2007 | case GL_SUBPIXEL_BITS: *params = 4; return true; |
2008 | case GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB: |
2009 | case GL_MAX_TEXTURE_SIZE: *params = IMPLEMENTATION_MAX_TEXTURE_SIZE; return true; |
2010 | case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE; return true; |
2011 | case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = NUM_COMPRESSED_TEXTURE_FORMATS; return true; |
2012 | case GL_MAX_SAMPLES: *params = IMPLEMENTATION_MAX_SAMPLES; return true; |
2013 | case GL_SAMPLE_BUFFERS: |
2014 | case GL_SAMPLES: |
2015 | { |
2016 | Framebuffer *framebuffer = getDrawFramebuffer(); |
2017 | int width, height, samples; |
2018 | |
2019 | if(framebuffer && (framebuffer->completeness(width, height, samples) == GL_FRAMEBUFFER_COMPLETE)) |
2020 | { |
2021 | switch(pname) |
2022 | { |
2023 | case GL_SAMPLE_BUFFERS: |
2024 | if(samples > 1) |
2025 | { |
2026 | *params = 1; |
2027 | } |
2028 | else |
2029 | { |
2030 | *params = 0; |
2031 | } |
2032 | break; |
2033 | case GL_SAMPLES: |
2034 | *params = samples; |
2035 | break; |
2036 | } |
2037 | } |
2038 | else |
2039 | { |
2040 | *params = 0; |
2041 | } |
2042 | } |
2043 | return true; |
2044 | case GL_IMPLEMENTATION_COLOR_READ_TYPE: |
2045 | { |
2046 | Framebuffer *framebuffer = getReadFramebuffer(); |
2047 | if(framebuffer) |
2048 | { |
2049 | *params = framebuffer->getImplementationColorReadType(); |
2050 | } |
2051 | else |
2052 | { |
2053 | return error(GL_INVALID_OPERATION, true); |
2054 | } |
2055 | } |
2056 | return true; |
2057 | case GL_IMPLEMENTATION_COLOR_READ_FORMAT: |
2058 | { |
2059 | Framebuffer *framebuffer = getReadFramebuffer(); |
2060 | if(framebuffer) |
2061 | { |
2062 | *params = framebuffer->getImplementationColorReadFormat(); |
2063 | } |
2064 | else |
2065 | { |
2066 | return error(GL_INVALID_OPERATION, true); |
2067 | } |
2068 | } |
2069 | return true; |
2070 | case GL_MAX_VIEWPORT_DIMS: |
2071 | { |
2072 | int maxDimension = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE; |
2073 | params[0] = maxDimension; |
2074 | params[1] = maxDimension; |
2075 | } |
2076 | return true; |
2077 | case GL_COMPRESSED_TEXTURE_FORMATS: |
2078 | { |
2079 | for(int i = 0; i < NUM_COMPRESSED_TEXTURE_FORMATS; i++) |
2080 | { |
2081 | params[i] = compressedTextureFormats[i]; |
2082 | } |
2083 | } |
2084 | return true; |
2085 | case GL_VIEWPORT: |
2086 | params[0] = mState.viewportX; |
2087 | params[1] = mState.viewportY; |
2088 | params[2] = mState.viewportWidth; |
2089 | params[3] = mState.viewportHeight; |
2090 | return true; |
2091 | case GL_SCISSOR_BOX: |
2092 | params[0] = mState.scissorX; |
2093 | params[1] = mState.scissorY; |
2094 | params[2] = mState.scissorWidth; |
2095 | params[3] = mState.scissorHeight; |
2096 | return true; |
2097 | case GL_CULL_FACE_MODE: *params = mState.cullMode; return true; |
2098 | case GL_FRONT_FACE: *params = mState.frontFace; return true; |
2099 | case GL_RED_BITS: |
2100 | case GL_GREEN_BITS: |
2101 | case GL_BLUE_BITS: |
2102 | case GL_ALPHA_BITS: |
2103 | { |
2104 | Framebuffer *framebuffer = getDrawFramebuffer(); |
2105 | Renderbuffer *colorbuffer = framebuffer ? framebuffer->getColorbuffer(0) : nullptr; |
2106 | |
2107 | if(colorbuffer) |
2108 | { |
2109 | switch(pname) |
2110 | { |
2111 | case GL_RED_BITS: *params = colorbuffer->getRedSize(); return true; |
2112 | case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); return true; |
2113 | case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); return true; |
2114 | case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); return true; |
2115 | } |
2116 | } |
2117 | else |
2118 | { |
2119 | *params = 0; |
2120 | } |
2121 | } |
2122 | return true; |
2123 | case GL_DEPTH_BITS: |
2124 | { |
2125 | Framebuffer *framebuffer = getDrawFramebuffer(); |
2126 | Renderbuffer *depthbuffer = framebuffer ? framebuffer->getDepthbuffer() : nullptr; |
2127 | |
2128 | if(depthbuffer) |
2129 | { |
2130 | *params = depthbuffer->getDepthSize(); |
2131 | } |
2132 | else |
2133 | { |
2134 | *params = 0; |
2135 | } |
2136 | } |
2137 | return true; |
2138 | case GL_STENCIL_BITS: |
2139 | { |
2140 | Framebuffer *framebuffer = getDrawFramebuffer(); |
2141 | Renderbuffer *stencilbuffer = framebuffer ? framebuffer->getStencilbuffer() : nullptr; |
2142 | |
2143 | if(stencilbuffer) |
2144 | { |
2145 | *params = stencilbuffer->getStencilSize(); |
2146 | } |
2147 | else |
2148 | { |
2149 | *params = 0; |
2150 | } |
2151 | } |
2152 | return true; |
2153 | case GL_TEXTURE_BINDING_2D: |
2154 | if(mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1) |
2155 | { |
2156 | error(GL_INVALID_OPERATION); |
2157 | return false; |
2158 | } |
2159 | |
2160 | *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].name(); |
2161 | return true; |
2162 | case GL_TEXTURE_BINDING_CUBE_MAP: |
2163 | if(mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1) |
2164 | { |
2165 | error(GL_INVALID_OPERATION); |
2166 | return false; |
2167 | } |
2168 | |
2169 | *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].name(); |
2170 | return true; |
2171 | case GL_TEXTURE_BINDING_RECTANGLE_ARB: |
2172 | if(mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1) |
2173 | { |
2174 | error(GL_INVALID_OPERATION); |
2175 | return false; |
2176 | } |
2177 | |
2178 | *params = mState.samplerTexture[TEXTURE_2D_RECT][mState.activeSampler].name(); |
2179 | return true; |
2180 | case GL_TEXTURE_BINDING_EXTERNAL_OES: |
2181 | if(mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1) |
2182 | { |
2183 | error(GL_INVALID_OPERATION); |
2184 | return false; |
2185 | } |
2186 | |
2187 | *params = mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler].name(); |
2188 | return true; |
2189 | case GL_TEXTURE_BINDING_3D_OES: |
2190 | if(mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1) |
2191 | { |
2192 | error(GL_INVALID_OPERATION); |
2193 | return false; |
2194 | } |
2195 | |
2196 | *params = mState.samplerTexture[TEXTURE_3D][mState.activeSampler].name(); |
2197 | return true; |
2198 | case GL_DRAW_BUFFER0: |
2199 | case GL_DRAW_BUFFER1: |
2200 | case GL_DRAW_BUFFER2: |
2201 | case GL_DRAW_BUFFER3: |
2202 | case GL_DRAW_BUFFER4: |
2203 | case GL_DRAW_BUFFER5: |
2204 | case GL_DRAW_BUFFER6: |
2205 | case GL_DRAW_BUFFER7: |
2206 | case GL_DRAW_BUFFER8: |
2207 | case GL_DRAW_BUFFER9: |
2208 | case GL_DRAW_BUFFER10: |
2209 | case GL_DRAW_BUFFER11: |
2210 | case GL_DRAW_BUFFER12: |
2211 | case GL_DRAW_BUFFER13: |
2212 | case GL_DRAW_BUFFER14: |
2213 | case GL_DRAW_BUFFER15: |
2214 | if((pname - GL_DRAW_BUFFER0) < MAX_DRAW_BUFFERS) |
2215 | { |
2216 | Framebuffer* framebuffer = getDrawFramebuffer(); |
2217 | *params = framebuffer ? framebuffer->getDrawBuffer(pname - GL_DRAW_BUFFER0) : GL_NONE; |
2218 | } |
2219 | else |
2220 | { |
2221 | return false; |
2222 | } |
2223 | return true; |
2224 | case GL_MAX_DRAW_BUFFERS: |
2225 | *params = MAX_DRAW_BUFFERS; |
2226 | return true; |
2227 | case GL_MAX_COLOR_ATTACHMENTS: // Note: MAX_COLOR_ATTACHMENTS_EXT added by GL_EXT_draw_buffers |
2228 | *params = MAX_COLOR_ATTACHMENTS; |
2229 | return true; |
2230 | case GL_TEXTURE_BINDING_2D_ARRAY: |
2231 | if(mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1) |
2232 | { |
2233 | error(GL_INVALID_OPERATION); |
2234 | return false; |
2235 | } |
2236 | |
2237 | *params = mState.samplerTexture[TEXTURE_2D_ARRAY][mState.activeSampler].name(); |
2238 | return true; |
2239 | case GL_COPY_READ_BUFFER_BINDING: |
2240 | *params = mState.copyReadBuffer.name(); |
2241 | return true; |
2242 | case GL_COPY_WRITE_BUFFER_BINDING: |
2243 | *params = mState.copyWriteBuffer.name(); |
2244 | return true; |
2245 | case GL_MAJOR_VERSION: |
2246 | *params = 3; |
2247 | return true; |
2248 | case GL_MINOR_VERSION: |
2249 | *params = 0; |
2250 | return true; |
2251 | case GL_MAX_3D_TEXTURE_SIZE: |
2252 | *params = IMPLEMENTATION_MAX_3D_TEXTURE_SIZE; |
2253 | return true; |
2254 | case GL_MAX_ARRAY_TEXTURE_LAYERS: |
2255 | *params = IMPLEMENTATION_MAX_TEXTURE_SIZE; |
2256 | return true; |
2257 | case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: |
2258 | *params = MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS; |
2259 | return true; |
2260 | case GL_MAX_COMBINED_UNIFORM_BLOCKS: |
2261 | *params = MAX_VERTEX_UNIFORM_BLOCKS + MAX_FRAGMENT_UNIFORM_BLOCKS; |
2262 | return true; |
2263 | case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: |
2264 | *params = MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS; |
2265 | return true; |
2266 | case GL_MAX_ELEMENT_INDEX: |
2267 | *params = MAX_ELEMENT_INDEX; |
2268 | return true; |
2269 | case GL_MAX_ELEMENTS_INDICES: |
2270 | *params = MAX_ELEMENTS_INDICES; |
2271 | return true; |
2272 | case GL_MAX_ELEMENTS_VERTICES: |
2273 | *params = MAX_ELEMENTS_VERTICES; |
2274 | return true; |
2275 | case GL_MAX_FRAGMENT_INPUT_COMPONENTS: |
2276 | *params = MAX_FRAGMENT_INPUT_VECTORS * 4; |
2277 | return true; |
2278 | case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: |
2279 | *params = MAX_FRAGMENT_UNIFORM_BLOCKS; |
2280 | return true; |
2281 | case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: |
2282 | *params = MAX_FRAGMENT_UNIFORM_COMPONENTS; |
2283 | return true; |
2284 | case GL_MAX_PROGRAM_TEXEL_OFFSET: |
2285 | // Note: SwiftShader has no actual texel offset limit, so this limit can be modified if required. |
2286 | // In any case, any behavior outside the specified range is valid since the spec mentions: |
2287 | // (see OpenGL ES 3.0.5, 3.8.10.1 Scale Factor and Level of Detail, p.153) |
2288 | // "If any of the offset values are outside the range of the implementation-defined values |
2289 | // MIN_PROGRAM_TEXEL_OFFSET and MAX_PROGRAM_TEXEL_OFFSET, results of the texture lookup are |
2290 | // undefined." |
2291 | *params = MAX_PROGRAM_TEXEL_OFFSET; |
2292 | return true; |
2293 | case GL_MAX_SERVER_WAIT_TIMEOUT: |
2294 | *params = 0; |
2295 | return true; |
2296 | case GL_MAX_TEXTURE_LOD_BIAS: |
2297 | *params = MAX_TEXTURE_LOD_BIAS; |
2298 | return true; |
2299 | case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: |
2300 | *params = sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; |
2301 | return true; |
2302 | case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: |
2303 | *params = MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS; |
2304 | return true; |
2305 | case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: |
2306 | *params = sw::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS; |
2307 | return true; |
2308 | case GL_MAX_UNIFORM_BLOCK_SIZE: |
2309 | *params = MAX_UNIFORM_BLOCK_SIZE; |
2310 | return true; |
2311 | case GL_MAX_UNIFORM_BUFFER_BINDINGS: |
2312 | *params = MAX_UNIFORM_BUFFER_BINDINGS; |
2313 | return true; |
2314 | case GL_MAX_VARYING_COMPONENTS: |
2315 | *params = MAX_VARYING_VECTORS * 4; |
2316 | return true; |
2317 | case GL_MAX_VERTEX_OUTPUT_COMPONENTS: |
2318 | *params = MAX_VERTEX_OUTPUT_VECTORS * 4; |
2319 | return true; |
2320 | case GL_MAX_VERTEX_UNIFORM_BLOCKS: |
2321 | *params = MAX_VERTEX_UNIFORM_BLOCKS; |
2322 | return true; |
2323 | case GL_MAX_VERTEX_UNIFORM_COMPONENTS: |
2324 | *params = MAX_VERTEX_UNIFORM_COMPONENTS; |
2325 | return true; |
2326 | case GL_MIN_PROGRAM_TEXEL_OFFSET: |
2327 | // Note: SwiftShader has no actual texel offset limit, so this limit can be modified if required. |
2328 | // In any case, any behavior outside the specified range is valid since the spec mentions: |
2329 | // (see OpenGL ES 3.0.5, 3.8.10.1 Scale Factor and Level of Detail, p.153) |
2330 | // "If any of the offset values are outside the range of the implementation-defined values |
2331 | // MIN_PROGRAM_TEXEL_OFFSET and MAX_PROGRAM_TEXEL_OFFSET, results of the texture lookup are |
2332 | // undefined." |
2333 | *params = MIN_PROGRAM_TEXEL_OFFSET; |
2334 | return true; |
2335 | case GL_NUM_EXTENSIONS: |
2336 | GLuint numExtensions; |
2337 | getExtensions(0, &numExtensions); |
2338 | *params = numExtensions; |
2339 | return true; |
2340 | case GL_NUM_PROGRAM_BINARY_FORMATS: |
2341 | *params = NUM_PROGRAM_BINARY_FORMATS; |
2342 | return true; |
2343 | case GL_PACK_ROW_LENGTH: |
2344 | *params = mState.packParameters.rowLength; |
2345 | return true; |
2346 | case GL_PACK_SKIP_PIXELS: |
2347 | *params = mState.packParameters.skipPixels; |
2348 | return true; |
2349 | case GL_PACK_SKIP_ROWS: |
2350 | *params = mState.packParameters.skipRows; |
2351 | return true; |
2352 | case GL_PIXEL_PACK_BUFFER_BINDING: |
2353 | *params = mState.pixelPackBuffer.name(); |
2354 | return true; |
2355 | case GL_PIXEL_UNPACK_BUFFER_BINDING: |
2356 | *params = mState.pixelUnpackBuffer.name(); |
2357 | return true; |
2358 | case GL_PROGRAM_BINARY_FORMATS: |
2359 | // Since NUM_PROGRAM_BINARY_FORMATS is 0, the input |
2360 | // should be a 0 sized array, so don't write to params |
2361 | return true; |
2362 | case GL_READ_BUFFER: |
2363 | { |
2364 | Framebuffer* framebuffer = getReadFramebuffer(); |
2365 | *params = framebuffer ? framebuffer->getReadBuffer() : GL_NONE; |
2366 | } |
2367 | return true; |
2368 | case GL_SAMPLER_BINDING: |
2369 | *params = mState.sampler[mState.activeSampler].name(); |
2370 | return true; |
2371 | case GL_UNIFORM_BUFFER_BINDING: |
2372 | *params = mState.genericUniformBuffer.name(); |
2373 | return true; |
2374 | case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: |
2375 | *params = UNIFORM_BUFFER_OFFSET_ALIGNMENT; |
2376 | return true; |
2377 | case GL_UNPACK_IMAGE_HEIGHT: |
2378 | *params = mState.unpackParameters.imageHeight; |
2379 | return true; |
2380 | case GL_UNPACK_ROW_LENGTH: |
2381 | *params = mState.unpackParameters.rowLength; |
2382 | return true; |
2383 | case GL_UNPACK_SKIP_IMAGES: |
2384 | *params = mState.unpackParameters.skipImages; |
2385 | return true; |
2386 | case GL_UNPACK_SKIP_PIXELS: |
2387 | *params = mState.unpackParameters.skipPixels; |
2388 | return true; |
2389 | case GL_UNPACK_SKIP_ROWS: |
2390 | *params = mState.unpackParameters.skipRows; |
2391 | return true; |
2392 | case GL_VERTEX_ARRAY_BINDING: |
2393 | *params = getCurrentVertexArray()->name; |
2394 | return true; |
2395 | case GL_TRANSFORM_FEEDBACK_BINDING: |
2396 | { |
2397 | TransformFeedback* transformFeedback = getTransformFeedback(mState.transformFeedback); |
2398 | if(transformFeedback) |
2399 | { |
2400 | *params = transformFeedback->name; |
2401 | } |
2402 | else |
2403 | { |
2404 | return false; |
2405 | } |
2406 | } |
2407 | return true; |
2408 | case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: |
2409 | { |
2410 | TransformFeedback* transformFeedback = getTransformFeedback(mState.transformFeedback); |
2411 | if(transformFeedback) |
2412 | { |
2413 | *params = mState.genericTransformFeedbackBuffer.name(); |
2414 | } |
2415 | else |
2416 | { |
2417 | return false; |
2418 | } |
2419 | } |
2420 | return true; |
2421 | default: |
2422 | break; |
2423 | } |
2424 | |
2425 | return false; |
2426 | } |
2427 | |
2428 | template bool Context::getTransformFeedbackiv<GLint>(GLuint index, GLenum pname, GLint *param) const; |
2429 | template bool Context::getTransformFeedbackiv<GLint64>(GLuint index, GLenum pname, GLint64 *param) const; |
2430 | |
2431 | template<typename T> bool Context::getTransformFeedbackiv(GLuint index, GLenum pname, T *param) const |
2432 | { |
2433 | TransformFeedback* transformFeedback = getTransformFeedback(mState.transformFeedback); |
2434 | if(!transformFeedback) |
2435 | { |
2436 | return false; |
2437 | } |
2438 | |
2439 | switch(pname) |
2440 | { |
2441 | case GL_TRANSFORM_FEEDBACK_BINDING: // GLint, initially 0 |
2442 | *param = transformFeedback->name; |
2443 | break; |
2444 | case GL_TRANSFORM_FEEDBACK_ACTIVE: // boolean, initially GL_FALSE |
2445 | *param = transformFeedback->isActive(); |
2446 | break; |
2447 | case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: // name, initially 0 |
2448 | *param = transformFeedback->getBufferName(index); |
2449 | break; |
2450 | case GL_TRANSFORM_FEEDBACK_PAUSED: // boolean, initially GL_FALSE |
2451 | *param = transformFeedback->isPaused(); |
2452 | break; |
2453 | case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: // indexed[n] 64-bit integer, initially 0 |
2454 | if(transformFeedback->getBuffer(index)) |
2455 | { |
2456 | *param = transformFeedback->getSize(index); |
2457 | break; |
2458 | } |
2459 | else return false; |
2460 | case GL_TRANSFORM_FEEDBACK_BUFFER_START: // indexed[n] 64-bit integer, initially 0 |
2461 | if(transformFeedback->getBuffer(index)) |
2462 | { |
2463 | *param = transformFeedback->getOffset(index); |
2464 | break; |
2465 | } |
2466 | else return false; |
2467 | default: |
2468 | return false; |
2469 | } |
2470 | |
2471 | return true; |
2472 | } |
2473 | |
2474 | template bool Context::getUniformBufferiv<GLint>(GLuint index, GLenum pname, GLint *param) const; |
2475 | template bool Context::getUniformBufferiv<GLint64>(GLuint index, GLenum pname, GLint64 *param) const; |
2476 | |
2477 | template<typename T> bool Context::getUniformBufferiv(GLuint index, GLenum pname, T *param) const |
2478 | { |
2479 | switch(pname) |
2480 | { |
2481 | case GL_UNIFORM_BUFFER_BINDING: |
2482 | case GL_UNIFORM_BUFFER_SIZE: |
2483 | case GL_UNIFORM_BUFFER_START: |
2484 | break; |
2485 | default: |
2486 | return false; |
2487 | } |
2488 | |
2489 | if(index >= MAX_UNIFORM_BUFFER_BINDINGS) |
2490 | { |
2491 | return error(GL_INVALID_VALUE, true); |
2492 | } |
2493 | |
2494 | const BufferBinding& uniformBuffer = mState.uniformBuffers[index]; |
2495 | |
2496 | switch(pname) |
2497 | { |
2498 | case GL_UNIFORM_BUFFER_BINDING: // name, initially 0 |
2499 | *param = uniformBuffer.get().name(); |
2500 | break; |
2501 | case GL_UNIFORM_BUFFER_SIZE: // indexed[n] 64-bit integer, initially 0 |
2502 | *param = uniformBuffer.getSize(); |
2503 | break; |
2504 | case GL_UNIFORM_BUFFER_START: // indexed[n] 64-bit integer, initially 0 |
2505 | *param = uniformBuffer.getOffset(); |
2506 | break; |
2507 | default: |
2508 | return false; |
2509 | } |
2510 | |
2511 | return true; |
2512 | } |
2513 | |
2514 | bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) const |
2515 | { |
2516 | // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation |
2517 | // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due |
2518 | // to the fact that it is stored internally as a float, and so would require conversion |
2519 | // if returned from Context::getIntegerv. Since this conversion is already implemented |
2520 | // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we |
2521 | // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling |
2522 | // application. |
2523 | switch(pname) |
2524 | { |
2525 | case GL_COMPRESSED_TEXTURE_FORMATS: |
2526 | { |
2527 | *type = GL_INT; |
2528 | *numParams = NUM_COMPRESSED_TEXTURE_FORMATS; |
2529 | } |
2530 | break; |
2531 | case GL_SHADER_BINARY_FORMATS: |
2532 | { |
2533 | *type = GL_INT; |
2534 | *numParams = 0; |
2535 | } |
2536 | break; |
2537 | case GL_MAX_VERTEX_ATTRIBS: |
2538 | case GL_MAX_VERTEX_UNIFORM_VECTORS: |
2539 | case GL_MAX_VARYING_VECTORS: |
2540 | case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: |
2541 | case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: |
2542 | case GL_MAX_TEXTURE_IMAGE_UNITS: |
2543 | case GL_MAX_FRAGMENT_UNIFORM_VECTORS: |
2544 | case GL_MAX_RENDERBUFFER_SIZE: |
2545 | case GL_NUM_SHADER_BINARY_FORMATS: |
2546 | case GL_NUM_COMPRESSED_TEXTURE_FORMATS: |
2547 | case GL_ARRAY_BUFFER_BINDING: |
2548 | case GL_FRAMEBUFFER_BINDING: // Same as GL_DRAW_FRAMEBUFFER_BINDING_ANGLE |
2549 | case GL_READ_FRAMEBUFFER_BINDING: // Same as GL_READ_FRAMEBUFFER_BINDING_ANGLE |
2550 | case GL_RENDERBUFFER_BINDING: |
2551 | case GL_CURRENT_PROGRAM: |
2552 | case GL_PACK_ALIGNMENT: |
2553 | case GL_UNPACK_ALIGNMENT: |
2554 | case GL_GENERATE_MIPMAP_HINT: |
2555 | case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: |
2556 | case GL_TEXTURE_FILTERING_HINT_CHROMIUM: |
2557 | case GL_RED_BITS: |
2558 | case GL_GREEN_BITS: |
2559 | case GL_BLUE_BITS: |
2560 | case GL_ALPHA_BITS: |
2561 | case GL_DEPTH_BITS: |
2562 | case GL_STENCIL_BITS: |
2563 | case GL_ELEMENT_ARRAY_BUFFER_BINDING: |
2564 | case GL_CULL_FACE_MODE: |
2565 | case GL_FRONT_FACE: |
2566 | case GL_ACTIVE_TEXTURE: |
2567 | case GL_STENCIL_FUNC: |
2568 | case GL_STENCIL_VALUE_MASK: |
2569 | case GL_STENCIL_REF: |
2570 | case GL_STENCIL_FAIL: |
2571 | case GL_STENCIL_PASS_DEPTH_FAIL: |
2572 | case GL_STENCIL_PASS_DEPTH_PASS: |
2573 | case GL_STENCIL_BACK_FUNC: |
2574 | case GL_STENCIL_BACK_VALUE_MASK: |
2575 | case GL_STENCIL_BACK_REF: |
2576 | case GL_STENCIL_BACK_FAIL: |
2577 | case GL_STENCIL_BACK_PASS_DEPTH_FAIL: |
2578 | case GL_STENCIL_BACK_PASS_DEPTH_PASS: |
2579 | case GL_DEPTH_FUNC: |
2580 | case GL_BLEND_SRC_RGB: |
2581 | case GL_BLEND_SRC_ALPHA: |
2582 | case GL_BLEND_DST_RGB: |
2583 | case GL_BLEND_DST_ALPHA: |
2584 | case GL_BLEND_EQUATION_RGB: |
2585 | case GL_BLEND_EQUATION_ALPHA: |
2586 | case GL_STENCIL_WRITEMASK: |
2587 | case GL_STENCIL_BACK_WRITEMASK: |
2588 | case GL_STENCIL_CLEAR_VALUE: |
2589 | case GL_SUBPIXEL_BITS: |
2590 | case GL_MAX_TEXTURE_SIZE: |
2591 | case GL_MAX_CUBE_MAP_TEXTURE_SIZE: |
2592 | case GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB: |
2593 | case GL_SAMPLE_BUFFERS: |
2594 | case GL_SAMPLES: |
2595 | case GL_IMPLEMENTATION_COLOR_READ_TYPE: |
2596 | case GL_IMPLEMENTATION_COLOR_READ_FORMAT: |
2597 | case GL_TEXTURE_BINDING_2D: |
2598 | case GL_TEXTURE_BINDING_CUBE_MAP: |
2599 | case GL_TEXTURE_BINDING_RECTANGLE_ARB: |
2600 | case GL_TEXTURE_BINDING_EXTERNAL_OES: |
2601 | case GL_TEXTURE_BINDING_3D_OES: |
2602 | case GL_COPY_READ_BUFFER_BINDING: |
2603 | case GL_COPY_WRITE_BUFFER_BINDING: |
2604 | case GL_DRAW_BUFFER0: |
2605 | case GL_DRAW_BUFFER1: |
2606 | case GL_DRAW_BUFFER2: |
2607 | case GL_DRAW_BUFFER3: |
2608 | case GL_DRAW_BUFFER4: |
2609 | case GL_DRAW_BUFFER5: |
2610 | case GL_DRAW_BUFFER6: |
2611 | case GL_DRAW_BUFFER7: |
2612 | case GL_DRAW_BUFFER8: |
2613 | case GL_DRAW_BUFFER9: |
2614 | case GL_DRAW_BUFFER10: |
2615 | case GL_DRAW_BUFFER11: |
2616 | case GL_DRAW_BUFFER12: |
2617 | case GL_DRAW_BUFFER13: |
2618 | case GL_DRAW_BUFFER14: |
2619 | case GL_DRAW_BUFFER15: |
2620 | case GL_MAJOR_VERSION: |
2621 | case GL_MAX_3D_TEXTURE_SIZE: |
2622 | case GL_MAX_ARRAY_TEXTURE_LAYERS: |
2623 | case GL_MAX_COLOR_ATTACHMENTS: |
2624 | case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: |
2625 | case GL_MAX_COMBINED_UNIFORM_BLOCKS: |
2626 | case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: |
2627 | case GL_MAX_DRAW_BUFFERS: |
2628 | case GL_MAX_ELEMENT_INDEX: |
2629 | case GL_MAX_ELEMENTS_INDICES: |
2630 | case GL_MAX_ELEMENTS_VERTICES: |
2631 | case GL_MAX_FRAGMENT_INPUT_COMPONENTS: |
2632 | case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: |
2633 | case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: |
2634 | case GL_MAX_PROGRAM_TEXEL_OFFSET: |
2635 | case GL_MAX_SERVER_WAIT_TIMEOUT: |
2636 | case GL_MAX_TEXTURE_LOD_BIAS: |
2637 | case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: |
2638 | case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: |
2639 | case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: |
2640 | case GL_MAX_UNIFORM_BLOCK_SIZE: |
2641 | case GL_MAX_UNIFORM_BUFFER_BINDINGS: |
2642 | case GL_MAX_VARYING_COMPONENTS: |
2643 | case GL_MAX_VERTEX_OUTPUT_COMPONENTS: |
2644 | case GL_MAX_VERTEX_UNIFORM_BLOCKS: |
2645 | case GL_MAX_VERTEX_UNIFORM_COMPONENTS: |
2646 | case GL_MIN_PROGRAM_TEXEL_OFFSET: |
2647 | case GL_MINOR_VERSION: |
2648 | case GL_NUM_EXTENSIONS: |
2649 | case GL_NUM_PROGRAM_BINARY_FORMATS: |
2650 | case GL_PACK_ROW_LENGTH: |
2651 | case GL_PACK_SKIP_PIXELS: |
2652 | case GL_PACK_SKIP_ROWS: |
2653 | case GL_PIXEL_PACK_BUFFER_BINDING: |
2654 | case GL_PIXEL_UNPACK_BUFFER_BINDING: |
2655 | case GL_PROGRAM_BINARY_FORMATS: |
2656 | case GL_READ_BUFFER: |
2657 | case GL_SAMPLER_BINDING: |
2658 | case GL_TEXTURE_BINDING_2D_ARRAY: |
2659 | case GL_UNIFORM_BUFFER_BINDING: |
2660 | case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: |
2661 | case GL_UNPACK_IMAGE_HEIGHT: |
2662 | case GL_UNPACK_ROW_LENGTH: |
2663 | case GL_UNPACK_SKIP_IMAGES: |
2664 | case GL_UNPACK_SKIP_PIXELS: |
2665 | case GL_UNPACK_SKIP_ROWS: |
2666 | case GL_VERTEX_ARRAY_BINDING: |
2667 | case GL_TRANSFORM_FEEDBACK_BINDING: |
2668 | case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: |
2669 | { |
2670 | *type = GL_INT; |
2671 | *numParams = 1; |
2672 | } |
2673 | break; |
2674 | case GL_MAX_SAMPLES: |
2675 | { |
2676 | *type = GL_INT; |
2677 | *numParams = 1; |
2678 | } |
2679 | break; |
2680 | case GL_MAX_VIEWPORT_DIMS: |
2681 | { |
2682 | *type = GL_INT; |
2683 | *numParams = 2; |
2684 | } |
2685 | break; |
2686 | case GL_VIEWPORT: |
2687 | case GL_SCISSOR_BOX: |
2688 | { |
2689 | *type = GL_INT; |
2690 | *numParams = 4; |
2691 | } |
2692 | break; |
2693 | case GL_SHADER_COMPILER: |
2694 | case GL_SAMPLE_COVERAGE_INVERT: |
2695 | case GL_DEPTH_WRITEMASK: |
2696 | case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled, |
2697 | case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries. |
2698 | case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural |
2699 | case GL_SAMPLE_COVERAGE: |
2700 | case GL_SCISSOR_TEST: |
2701 | case GL_STENCIL_TEST: |
2702 | case GL_DEPTH_TEST: |
2703 | case GL_BLEND: |
2704 | case GL_DITHER: |
2705 | case GL_PRIMITIVE_RESTART_FIXED_INDEX: |
2706 | case GL_RASTERIZER_DISCARD: |
2707 | case GL_TRANSFORM_FEEDBACK_ACTIVE: |
2708 | case GL_TRANSFORM_FEEDBACK_PAUSED: |
2709 | { |
2710 | *type = GL_BOOL; |
2711 | *numParams = 1; |
2712 | } |
2713 | break; |
2714 | case GL_COLOR_WRITEMASK: |
2715 | { |
2716 | *type = GL_BOOL; |
2717 | *numParams = 4; |
2718 | } |
2719 | break; |
2720 | case GL_POLYGON_OFFSET_FACTOR: |
2721 | case GL_POLYGON_OFFSET_UNITS: |
2722 | case GL_SAMPLE_COVERAGE_VALUE: |
2723 | case GL_DEPTH_CLEAR_VALUE: |
2724 | case GL_LINE_WIDTH: |
2725 | { |
2726 | *type = GL_FLOAT; |
2727 | *numParams = 1; |
2728 | } |
2729 | break; |
2730 | case GL_ALIASED_LINE_WIDTH_RANGE: |
2731 | case GL_ALIASED_POINT_SIZE_RANGE: |
2732 | case GL_DEPTH_RANGE: |
2733 | { |
2734 | *type = GL_FLOAT; |
2735 | *numParams = 2; |
2736 | } |
2737 | break; |
2738 | case GL_COLOR_CLEAR_VALUE: |
2739 | case GL_BLEND_COLOR: |
2740 | { |
2741 | *type = GL_FLOAT; |
2742 | *numParams = 4; |
2743 | } |
2744 | break; |
2745 | case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: |
2746 | *type = GL_FLOAT; |
2747 | *numParams = 1; |
2748 | break; |
2749 | default: |
2750 | return false; |
2751 | } |
2752 | |
2753 | return true; |
2754 | } |
2755 | |
2756 | void Context::applyScissor(int width, int height) |
2757 | { |
2758 | if(mState.scissorTestEnabled) |
2759 | { |
2760 | sw::Rect scissor = { mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight }; |
2761 | scissor.clip(0, 0, width, height); |
2762 | |
2763 | device->setScissorRect(scissor); |
2764 | device->setScissorEnable(true); |
2765 | } |
2766 | else |
2767 | { |
2768 | device->setScissorEnable(false); |
2769 | } |
2770 | } |
2771 | |
2772 | // Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle |
2773 | bool Context::applyRenderTarget() |
2774 | { |
2775 | Framebuffer *framebuffer = getDrawFramebuffer(); |
2776 | int width, height, samples; |
2777 | |
2778 | if(!framebuffer || (framebuffer->completeness(width, height, samples) != GL_FRAMEBUFFER_COMPLETE)) |
2779 | { |
2780 | return error(GL_INVALID_FRAMEBUFFER_OPERATION, false); |
2781 | } |
2782 | |
2783 | for(int i = 0; i < MAX_DRAW_BUFFERS; i++) |
2784 | { |
2785 | if(framebuffer->getDrawBuffer(i) != GL_NONE) |
2786 | { |
2787 | egl::Image *renderTarget = framebuffer->getRenderTarget(i); |
2788 | GLint layer = framebuffer->getColorbufferLayer(i); |
2789 | device->setRenderTarget(i, renderTarget, layer); |
2790 | if(renderTarget) renderTarget->release(); |
2791 | } |
2792 | else |
2793 | { |
2794 | device->setRenderTarget(i, nullptr, 0); |
2795 | } |
2796 | } |
2797 | |
2798 | egl::Image *depthBuffer = framebuffer->getDepthBuffer(); |
2799 | GLint dLayer = framebuffer->getDepthbufferLayer(); |
2800 | device->setDepthBuffer(depthBuffer, dLayer); |
2801 | if(depthBuffer) depthBuffer->release(); |
2802 | |
2803 | egl::Image *stencilBuffer = framebuffer->getStencilBuffer(); |
2804 | GLint sLayer = framebuffer->getStencilbufferLayer(); |
2805 | device->setStencilBuffer(stencilBuffer, sLayer); |
2806 | if(stencilBuffer) stencilBuffer->release(); |
2807 | |
2808 | Viewport viewport; |
2809 | float zNear = clamp01(mState.zNear); |
2810 | float zFar = clamp01(mState.zFar); |
2811 | |
2812 | viewport.x0 = mState.viewportX; |
2813 | viewport.y0 = mState.viewportY; |
2814 | viewport.width = mState.viewportWidth; |
2815 | viewport.height = mState.viewportHeight; |
2816 | viewport.minZ = zNear; |
2817 | viewport.maxZ = zFar; |
2818 | |
2819 | if (viewport.x0 > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE || |
2820 | viewport.y0 > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE) |
2821 | { |
2822 | TransformFeedback* transformFeedback = getTransformFeedback(); |
2823 | if (!transformFeedback->isActive() || transformFeedback->isPaused()) |
2824 | { |
2825 | return false; |
2826 | } |
2827 | else |
2828 | { |
2829 | viewport.x0 = 0; |
2830 | viewport.y0 = 0; |
2831 | viewport.width = 0; |
2832 | viewport.height = 0; |
2833 | } |
2834 | } |
2835 | |
2836 | device->setViewport(viewport); |
2837 | |
2838 | applyScissor(width, height); |
2839 | |
2840 | Program *program = getCurrentProgram(); |
2841 | |
2842 | if(program) |
2843 | { |
2844 | GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear}; |
2845 | program->setUniform1fv(program->getUniformLocation("gl_DepthRange.near" ), 1, &nearFarDiff[0]); |
2846 | program->setUniform1fv(program->getUniformLocation("gl_DepthRange.far" ), 1, &nearFarDiff[1]); |
2847 | program->setUniform1fv(program->getUniformLocation("gl_DepthRange.diff" ), 1, &nearFarDiff[2]); |
2848 | } |
2849 | |
2850 | return true; |
2851 | } |
2852 | |
2853 | // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) |
2854 | void Context::applyState(GLenum drawMode) |
2855 | { |
2856 | Framebuffer *framebuffer = getDrawFramebuffer(); |
2857 | bool frontFaceCCW = (mState.frontFace == GL_CCW); |
2858 | |
2859 | if(mState.cullFaceEnabled) |
2860 | { |
2861 | device->setCullMode(es2sw::ConvertCullMode(mState.cullMode, mState.frontFace), frontFaceCCW); |
2862 | } |
2863 | else |
2864 | { |
2865 | device->setCullMode(sw::CULL_NONE, frontFaceCCW); |
2866 | } |
2867 | |
2868 | if(mDepthStateDirty) |
2869 | { |
2870 | if(mState.depthTestEnabled) |
2871 | { |
2872 | device->setDepthBufferEnable(true); |
2873 | device->setDepthCompare(es2sw::ConvertDepthComparison(mState.depthFunc)); |
2874 | } |
2875 | else |
2876 | { |
2877 | device->setDepthBufferEnable(false); |
2878 | } |
2879 | |
2880 | mDepthStateDirty = false; |
2881 | } |
2882 | |
2883 | if(mBlendStateDirty) |
2884 | { |
2885 | if(mState.blendEnabled) |
2886 | { |
2887 | device->setAlphaBlendEnable(true); |
2888 | device->setSeparateAlphaBlendEnable(true); |
2889 | |
2890 | device->setBlendConstant(es2sw::ConvertColor(mState.blendColor)); |
2891 | |
2892 | device->setSourceBlendFactor(es2sw::ConvertBlendFunc(mState.sourceBlendRGB)); |
2893 | device->setDestBlendFactor(es2sw::ConvertBlendFunc(mState.destBlendRGB)); |
2894 | device->setBlendOperation(es2sw::ConvertBlendOp(mState.blendEquationRGB)); |
2895 | |
2896 | device->setSourceBlendFactorAlpha(es2sw::ConvertBlendFunc(mState.sourceBlendAlpha)); |
2897 | device->setDestBlendFactorAlpha(es2sw::ConvertBlendFunc(mState.destBlendAlpha)); |
2898 | device->setBlendOperationAlpha(es2sw::ConvertBlendOp(mState.blendEquationAlpha)); |
2899 | } |
2900 | else |
2901 | { |
2902 | device->setAlphaBlendEnable(false); |
2903 | } |
2904 | |
2905 | mBlendStateDirty = false; |
2906 | } |
2907 | |
2908 | if(mStencilStateDirty || mFrontFaceDirty) |
2909 | { |
2910 | if(mState.stencilTestEnabled && framebuffer->hasStencil()) |
2911 | { |
2912 | device->setStencilEnable(true); |
2913 | device->setTwoSidedStencil(true); |
2914 | |
2915 | // get the maximum size of the stencil ref |
2916 | Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer(); |
2917 | GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1; |
2918 | |
2919 | if(mState.frontFace == GL_CCW) |
2920 | { |
2921 | device->setStencilWriteMask(mState.stencilWritemask); |
2922 | device->setStencilCompare(es2sw::ConvertStencilComparison(mState.stencilFunc)); |
2923 | |
2924 | device->setStencilReference((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil); |
2925 | device->setStencilMask(mState.stencilMask); |
2926 | |
2927 | device->setStencilFailOperation(es2sw::ConvertStencilOp(mState.stencilFail)); |
2928 | device->setStencilZFailOperation(es2sw::ConvertStencilOp(mState.stencilPassDepthFail)); |
2929 | device->setStencilPassOperation(es2sw::ConvertStencilOp(mState.stencilPassDepthPass)); |
2930 | |
2931 | device->setStencilWriteMaskCCW(mState.stencilBackWritemask); |
2932 | device->setStencilCompareCCW(es2sw::ConvertStencilComparison(mState.stencilBackFunc)); |
2933 | |
2934 | device->setStencilReferenceCCW((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil); |
2935 | device->setStencilMaskCCW(mState.stencilBackMask); |
2936 | |
2937 | device->setStencilFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilBackFail)); |
2938 | device->setStencilZFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilBackPassDepthFail)); |
2939 | device->setStencilPassOperationCCW(es2sw::ConvertStencilOp(mState.stencilBackPassDepthPass)); |
2940 | } |
2941 | else |
2942 | { |
2943 | device->setStencilWriteMaskCCW(mState.stencilWritemask); |
2944 | device->setStencilCompareCCW(es2sw::ConvertStencilComparison(mState.stencilFunc)); |
2945 | |
2946 | device->setStencilReferenceCCW((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil); |
2947 | device->setStencilMaskCCW(mState.stencilMask); |
2948 | |
2949 | device->setStencilFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilFail)); |
2950 | device->setStencilZFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilPassDepthFail)); |
2951 | device->setStencilPassOperationCCW(es2sw::ConvertStencilOp(mState.stencilPassDepthPass)); |
2952 | |
2953 | device->setStencilWriteMask(mState.stencilBackWritemask); |
2954 | device->setStencilCompare(es2sw::ConvertStencilComparison(mState.stencilBackFunc)); |
2955 | |
2956 | device->setStencilReference((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil); |
2957 | device->setStencilMask(mState.stencilBackMask); |
2958 | |
2959 | device->setStencilFailOperation(es2sw::ConvertStencilOp(mState.stencilBackFail)); |
2960 | device->setStencilZFailOperation(es2sw::ConvertStencilOp(mState.stencilBackPassDepthFail)); |
2961 | device->setStencilPassOperation(es2sw::ConvertStencilOp(mState.stencilBackPassDepthPass)); |
2962 | } |
2963 | } |
2964 | else |
2965 | { |
2966 | device->setStencilEnable(false); |
2967 | } |
2968 | |
2969 | mStencilStateDirty = false; |
2970 | mFrontFaceDirty = false; |
2971 | } |
2972 | |
2973 | if(mMaskStateDirty) |
2974 | { |
2975 | for(int i = 0; i < MAX_DRAW_BUFFERS; i++) |
2976 | { |
2977 | device->setColorWriteMask(i, es2sw::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha)); |
2978 | } |
2979 | |
2980 | device->setDepthWriteEnable(mState.depthMask); |
2981 | |
2982 | mMaskStateDirty = false; |
2983 | } |
2984 | |
2985 | if(mPolygonOffsetStateDirty) |
2986 | { |
2987 | if(mState.polygonOffsetFillEnabled) |
2988 | { |
2989 | Renderbuffer *depthbuffer = framebuffer->getDepthbuffer(); |
2990 | if(depthbuffer) |
2991 | { |
2992 | device->setSlopeDepthBias(mState.polygonOffsetFactor); |
2993 | float depthBias = ldexp(mState.polygonOffsetUnits, -23); // We use 32-bit floating-point for all depth formats, with 23 mantissa bits. |
2994 | device->setDepthBias(depthBias); |
2995 | } |
2996 | } |
2997 | else |
2998 | { |
2999 | device->setSlopeDepthBias(0); |
3000 | device->setDepthBias(0); |
3001 | } |
3002 | |
3003 | mPolygonOffsetStateDirty = false; |
3004 | } |
3005 | |
3006 | if(mSampleStateDirty) |
3007 | { |
3008 | if(mState.sampleAlphaToCoverageEnabled) |
3009 | { |
3010 | device->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE); |
3011 | } |
3012 | else |
3013 | { |
3014 | device->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE); |
3015 | } |
3016 | |
3017 | if(mState.sampleCoverageEnabled) |
3018 | { |
3019 | unsigned int mask = 0; |
3020 | if(mState.sampleCoverageValue != 0) |
3021 | { |
3022 | int width, height, samples; |
3023 | framebuffer->completeness(width, height, samples); |
3024 | |
3025 | float threshold = 0.5f; |
3026 | |
3027 | for(int i = 0; i < samples; i++) |
3028 | { |
3029 | mask <<= 1; |
3030 | |
3031 | if((i + 1) * mState.sampleCoverageValue >= threshold) |
3032 | { |
3033 | threshold += 1.0f; |
3034 | mask |= 1; |
3035 | } |
3036 | } |
3037 | } |
3038 | |
3039 | if(mState.sampleCoverageInvert) |
3040 | { |
3041 | mask = ~mask; |
3042 | } |
3043 | |
3044 | device->setMultiSampleMask(mask); |
3045 | } |
3046 | else |
3047 | { |
3048 | device->setMultiSampleMask(0xFFFFFFFF); |
3049 | } |
3050 | |
3051 | mSampleStateDirty = false; |
3052 | } |
3053 | |
3054 | if(mDitherStateDirty) |
3055 | { |
3056 | // UNIMPLEMENTED(); // FIXME |
3057 | |
3058 | mDitherStateDirty = false; |
3059 | } |
3060 | |
3061 | device->setRasterizerDiscard(mState.rasterizerDiscardEnabled); |
3062 | } |
3063 | |
3064 | GLenum Context::applyVertexBuffer(GLint base, GLint first, GLsizei count, GLsizei instanceId) |
3065 | { |
3066 | TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS]; |
3067 | |
3068 | GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes, instanceId); |
3069 | if(err != GL_NO_ERROR) |
3070 | { |
3071 | return err; |
3072 | } |
3073 | |
3074 | Program *program = getCurrentProgram(); |
3075 | |
3076 | device->resetInputStreams(false); |
3077 | |
3078 | for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) |
3079 | { |
3080 | if(program->getAttributeStream(i) == -1) |
3081 | { |
3082 | continue; |
3083 | } |
3084 | |
3085 | sw::Resource *resource = attributes[i].vertexBuffer; |
3086 | const void *buffer = (char*)resource->data() + attributes[i].offset; |
3087 | |
3088 | int stride = attributes[i].stride; |
3089 | |
3090 | buffer = (char*)buffer + stride * base; |
3091 | |
3092 | sw::Stream attribute(resource, buffer, stride); |
3093 | |
3094 | attribute.type = attributes[i].type; |
3095 | attribute.count = attributes[i].count; |
3096 | attribute.normalized = attributes[i].normalized; |
3097 | |
3098 | int stream = program->getAttributeStream(i); |
3099 | device->setInputStream(stream, attribute); |
3100 | } |
3101 | |
3102 | return GL_NO_ERROR; |
3103 | } |
3104 | |
3105 | // Applies the indices and element array bindings |
3106 | GLenum Context::applyIndexBuffer(const void *indices, GLuint start, GLuint end, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) |
3107 | { |
3108 | GLenum err = mIndexDataManager->prepareIndexData(mode, type, start, end, count, getCurrentVertexArray()->getElementArrayBuffer(), indices, indexInfo, isPrimitiveRestartFixedIndexEnabled()); |
3109 | |
3110 | if(err == GL_NO_ERROR) |
3111 | { |
3112 | device->setIndexBuffer(indexInfo->indexBuffer); |
3113 | } |
3114 | |
3115 | return err; |
3116 | } |
3117 | |
3118 | // Applies the shaders and shader constants |
3119 | void Context::applyShaders() |
3120 | { |
3121 | Program *programObject = getCurrentProgram(); |
3122 | sw::VertexShader *vertexShader = programObject->getVertexShader(); |
3123 | sw::PixelShader *pixelShader = programObject->getPixelShader(); |
3124 | |
3125 | device->setVertexShader(vertexShader); |
3126 | device->setPixelShader(pixelShader); |
3127 | |
3128 | if(programObject->getSerial() != mAppliedProgramSerial) |
3129 | { |
3130 | programObject->dirtyAllUniforms(); |
3131 | mAppliedProgramSerial = programObject->getSerial(); |
3132 | } |
3133 | |
3134 | programObject->applyTransformFeedback(device, getTransformFeedback()); |
3135 | programObject->applyUniformBuffers(device, mState.uniformBuffers); |
3136 | programObject->applyUniforms(device); |
3137 | } |
3138 | |
3139 | void Context::applyTextures() |
3140 | { |
3141 | applyTextures(sw::SAMPLER_PIXEL); |
3142 | applyTextures(sw::SAMPLER_VERTEX); |
3143 | } |
3144 | |
3145 | void Context::applyTextures(sw::SamplerType samplerType) |
3146 | { |
3147 | Program *programObject = getCurrentProgram(); |
3148 | |
3149 | int samplerCount = (samplerType == sw::SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS; // Range of samplers of given sampler type |
3150 | |
3151 | for(int samplerIndex = 0; samplerIndex < samplerCount; samplerIndex++) |
3152 | { |
3153 | int textureUnit = programObject->getSamplerMapping(samplerType, samplerIndex); // OpenGL texture image unit index |
3154 | |
3155 | if(textureUnit != -1) |
3156 | { |
3157 | TextureType textureType = programObject->getSamplerTextureType(samplerType, samplerIndex); |
3158 | |
3159 | Texture *texture = getSamplerTexture(textureUnit, textureType); |
3160 | Sampler *samplerObject = mState.sampler[textureUnit]; |
3161 | |
3162 | if(texture->isSamplerComplete(samplerObject)) |
3163 | { |
3164 | GLenum wrapS, wrapT, wrapR, minFilter, magFilter, compFunc, compMode; |
3165 | GLfloat minLOD, maxLOD, maxAnisotropy; |
3166 | |
3167 | if(samplerObject) |
3168 | { |
3169 | wrapS = samplerObject->getWrapS(); |
3170 | wrapT = samplerObject->getWrapT(); |
3171 | wrapR = samplerObject->getWrapR(); |
3172 | minFilter = samplerObject->getMinFilter(); |
3173 | magFilter = samplerObject->getMagFilter(); |
3174 | minLOD = samplerObject->getMinLod(); |
3175 | maxLOD = samplerObject->getMaxLod(); |
3176 | compFunc = samplerObject->getCompareFunc(); |
3177 | compMode = samplerObject->getCompareMode(); |
3178 | maxAnisotropy = samplerObject->getMaxAnisotropy(); |
3179 | } |
3180 | else |
3181 | { |
3182 | wrapS = texture->getWrapS(); |
3183 | wrapT = texture->getWrapT(); |
3184 | wrapR = texture->getWrapR(); |
3185 | minFilter = texture->getMinFilter(); |
3186 | magFilter = texture->getMagFilter(); |
3187 | minLOD = texture->getMinLOD(); |
3188 | maxLOD = texture->getMaxLOD(); |
3189 | compFunc = texture->getCompareFunc(); |
3190 | compMode = texture->getCompareMode(); |
3191 | maxAnisotropy = texture->getMaxAnisotropy(); |
3192 | } |
3193 | |
3194 | GLint baseLevel = texture->getBaseLevel(); |
3195 | GLint maxLevel = texture->getMaxLevel(); |
3196 | GLenum swizzleR = texture->getSwizzleR(); |
3197 | GLenum swizzleG = texture->getSwizzleG(); |
3198 | GLenum swizzleB = texture->getSwizzleB(); |
3199 | GLenum swizzleA = texture->getSwizzleA(); |
3200 | |
3201 | device->setAddressingModeU(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapS)); |
3202 | device->setAddressingModeV(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapT)); |
3203 | device->setAddressingModeW(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapR)); |
3204 | device->setCompareFunc(samplerType, samplerIndex, es2sw::ConvertCompareFunc(compFunc, compMode)); |
3205 | device->setSwizzleR(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleR)); |
3206 | device->setSwizzleG(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleG)); |
3207 | device->setSwizzleB(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleB)); |
3208 | device->setSwizzleA(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleA)); |
3209 | device->setMinLod(samplerType, samplerIndex, minLOD); |
3210 | device->setMaxLod(samplerType, samplerIndex, maxLOD); |
3211 | device->setBaseLevel(samplerType, samplerIndex, baseLevel); |
3212 | device->setMaxLevel(samplerType, samplerIndex, maxLevel); |
3213 | device->setTextureFilter(samplerType, samplerIndex, es2sw::ConvertTextureFilter(minFilter, magFilter, maxAnisotropy)); |
3214 | device->setMipmapFilter(samplerType, samplerIndex, es2sw::ConvertMipMapFilter(minFilter)); |
3215 | device->setMaxAnisotropy(samplerType, samplerIndex, maxAnisotropy); |
3216 | device->setHighPrecisionFiltering(samplerType, samplerIndex, mState.textureFilteringHint == GL_NICEST); |
3217 | device->setSyncRequired(samplerType, samplerIndex, texture->requiresSync()); |
3218 | |
3219 | applyTexture(samplerType, samplerIndex, texture); |
3220 | } |
3221 | else |
3222 | { |
3223 | applyTexture(samplerType, samplerIndex, nullptr); |
3224 | } |
3225 | } |
3226 | else |
3227 | { |
3228 | applyTexture(samplerType, samplerIndex, nullptr); |
3229 | } |
3230 | } |
3231 | } |
3232 | |
3233 | void Context::applyTexture(sw::SamplerType type, int index, Texture *baseTexture) |
3234 | { |
3235 | Program *program = getCurrentProgram(); |
3236 | int sampler = (type == sw::SAMPLER_PIXEL) ? index : 16 + index; |
3237 | bool textureUsed = false; |
3238 | |
3239 | if(type == sw::SAMPLER_PIXEL) |
3240 | { |
3241 | textureUsed = program->getPixelShader()->usesSampler(index); |
3242 | } |
3243 | else if(type == sw::SAMPLER_VERTEX) |
3244 | { |
3245 | textureUsed = program->getVertexShader()->usesSampler(index); |
3246 | } |
3247 | else UNREACHABLE(type); |
3248 | |
3249 | sw::Resource *resource = nullptr; |
3250 | |
3251 | if(baseTexture && textureUsed) |
3252 | { |
3253 | resource = baseTexture->getResource(); |
3254 | } |
3255 | |
3256 | device->setTextureResource(sampler, resource); |
3257 | |
3258 | if(baseTexture && textureUsed) |
3259 | { |
3260 | int baseLevel = baseTexture->getBaseLevel(); |
3261 | int maxLevel = std::min(baseTexture->getTopLevel(), baseTexture->getMaxLevel()); |
3262 | GLenum target = baseTexture->getTarget(); |
3263 | |
3264 | switch(target) |
3265 | { |
3266 | case GL_TEXTURE_2D: |
3267 | case GL_TEXTURE_EXTERNAL_OES: |
3268 | case GL_TEXTURE_RECTANGLE_ARB: |
3269 | { |
3270 | Texture2D *texture = static_cast<Texture2D*>(baseTexture); |
3271 | |
3272 | for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) |
3273 | { |
3274 | int surfaceLevel = mipmapLevel + baseLevel; |
3275 | |
3276 | if(surfaceLevel > maxLevel) |
3277 | { |
3278 | surfaceLevel = maxLevel; |
3279 | } |
3280 | |
3281 | egl::Image *surface = texture->getImage(surfaceLevel); |
3282 | device->setTextureLevel(sampler, 0, mipmapLevel, surface, |
3283 | (target == GL_TEXTURE_RECTANGLE_ARB) ? sw::TEXTURE_RECTANGLE : sw::TEXTURE_2D); |
3284 | } |
3285 | } |
3286 | break; |
3287 | case GL_TEXTURE_3D: |
3288 | { |
3289 | Texture3D *texture = static_cast<Texture3D*>(baseTexture); |
3290 | |
3291 | for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) |
3292 | { |
3293 | int surfaceLevel = mipmapLevel + baseLevel; |
3294 | |
3295 | if(surfaceLevel > maxLevel) |
3296 | { |
3297 | surfaceLevel = maxLevel; |
3298 | } |
3299 | |
3300 | egl::Image *surface = texture->getImage(surfaceLevel); |
3301 | device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_3D); |
3302 | } |
3303 | } |
3304 | break; |
3305 | case GL_TEXTURE_2D_ARRAY: |
3306 | { |
3307 | Texture2DArray *texture = static_cast<Texture2DArray*>(baseTexture); |
3308 | |
3309 | for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) |
3310 | { |
3311 | int surfaceLevel = mipmapLevel + baseLevel; |
3312 | |
3313 | if(surfaceLevel > maxLevel) |
3314 | { |
3315 | surfaceLevel = maxLevel; |
3316 | } |
3317 | |
3318 | egl::Image *surface = texture->getImage(surfaceLevel); |
3319 | device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D_ARRAY); |
3320 | } |
3321 | } |
3322 | break; |
3323 | case GL_TEXTURE_CUBE_MAP: |
3324 | { |
3325 | TextureCubeMap *cubeTexture = static_cast<TextureCubeMap*>(baseTexture); |
3326 | |
3327 | for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) |
3328 | { |
3329 | cubeTexture->updateBorders(mipmapLevel); |
3330 | |
3331 | for(int face = 0; face < 6; face++) |
3332 | { |
3333 | int surfaceLevel = mipmapLevel + baseLevel; |
3334 | |
3335 | if(surfaceLevel > maxLevel) |
3336 | { |
3337 | surfaceLevel = maxLevel; |
3338 | } |
3339 | |
3340 | egl::Image *surface = cubeTexture->getImage(face, surfaceLevel); |
3341 | device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE); |
3342 | } |
3343 | } |
3344 | } |
3345 | break; |
3346 | default: |
3347 | UNIMPLEMENTED(); |
3348 | break; |
3349 | } |
3350 | } |
3351 | else |
3352 | { |
3353 | device->setTextureLevel(sampler, 0, 0, 0, sw::TEXTURE_NULL); |
3354 | } |
3355 | } |
3356 | |
3357 | void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels) |
3358 | { |
3359 | Framebuffer *framebuffer = getReadFramebuffer(); |
3360 | int framebufferWidth, framebufferHeight, framebufferSamples; |
3361 | |
3362 | if(!framebuffer || (framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE)) |
3363 | { |
3364 | return error(GL_INVALID_FRAMEBUFFER_OPERATION); |
3365 | } |
3366 | |
3367 | if(getReadFramebufferName() != 0 && framebufferSamples != 0) |
3368 | { |
3369 | return error(GL_INVALID_OPERATION); |
3370 | } |
3371 | |
3372 | if(!ValidateReadPixelsFormatType(framebuffer, format, type)) |
3373 | { |
3374 | return; |
3375 | } |
3376 | |
3377 | GLsizei outputWidth = (mState.packParameters.rowLength > 0) ? mState.packParameters.rowLength : width; |
3378 | GLsizei outputPitch = gl::ComputePitch(outputWidth, format, type, mState.packParameters.alignment); |
3379 | GLsizei outputHeight = (mState.packParameters.imageHeight == 0) ? height : mState.packParameters.imageHeight; |
3380 | pixels = getPixelPackBuffer() ? (unsigned char*)getPixelPackBuffer()->data() + (ptrdiff_t)pixels : (unsigned char*)pixels; |
3381 | pixels = ((char*)pixels) + gl::ComputePackingOffset(format, type, outputWidth, outputHeight, mState.packParameters); |
3382 | |
3383 | // Sized query sanity check |
3384 | if(bufSize) |
3385 | { |
3386 | int requiredSize = outputPitch * height; |
3387 | if(requiredSize > *bufSize) |
3388 | { |
3389 | return error(GL_INVALID_OPERATION); |
3390 | } |
3391 | } |
3392 | |
3393 | egl::Image *renderTarget = nullptr; |
3394 | switch(format) |
3395 | { |
3396 | case GL_DEPTH_COMPONENT: // GL_NV_read_depth |
3397 | case GL_DEPTH_STENCIL_OES: // GL_NV_read_depth_stencil |
3398 | renderTarget = framebuffer->getDepthBuffer(); |
3399 | break; |
3400 | case GL_STENCIL_INDEX_OES: // GL_NV_read_stencil |
3401 | renderTarget = framebuffer->getStencilBuffer(); |
3402 | break; |
3403 | default: |
3404 | renderTarget = framebuffer->getReadRenderTarget(); |
3405 | break; |
3406 | } |
3407 | |
3408 | if(!renderTarget) |
3409 | { |
3410 | return error(GL_INVALID_OPERATION); |
3411 | } |
3412 | |
3413 | sw::SliceRectF srcRect((float)x, (float)y, (float)(x + width), (float)(y + height), 0); |
3414 | sw::SliceRect dstRect(0, 0, width, height, 0); |
3415 | srcRect.clip(0.0f, 0.0f, (float)renderTarget->getWidth(), (float)renderTarget->getHeight()); |
3416 | |
3417 | if(format != GL_DEPTH_STENCIL_OES) // The blitter only handles reading either depth or stencil. |
3418 | { |
3419 | sw::Surface *externalSurface = sw::Surface::create(width, height, 1, es2::ConvertReadFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight); |
3420 | device->blit(renderTarget, srcRect, externalSurface, dstRect, false, false, false); |
3421 | externalSurface->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); |
3422 | externalSurface->unlockExternal(); |
3423 | delete externalSurface; |
3424 | } |
3425 | else // format == GL_DEPTH_STENCIL_OES |
3426 | { |
3427 | ASSERT(renderTarget->getInternalFormat() == sw::FORMAT_D32F_LOCKABLE); |
3428 | float *depth = (float*)renderTarget->lockInternal((int)srcRect.x0, (int)srcRect.y0, 0, sw::LOCK_READONLY, sw::PUBLIC); |
3429 | uint8_t *stencil = (uint8_t*)renderTarget->lockStencil((int)srcRect.x0, (int)srcRect.y0, 0, sw::PUBLIC); |
3430 | |
3431 | switch(type) |
3432 | { |
3433 | case GL_UNSIGNED_INT_24_8_OES: |
3434 | { |
3435 | uint32_t *output = (uint32_t*)pixels; |
3436 | |
3437 | for(int y = 0; y < height; y++) |
3438 | { |
3439 | for(int x = 0; x < width; x++) |
3440 | { |
3441 | output[x] = ((uint32_t)roundf(depth[x] * 0xFFFFFF00) & 0xFFFFFF00) | stencil[x]; |
3442 | } |
3443 | |
3444 | depth += renderTarget->getInternalPitchP(); |
3445 | stencil += renderTarget->getStencilPitchB(); |
3446 | (uint8_t*&)output += outputPitch; |
3447 | } |
3448 | } |
3449 | break; |
3450 | case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: |
3451 | { |
3452 | struct D32FS8 { float depth32f; unsigned int stencil24_8; }; |
3453 | D32FS8 *output = (D32FS8*)pixels; |
3454 | |
3455 | for(int y = 0; y < height; y++) |
3456 | { |
3457 | for(int x = 0; x < width; x++) |
3458 | { |
3459 | output[x].depth32f = depth[x]; |
3460 | output[x].stencil24_8 = stencil[x]; |
3461 | } |
3462 | |
3463 | depth += renderTarget->getInternalPitchP(); |
3464 | stencil += renderTarget->getStencilPitchB(); |
3465 | (uint8_t*&)output += outputPitch; |
3466 | } |
3467 | } |
3468 | break; |
3469 | default: UNREACHABLE(type); |
3470 | } |
3471 | |
3472 | renderTarget->unlockInternal(); |
3473 | renderTarget->unlockStencil(); |
3474 | } |
3475 | |
3476 | renderTarget->release(); |
3477 | } |
3478 | |
3479 | void Context::clear(GLbitfield mask) |
3480 | { |
3481 | if(mState.rasterizerDiscardEnabled) |
3482 | { |
3483 | return; |
3484 | } |
3485 | |
3486 | Framebuffer *framebuffer = getDrawFramebuffer(); |
3487 | |
3488 | if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)) |
3489 | { |
3490 | return error(GL_INVALID_FRAMEBUFFER_OPERATION); |
3491 | } |
3492 | |
3493 | if(!applyRenderTarget()) |
3494 | { |
3495 | return; |
3496 | } |
3497 | |
3498 | if(mask & GL_COLOR_BUFFER_BIT) |
3499 | { |
3500 | unsigned int rgbaMask = getColorMask(); |
3501 | |
3502 | if(rgbaMask != 0) |
3503 | { |
3504 | device->clearColor(mState.colorClearValue.red, mState.colorClearValue.green, mState.colorClearValue.blue, mState.colorClearValue.alpha, rgbaMask); |
3505 | } |
3506 | } |
3507 | |
3508 | if(mask & GL_DEPTH_BUFFER_BIT) |
3509 | { |
3510 | if(mState.depthMask != 0) |
3511 | { |
3512 | float depth = clamp01(mState.depthClearValue); |
3513 | device->clearDepth(depth); |
3514 | } |
3515 | } |
3516 | |
3517 | if(mask & GL_STENCIL_BUFFER_BIT) |
3518 | { |
3519 | if(mState.stencilWritemask != 0) |
3520 | { |
3521 | int stencil = mState.stencilClearValue & 0x000000FF; |
3522 | device->clearStencil(stencil, mState.stencilWritemask); |
3523 | } |
3524 | } |
3525 | } |
3526 | |
3527 | void Context::clearColorBuffer(GLint drawbuffer, void *value, sw::Format format) |
3528 | { |
3529 | unsigned int rgbaMask = getColorMask(); |
3530 | if(rgbaMask && !mState.rasterizerDiscardEnabled) |
3531 | { |
3532 | Framebuffer *framebuffer = getDrawFramebuffer(); |
3533 | if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)) |
3534 | { |
3535 | return error(GL_INVALID_FRAMEBUFFER_OPERATION); |
3536 | } |
3537 | egl::Image *colorbuffer = framebuffer->getRenderTarget(drawbuffer); |
3538 | |
3539 | if(colorbuffer) |
3540 | { |
3541 | sw::Rect clearRect = colorbuffer->getRect(); |
3542 | |
3543 | if(mState.scissorTestEnabled) |
3544 | { |
3545 | clearRect.clip(mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight); |
3546 | } |
3547 | |
3548 | device->clear(value, format, colorbuffer, clearRect, rgbaMask); |
3549 | |
3550 | colorbuffer->release(); |
3551 | } |
3552 | } |
3553 | } |
3554 | |
3555 | void Context::clearColorBuffer(GLint drawbuffer, const GLint *value) |
3556 | { |
3557 | clearColorBuffer(drawbuffer, (void*)value, sw::FORMAT_A32B32G32R32I); |
3558 | } |
3559 | |
3560 | void Context::clearColorBuffer(GLint drawbuffer, const GLuint *value) |
3561 | { |
3562 | clearColorBuffer(drawbuffer, (void*)value, sw::FORMAT_A32B32G32R32UI); |
3563 | } |
3564 | |
3565 | void Context::clearColorBuffer(GLint drawbuffer, const GLfloat *value) |
3566 | { |
3567 | clearColorBuffer(drawbuffer, (void*)value, sw::FORMAT_A32B32G32R32F); |
3568 | } |
3569 | |
3570 | void Context::clearDepthBuffer(const GLfloat value) |
3571 | { |
3572 | if(mState.depthMask && !mState.rasterizerDiscardEnabled) |
3573 | { |
3574 | Framebuffer *framebuffer = getDrawFramebuffer(); |
3575 | if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)) |
3576 | { |
3577 | return error(GL_INVALID_FRAMEBUFFER_OPERATION); |
3578 | } |
3579 | egl::Image *depthbuffer = framebuffer->getDepthBuffer(); |
3580 | |
3581 | if(depthbuffer) |
3582 | { |
3583 | float depth = clamp01(value); |
3584 | sw::Rect clearRect = depthbuffer->getRect(); |
3585 | |
3586 | if(mState.scissorTestEnabled) |
3587 | { |
3588 | clearRect.clip(mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight); |
3589 | } |
3590 | |
3591 | depthbuffer->clearDepth(depth, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); |
3592 | |
3593 | depthbuffer->release(); |
3594 | } |
3595 | } |
3596 | } |
3597 | |
3598 | void Context::clearStencilBuffer(const GLint value) |
3599 | { |
3600 | if(mState.stencilWritemask && !mState.rasterizerDiscardEnabled) |
3601 | { |
3602 | Framebuffer *framebuffer = getDrawFramebuffer(); |
3603 | if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)) |
3604 | { |
3605 | return error(GL_INVALID_FRAMEBUFFER_OPERATION); |
3606 | } |
3607 | egl::Image *stencilbuffer = framebuffer->getStencilBuffer(); |
3608 | |
3609 | if(stencilbuffer) |
3610 | { |
3611 | unsigned char stencil = value < 0 ? 0 : static_cast<unsigned char>(value & 0x000000FF); |
3612 | sw::Rect clearRect = stencilbuffer->getRect(); |
3613 | |
3614 | if(mState.scissorTestEnabled) |
3615 | { |
3616 | clearRect.clip(mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight); |
3617 | } |
3618 | |
3619 | stencilbuffer->clearStencil(stencil, static_cast<unsigned char>(mState.stencilWritemask), clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); |
3620 | |
3621 | stencilbuffer->release(); |
3622 | } |
3623 | } |
3624 | } |
3625 | |
3626 | void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) |
3627 | { |
3628 | if(!applyRenderTarget()) |
3629 | { |
3630 | return; |
3631 | } |
3632 | |
3633 | if(mState.currentProgram == 0) |
3634 | { |
3635 | return; // Nothing to process. |
3636 | } |
3637 | |
3638 | sw::DrawType primitiveType; |
3639 | int primitiveCount; |
3640 | int verticesPerPrimitive; |
3641 | |
3642 | if(!es2sw::ConvertPrimitiveType(mode, count, GL_NONE, primitiveType, primitiveCount, verticesPerPrimitive)) |
3643 | { |
3644 | return error(GL_INVALID_ENUM); |
3645 | } |
3646 | |
3647 | applyState(mode); |
3648 | |
3649 | for(int i = 0; i < instanceCount; ++i) |
3650 | { |
3651 | device->setInstanceID(i); |
3652 | |
3653 | GLenum err = applyVertexBuffer(0, first, count, i); |
3654 | if(err != GL_NO_ERROR) |
3655 | { |
3656 | return error(err); |
3657 | } |
3658 | |
3659 | applyShaders(); |
3660 | applyTextures(); |
3661 | |
3662 | if(!getCurrentProgram()->validateSamplers(false)) |
3663 | { |
3664 | return error(GL_INVALID_OPERATION); |
3665 | } |
3666 | |
3667 | if(primitiveCount <= 0) |
3668 | { |
3669 | return; |
3670 | } |
3671 | |
3672 | TransformFeedback* transformFeedback = getTransformFeedback(); |
3673 | if(!cullSkipsDraw(mode) || (transformFeedback->isActive() && !transformFeedback->isPaused())) |
3674 | { |
3675 | device->drawPrimitive(primitiveType, primitiveCount); |
3676 | } |
3677 | if(transformFeedback) |
3678 | { |
3679 | transformFeedback->addVertexOffset(primitiveCount * verticesPerPrimitive); |
3680 | } |
3681 | } |
3682 | } |
3683 | |
3684 | void Context::drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount) |
3685 | { |
3686 | if(!applyRenderTarget()) |
3687 | { |
3688 | return; |
3689 | } |
3690 | |
3691 | if(mState.currentProgram == 0) |
3692 | { |
3693 | return; // Nothing to process. |
3694 | } |
3695 | |
3696 | if(count == 0) |
3697 | { |
3698 | return; |
3699 | } |
3700 | |
3701 | if(!indices && !getCurrentVertexArray()->getElementArrayBuffer()) |
3702 | { |
3703 | return error(GL_INVALID_OPERATION); |
3704 | } |
3705 | |
3706 | GLenum internalMode = mode; |
3707 | if(isPrimitiveRestartFixedIndexEnabled()) |
3708 | { |
3709 | switch(mode) |
3710 | { |
3711 | case GL_TRIANGLE_FAN: |
3712 | case GL_TRIANGLE_STRIP: |
3713 | internalMode = GL_TRIANGLES; |
3714 | break; |
3715 | case GL_LINE_LOOP: |
3716 | case GL_LINE_STRIP: |
3717 | internalMode = GL_LINES; |
3718 | break; |
3719 | default: |
3720 | break; |
3721 | } |
3722 | } |
3723 | |
3724 | sw::DrawType primitiveType; |
3725 | int primitiveCount; |
3726 | int verticesPerPrimitive; |
3727 | |
3728 | if(!es2sw::ConvertPrimitiveType(internalMode, count, type, primitiveType, primitiveCount, verticesPerPrimitive)) |
3729 | { |
3730 | return error(GL_INVALID_ENUM); |
3731 | } |
3732 | |
3733 | TranslatedIndexData indexInfo(primitiveCount); |
3734 | GLenum err = applyIndexBuffer(indices, start, end, count, mode, type, &indexInfo); |
3735 | if(err != GL_NO_ERROR) |
3736 | { |
3737 | return error(err); |
3738 | } |
3739 | |
3740 | applyState(internalMode); |
3741 | |
3742 | for(int i = 0; i < instanceCount; ++i) |
3743 | { |
3744 | device->setInstanceID(i); |
3745 | |
3746 | GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; |
3747 | err = applyVertexBuffer(-(int)indexInfo.minIndex, indexInfo.minIndex, vertexCount, i); |
3748 | if(err != GL_NO_ERROR) |
3749 | { |
3750 | return error(err); |
3751 | } |
3752 | |
3753 | applyShaders(); |
3754 | applyTextures(); |
3755 | |
3756 | if(!getCurrentProgram()->validateSamplers(false)) |
3757 | { |
3758 | return error(GL_INVALID_OPERATION); |
3759 | } |
3760 | |
3761 | if(primitiveCount <= 0) |
3762 | { |
3763 | return; |
3764 | } |
3765 | |
3766 | TransformFeedback* transformFeedback = getTransformFeedback(); |
3767 | if(!cullSkipsDraw(internalMode) || (transformFeedback->isActive() && !transformFeedback->isPaused())) |
3768 | { |
3769 | device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, indexInfo.primitiveCount); |
3770 | } |
3771 | if(transformFeedback) |
3772 | { |
3773 | transformFeedback->addVertexOffset(indexInfo.primitiveCount * verticesPerPrimitive); |
3774 | } |
3775 | } |
3776 | } |
3777 | |
3778 | void Context::blit(sw::Surface *source, const sw::SliceRect &sRect, sw::Surface *dest, const sw::SliceRect &dRect) |
3779 | { |
3780 | sw::SliceRectF sRectF((float)sRect.x0, (float)sRect.y0, (float)sRect.x1, (float)sRect.y1, sRect.slice); |
3781 | device->blit(source, sRectF, dest, dRect, false); |
3782 | } |
3783 | |
3784 | void Context::finish() |
3785 | { |
3786 | device->finish(); |
3787 | } |
3788 | |
3789 | void Context::flush() |
3790 | { |
3791 | // We don't queue anything without processing it as fast as possible |
3792 | } |
3793 | |
3794 | void Context::recordInvalidEnum() |
3795 | { |
3796 | mInvalidEnum = true; |
3797 | } |
3798 | |
3799 | void Context::recordInvalidValue() |
3800 | { |
3801 | mInvalidValue = true; |
3802 | } |
3803 | |
3804 | void Context::recordInvalidOperation() |
3805 | { |
3806 | mInvalidOperation = true; |
3807 | } |
3808 | |
3809 | void Context::recordOutOfMemory() |
3810 | { |
3811 | mOutOfMemory = true; |
3812 | } |
3813 | |
3814 | void Context::recordInvalidFramebufferOperation() |
3815 | { |
3816 | mInvalidFramebufferOperation = true; |
3817 | } |
3818 | |
3819 | // Get one of the recorded errors and clear its flag, if any. |
3820 | // [OpenGL ES 2.0.24] section 2.5 page 13. |
3821 | GLenum Context::getError() |
3822 | { |
3823 | if(mInvalidEnum) |
3824 | { |
3825 | mInvalidEnum = false; |
3826 | |
3827 | return GL_INVALID_ENUM; |
3828 | } |
3829 | |
3830 | if(mInvalidValue) |
3831 | { |
3832 | mInvalidValue = false; |
3833 | |
3834 | return GL_INVALID_VALUE; |
3835 | } |
3836 | |
3837 | if(mInvalidOperation) |
3838 | { |
3839 | mInvalidOperation = false; |
3840 | |
3841 | return GL_INVALID_OPERATION; |
3842 | } |
3843 | |
3844 | if(mOutOfMemory) |
3845 | { |
3846 | mOutOfMemory = false; |
3847 | |
3848 | return GL_OUT_OF_MEMORY; |
3849 | } |
3850 | |
3851 | if(mInvalidFramebufferOperation) |
3852 | { |
3853 | mInvalidFramebufferOperation = false; |
3854 | |
3855 | return GL_INVALID_FRAMEBUFFER_OPERATION; |
3856 | } |
3857 | |
3858 | return GL_NO_ERROR; |
3859 | } |
3860 | |
3861 | int Context::getSupportedMultisampleCount(int requested) |
3862 | { |
3863 | int supported = 0; |
3864 | |
3865 | for(int i = NUM_MULTISAMPLE_COUNTS - 1; i >= 0; i--) |
3866 | { |
3867 | if(supported >= requested) |
3868 | { |
3869 | return supported; |
3870 | } |
3871 | |
3872 | supported = multisampleCount[i]; |
3873 | } |
3874 | |
3875 | return supported; |
3876 | } |
3877 | |
3878 | void Context::detachBuffer(GLuint buffer) |
3879 | { |
3880 | // [OpenGL ES 2.0.24] section 2.9 page 22: |
3881 | // If a buffer object is deleted while it is bound, all bindings to that object in the current context |
3882 | // (i.e. in the thread that called Delete-Buffers) are reset to zero. |
3883 | |
3884 | if(mState.copyReadBuffer.name() == buffer) |
3885 | { |
3886 | mState.copyReadBuffer = nullptr; |
3887 | } |
3888 | |
3889 | if(mState.copyWriteBuffer.name() == buffer) |
3890 | { |
3891 | mState.copyWriteBuffer = nullptr; |
3892 | } |
3893 | |
3894 | if(mState.pixelPackBuffer.name() == buffer) |
3895 | { |
3896 | mState.pixelPackBuffer = nullptr; |
3897 | } |
3898 | |
3899 | if(mState.pixelUnpackBuffer.name() == buffer) |
3900 | { |
3901 | mState.pixelUnpackBuffer = nullptr; |
3902 | } |
3903 | |
3904 | if(mState.genericUniformBuffer.name() == buffer) |
3905 | { |
3906 | mState.genericUniformBuffer = nullptr; |
3907 | } |
3908 | if (mState.genericTransformFeedbackBuffer.name() == buffer) |
3909 | { |
3910 | mState.genericTransformFeedbackBuffer = nullptr; |
3911 | } |
3912 | |
3913 | if(getArrayBufferName() == buffer) |
3914 | { |
3915 | mState.arrayBuffer = nullptr; |
3916 | } |
3917 | |
3918 | // Only detach from the current transform feedback |
3919 | TransformFeedback* currentTransformFeedback = getTransformFeedback(); |
3920 | if(currentTransformFeedback) |
3921 | { |
3922 | currentTransformFeedback->detachBuffer(buffer); |
3923 | } |
3924 | |
3925 | // Only detach from the current vertex array |
3926 | VertexArray* currentVertexArray = getCurrentVertexArray(); |
3927 | if(currentVertexArray) |
3928 | { |
3929 | currentVertexArray->detachBuffer(buffer); |
3930 | } |
3931 | |
3932 | for(int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) |
3933 | { |
3934 | if(mState.vertexAttribute[attribute].mBoundBuffer.name() == buffer) |
3935 | { |
3936 | mState.vertexAttribute[attribute].mBoundBuffer = nullptr; |
3937 | } |
3938 | } |
3939 | } |
3940 | |
3941 | void Context::detachTexture(GLuint texture) |
3942 | { |
3943 | // [OpenGL ES 2.0.24] section 3.8 page 84: |
3944 | // If a texture object is deleted, it is as if all texture units which are bound to that texture object are |
3945 | // rebound to texture object zero |
3946 | |
3947 | for(int type = 0; type < TEXTURE_TYPE_COUNT; type++) |
3948 | { |
3949 | for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) |
3950 | { |
3951 | if(mState.samplerTexture[type][sampler].name() == texture) |
3952 | { |
3953 | mState.samplerTexture[type][sampler] = nullptr; |
3954 | } |
3955 | } |
3956 | } |
3957 | |
3958 | // [OpenGL ES 2.0.24] section 4.4 page 112: |
3959 | // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is |
3960 | // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this |
3961 | // image was attached in the currently bound framebuffer. |
3962 | |
3963 | Framebuffer *readFramebuffer = getReadFramebuffer(); |
3964 | Framebuffer *drawFramebuffer = getDrawFramebuffer(); |
3965 | |
3966 | if(readFramebuffer) |
3967 | { |
3968 | readFramebuffer->detachTexture(texture); |
3969 | } |
3970 | |
3971 | if(drawFramebuffer && drawFramebuffer != readFramebuffer) |
3972 | { |
3973 | drawFramebuffer->detachTexture(texture); |
3974 | } |
3975 | } |
3976 | |
3977 | void Context::detachFramebuffer(GLuint framebuffer) |
3978 | { |
3979 | // [OpenGL ES 2.0.24] section 4.4 page 107: |
3980 | // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though |
3981 | // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. |
3982 | |
3983 | if(mState.readFramebuffer == framebuffer) |
3984 | { |
3985 | bindReadFramebuffer(0); |
3986 | } |
3987 | |
3988 | if(mState.drawFramebuffer == framebuffer) |
3989 | { |
3990 | bindDrawFramebuffer(0); |
3991 | } |
3992 | } |
3993 | |
3994 | void Context::detachRenderbuffer(GLuint renderbuffer) |
3995 | { |
3996 | // [OpenGL ES 2.0.24] section 4.4 page 109: |
3997 | // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer |
3998 | // had been executed with the target RENDERBUFFER and name of zero. |
3999 | |
4000 | if(mState.renderbuffer.name() == renderbuffer) |
4001 | { |
4002 | bindRenderbuffer(0); |
4003 | } |
4004 | |
4005 | // [OpenGL ES 2.0.24] section 4.4 page 111: |
4006 | // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, |
4007 | // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment |
4008 | // point to which this image was attached in the currently bound framebuffer. |
4009 | |
4010 | Framebuffer *readFramebuffer = getReadFramebuffer(); |
4011 | Framebuffer *drawFramebuffer = getDrawFramebuffer(); |
4012 | |
4013 | if(readFramebuffer) |
4014 | { |
4015 | readFramebuffer->detachRenderbuffer(renderbuffer); |
4016 | } |
4017 | |
4018 | if(drawFramebuffer && drawFramebuffer != readFramebuffer) |
4019 | { |
4020 | drawFramebuffer->detachRenderbuffer(renderbuffer); |
4021 | } |
4022 | } |
4023 | |
4024 | void Context::detachSampler(GLuint sampler) |
4025 | { |
4026 | // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124: |
4027 | // If a sampler object that is currently bound to one or more texture units is |
4028 | // deleted, it is as though BindSampler is called once for each texture unit to |
4029 | // which the sampler is bound, with unit set to the texture unit and sampler set to zero. |
4030 | for(size_t textureUnit = 0; textureUnit < MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++textureUnit) |
4031 | { |
4032 | gl::BindingPointer<Sampler> &samplerBinding = mState.sampler[textureUnit]; |
4033 | if(samplerBinding.name() == sampler) |
4034 | { |
4035 | samplerBinding = nullptr; |
4036 | } |
4037 | } |
4038 | } |
4039 | |
4040 | bool Context::cullSkipsDraw(GLenum drawMode) |
4041 | { |
4042 | return mState.cullFaceEnabled && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode); |
4043 | } |
4044 | |
4045 | bool Context::isTriangleMode(GLenum drawMode) |
4046 | { |
4047 | switch(drawMode) |
4048 | { |
4049 | case GL_TRIANGLES: |
4050 | case GL_TRIANGLE_FAN: |
4051 | case GL_TRIANGLE_STRIP: |
4052 | return true; |
4053 | case GL_POINTS: |
4054 | case GL_LINES: |
4055 | case GL_LINE_LOOP: |
4056 | case GL_LINE_STRIP: |
4057 | return false; |
4058 | default: UNREACHABLE(drawMode); |
4059 | } |
4060 | |
4061 | return false; |
4062 | } |
4063 | |
4064 | void Context::setVertexAttrib(GLuint index, const GLfloat *values) |
4065 | { |
4066 | ASSERT(index < MAX_VERTEX_ATTRIBS); |
4067 | |
4068 | mState.vertexAttribute[index].setCurrentValue(values); |
4069 | |
4070 | mVertexDataManager->dirtyCurrentValue(index); |
4071 | } |
4072 | |
4073 | void Context::setVertexAttrib(GLuint index, const GLint *values) |
4074 | { |
4075 | ASSERT(index < MAX_VERTEX_ATTRIBS); |
4076 | |
4077 | mState.vertexAttribute[index].setCurrentValue(values); |
4078 | |
4079 | mVertexDataManager->dirtyCurrentValue(index); |
4080 | } |
4081 | |
4082 | void Context::setVertexAttrib(GLuint index, const GLuint *values) |
4083 | { |
4084 | ASSERT(index < MAX_VERTEX_ATTRIBS); |
4085 | |
4086 | mState.vertexAttribute[index].setCurrentValue(values); |
4087 | |
4088 | mVertexDataManager->dirtyCurrentValue(index); |
4089 | } |
4090 | |
4091 | void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, |
4092 | GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, |
4093 | GLbitfield mask, bool filter, bool allowPartialDepthStencilBlit) |
4094 | { |
4095 | Framebuffer *readFramebuffer = getReadFramebuffer(); |
4096 | Framebuffer *drawFramebuffer = getDrawFramebuffer(); |
4097 | |
4098 | int readBufferWidth, readBufferHeight, readBufferSamples; |
4099 | int drawBufferWidth, drawBufferHeight, drawBufferSamples; |
4100 | |
4101 | if(!readFramebuffer || (readFramebuffer->completeness(readBufferWidth, readBufferHeight, readBufferSamples) != GL_FRAMEBUFFER_COMPLETE) || |
4102 | !drawFramebuffer || (drawFramebuffer->completeness(drawBufferWidth, drawBufferHeight, drawBufferSamples) != GL_FRAMEBUFFER_COMPLETE)) |
4103 | { |
4104 | return error(GL_INVALID_FRAMEBUFFER_OPERATION); |
4105 | } |
4106 | |
4107 | if(drawBufferSamples > 1) |
4108 | { |
4109 | return error(GL_INVALID_OPERATION); |
4110 | } |
4111 | |
4112 | sw::SliceRect sourceRect; |
4113 | sw::SliceRect destRect; |
4114 | bool flipX = (srcX0 < srcX1) ^ (dstX0 < dstX1); |
4115 | bool flipY = (srcY0 < srcY1) ^ (dstY0 < dstY1); |
4116 | |
4117 | if(srcX0 < srcX1) |
4118 | { |
4119 | sourceRect.x0 = srcX0; |
4120 | sourceRect.x1 = srcX1; |
4121 | } |
4122 | else |
4123 | { |
4124 | sourceRect.x0 = srcX1; |
4125 | sourceRect.x1 = srcX0; |
4126 | } |
4127 | |
4128 | if(dstX0 < dstX1) |
4129 | { |
4130 | destRect.x0 = dstX0; |
4131 | destRect.x1 = dstX1; |
4132 | } |
4133 | else |
4134 | { |
4135 | destRect.x0 = dstX1; |
4136 | destRect.x1 = dstX0; |
4137 | } |
4138 | |
4139 | if(srcY0 < srcY1) |
4140 | { |
4141 | sourceRect.y0 = srcY0; |
4142 | sourceRect.y1 = srcY1; |
4143 | } |
4144 | else |
4145 | { |
4146 | sourceRect.y0 = srcY1; |
4147 | sourceRect.y1 = srcY0; |
4148 | } |
4149 | |
4150 | if(dstY0 < dstY1) |
4151 | { |
4152 | destRect.y0 = dstY0; |
4153 | destRect.y1 = dstY1; |
4154 | } |
4155 | else |
4156 | { |
4157 | destRect.y0 = dstY1; |
4158 | destRect.y1 = dstY0; |
4159 | } |
4160 | |
4161 | sw::RectF sourceScissoredRect(static_cast<float>(sourceRect.x0), static_cast<float>(sourceRect.y0), |
4162 | static_cast<float>(sourceRect.x1), static_cast<float>(sourceRect.y1)); |
4163 | sw::Rect destScissoredRect = destRect; |
4164 | |
4165 | if(mState.scissorTestEnabled) // Only write to parts of the destination framebuffer which pass the scissor test |
4166 | { |
4167 | sw::Rect scissorRect(mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight); |
4168 | if (!Device::ClipDstRect(sourceScissoredRect, destScissoredRect, scissorRect, flipX, flipY)) |
4169 | { |
4170 | // Failed to clip, blitting can't happen. |
4171 | return error(GL_INVALID_OPERATION); |
4172 | } |
4173 | } |
4174 | |
4175 | sw::SliceRectF sourceTrimmedRect = sourceScissoredRect; |
4176 | sw::SliceRect destTrimmedRect = destScissoredRect; |
4177 | |
4178 | // The source & destination rectangles also may need to be trimmed if |
4179 | // they fall out of the bounds of the actual draw and read surfaces. |
4180 | sw::Rect sourceTrimRect(0, 0, readBufferWidth, readBufferHeight); |
4181 | if (!Device::ClipSrcRect(sourceTrimmedRect, destTrimmedRect, sourceTrimRect, flipX, flipY)) |
4182 | { |
4183 | // Failed to clip, blitting can't happen. |
4184 | return error(GL_INVALID_OPERATION); |
4185 | } |
4186 | |
4187 | sw::Rect destTrimRect(0, 0, drawBufferWidth, drawBufferHeight); |
4188 | if (!Device::ClipDstRect(sourceTrimmedRect, destTrimmedRect, destTrimRect, flipX, flipY)) |
4189 | { |
4190 | // Failed to clip, blitting can't happen. |
4191 | return error(GL_INVALID_OPERATION); |
4192 | } |
4193 | |
4194 | bool partialBufferCopy = false; |
4195 | |
4196 | if(sourceTrimmedRect.y1 - sourceTrimmedRect.y0 < readBufferHeight || |
4197 | sourceTrimmedRect.x1 - sourceTrimmedRect.x0 < readBufferWidth || |
4198 | destTrimmedRect.y1 - destTrimmedRect.y0 < drawBufferHeight || |
4199 | destTrimmedRect.x1 - destTrimmedRect.x0 < drawBufferWidth || |
4200 | sourceTrimmedRect.y0 != 0 || destTrimmedRect.y0 != 0 || sourceTrimmedRect.x0 != 0 || destTrimmedRect.x0 != 0) |
4201 | { |
4202 | partialBufferCopy = true; |
4203 | } |
4204 | |
4205 | bool sameBounds = (srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1); |
4206 | bool blitRenderTarget = false; |
4207 | bool blitDepth = false; |
4208 | bool blitStencil = false; |
4209 | |
4210 | if(mask & GL_COLOR_BUFFER_BIT) |
4211 | { |
4212 | GLenum readColorbufferType = readFramebuffer->getReadBufferType(); |
4213 | GLenum drawColorbufferType = drawFramebuffer->getColorbufferType(0); |
4214 | const bool validReadType = readColorbufferType == GL_TEXTURE_2D || readColorbufferType == GL_TEXTURE_RECTANGLE_ARB || readColorbufferType == GL_TEXTURE_2D_ARRAY || readColorbufferType == GL_TEXTURE_3D || Framebuffer::IsRenderbuffer(readColorbufferType); |
4215 | const bool validDrawType = drawColorbufferType == GL_TEXTURE_2D || drawColorbufferType == GL_TEXTURE_RECTANGLE_ARB || readColorbufferType == GL_TEXTURE_2D_ARRAY || readColorbufferType == GL_TEXTURE_3D || Framebuffer::IsRenderbuffer(drawColorbufferType); |
4216 | if(!validReadType || !validDrawType) |
4217 | { |
4218 | return error(GL_INVALID_OPERATION); |
4219 | } |
4220 | |
4221 | if(partialBufferCopy && readBufferSamples > 1 && !sameBounds) |
4222 | { |
4223 | return error(GL_INVALID_OPERATION); |
4224 | } |
4225 | |
4226 | // The GL ES 3.0.2 spec (pg 193) states that: |
4227 | // 1) If the read buffer is fixed point format, the draw buffer must be as well |
4228 | // 2) If the read buffer is an unsigned integer format, the draw buffer must be |
4229 | // as well |
4230 | // 3) If the read buffer is a signed integer format, the draw buffer must be as |
4231 | // well |
4232 | es2::Renderbuffer *readRenderbuffer = readFramebuffer->getReadColorbuffer(); |
4233 | es2::Renderbuffer *drawRenderbuffer = drawFramebuffer->getColorbuffer(0); |
4234 | GLint readFormat = readRenderbuffer->getFormat(); |
4235 | GLint drawFormat = drawRenderbuffer->getFormat(); |
4236 | GLenum readComponentType = GetComponentType(readFormat, GL_COLOR_ATTACHMENT0); |
4237 | GLenum drawComponentType = GetComponentType(drawFormat, GL_COLOR_ATTACHMENT0); |
4238 | bool readFixedPoint = ((readComponentType == GL_UNSIGNED_NORMALIZED) || |
4239 | (readComponentType == GL_SIGNED_NORMALIZED)); |
4240 | bool drawFixedPoint = ((drawComponentType == GL_UNSIGNED_NORMALIZED) || |
4241 | (drawComponentType == GL_SIGNED_NORMALIZED)); |
4242 | bool readFixedOrFloat = (readFixedPoint || (readComponentType == GL_FLOAT)); |
4243 | bool drawFixedOrFloat = (drawFixedPoint || (drawComponentType == GL_FLOAT)); |
4244 | |
4245 | if(readFixedOrFloat != drawFixedOrFloat) |
4246 | { |
4247 | return error(GL_INVALID_OPERATION); |
4248 | } |
4249 | |
4250 | if((readComponentType == GL_UNSIGNED_INT) && (drawComponentType != GL_UNSIGNED_INT)) |
4251 | { |
4252 | return error(GL_INVALID_OPERATION); |
4253 | } |
4254 | |
4255 | if((readComponentType == GL_INT) && (drawComponentType != GL_INT)) |
4256 | { |
4257 | return error(GL_INVALID_OPERATION); |
4258 | } |
4259 | |
4260 | // Cannot filter integer data |
4261 | if(((readComponentType == GL_UNSIGNED_INT) || (readComponentType == GL_INT)) && filter) |
4262 | { |
4263 | return error(GL_INVALID_OPERATION); |
4264 | } |
4265 | |
4266 | if((readRenderbuffer->getSamples() > 0) && (readFormat != drawFormat)) |
4267 | { |
4268 | // RGBA8 and BGRA8 should be interchangeable here |
4269 | if(!(((readFormat == GL_RGBA8) && (drawFormat == GL_BGRA8_EXT)) || |
4270 | ((readFormat == GL_BGRA8_EXT) && (drawFormat == GL_RGBA8)))) |
4271 | { |
4272 | return error(GL_INVALID_OPERATION); |
4273 | } |
4274 | } |
4275 | |
4276 | blitRenderTarget = true; |
4277 | } |
4278 | |
4279 | if(mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) |
4280 | { |
4281 | Renderbuffer *readDSBuffer = nullptr; |
4282 | Renderbuffer *drawDSBuffer = nullptr; |
4283 | |
4284 | if(mask & GL_DEPTH_BUFFER_BIT) |
4285 | { |
4286 | if(readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer()) |
4287 | { |
4288 | GLenum readDepthBufferType = readFramebuffer->getDepthbufferType(); |
4289 | GLenum drawDepthBufferType = drawFramebuffer->getDepthbufferType(); |
4290 | if((readDepthBufferType != drawDepthBufferType) && |
4291 | !(Framebuffer::IsRenderbuffer(readDepthBufferType) && Framebuffer::IsRenderbuffer(drawDepthBufferType))) |
4292 | { |
4293 | return error(GL_INVALID_OPERATION); |
4294 | } |
4295 | |
4296 | blitDepth = true; |
4297 | readDSBuffer = readFramebuffer->getDepthbuffer(); |
4298 | drawDSBuffer = drawFramebuffer->getDepthbuffer(); |
4299 | |
4300 | if(readDSBuffer->getFormat() != drawDSBuffer->getFormat()) |
4301 | { |
4302 | return error(GL_INVALID_OPERATION); |
4303 | } |
4304 | } |
4305 | } |
4306 | |
4307 | if(mask & GL_STENCIL_BUFFER_BIT) |
4308 | { |
4309 | if(readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer()) |
4310 | { |
4311 | GLenum readStencilBufferType = readFramebuffer->getStencilbufferType(); |
4312 | GLenum drawStencilBufferType = drawFramebuffer->getStencilbufferType(); |
4313 | if((readStencilBufferType != drawStencilBufferType) && |
4314 | !(Framebuffer::IsRenderbuffer(readStencilBufferType) && Framebuffer::IsRenderbuffer(drawStencilBufferType))) |
4315 | { |
4316 | return error(GL_INVALID_OPERATION); |
4317 | } |
4318 | |
4319 | blitStencil = true; |
4320 | readDSBuffer = readFramebuffer->getStencilbuffer(); |
4321 | drawDSBuffer = drawFramebuffer->getStencilbuffer(); |
4322 | |
4323 | if(readDSBuffer->getFormat() != drawDSBuffer->getFormat()) |
4324 | { |
4325 | return error(GL_INVALID_OPERATION); |
4326 | } |
4327 | } |
4328 | } |
4329 | |
4330 | if(partialBufferCopy && !allowPartialDepthStencilBlit) |
4331 | { |
4332 | ERR("Only whole-buffer depth and stencil blits are supported by ANGLE_framebuffer_blit." ); |
4333 | return error(GL_INVALID_OPERATION); // Only whole-buffer copies are permitted |
4334 | } |
4335 | |
4336 | // OpenGL ES 3.0.4 spec, p.199: |
4337 | // ...an INVALID_OPERATION error is generated if the formats of the read |
4338 | // and draw framebuffers are not identical or if the source and destination |
4339 | // rectangles are not defined with the same(X0, Y 0) and (X1, Y 1) bounds. |
4340 | // If SAMPLE_BUFFERS for the draw framebuffer is greater than zero, an |
4341 | // INVALID_OPERATION error is generated. |
4342 | if((drawDSBuffer && drawDSBuffer->getSamples() > 1) || |
4343 | ((readDSBuffer && readDSBuffer->getSamples() > 1) && |
4344 | (!sameBounds || (drawDSBuffer->getFormat() != readDSBuffer->getFormat())))) |
4345 | { |
4346 | return error(GL_INVALID_OPERATION); |
4347 | } |
4348 | } |
4349 | |
4350 | if(blitRenderTarget || blitDepth || blitStencil) |
4351 | { |
4352 | if(flipX) |
4353 | { |
4354 | swap(destTrimmedRect.x0, destTrimmedRect.x1); |
4355 | } |
4356 | if(flipY) |
4357 | { |
4358 | swap(destTrimmedRect.y0, destTrimmedRect.y1); |
4359 | } |
4360 | |
4361 | if(blitRenderTarget) |
4362 | { |
4363 | egl::Image *readRenderTarget = readFramebuffer->getReadRenderTarget(); |
4364 | egl::Image *drawRenderTarget = drawFramebuffer->getRenderTarget(0); |
4365 | |
4366 | bool success = device->stretchRect(readRenderTarget, &sourceTrimmedRect, drawRenderTarget, &destTrimmedRect, (filter ? Device::USE_FILTER : 0) | Device::COLOR_BUFFER); |
4367 | |
4368 | readRenderTarget->release(); |
4369 | drawRenderTarget->release(); |
4370 | |
4371 | if(!success) |
4372 | { |
4373 | ERR("BlitFramebuffer failed." ); |
4374 | return; |
4375 | } |
4376 | } |
4377 | |
4378 | if(blitDepth) |
4379 | { |
4380 | egl::Image *readRenderTarget = readFramebuffer->getDepthBuffer(); |
4381 | egl::Image *drawRenderTarget = drawFramebuffer->getDepthBuffer(); |
4382 | |
4383 | bool success = device->stretchRect(readRenderTarget, &sourceTrimmedRect, drawRenderTarget, &destTrimmedRect, (filter ? Device::USE_FILTER : 0) | Device::DEPTH_BUFFER); |
4384 | |
4385 | readRenderTarget->release(); |
4386 | drawRenderTarget->release(); |
4387 | |
4388 | if(!success) |
4389 | { |
4390 | ERR("BlitFramebuffer failed." ); |
4391 | return; |
4392 | } |
4393 | } |
4394 | |
4395 | if(blitStencil) |
4396 | { |
4397 | egl::Image *readRenderTarget = readFramebuffer->getStencilBuffer(); |
4398 | egl::Image *drawRenderTarget = drawFramebuffer->getStencilBuffer(); |
4399 | |
4400 | bool success = device->stretchRect(readRenderTarget, &sourceTrimmedRect, drawRenderTarget, &destTrimmedRect, (filter ? Device::USE_FILTER : 0) | Device::STENCIL_BUFFER); |
4401 | |
4402 | readRenderTarget->release(); |
4403 | drawRenderTarget->release(); |
4404 | |
4405 | if(!success) |
4406 | { |
4407 | ERR("BlitFramebuffer failed." ); |
4408 | return; |
4409 | } |
4410 | } |
4411 | } |
4412 | } |
4413 | |
4414 | void Context::bindTexImage(gl::Surface *surface) |
4415 | { |
4416 | bool isRect = (surface->getTextureTarget() == EGL_TEXTURE_RECTANGLE_ANGLE); |
4417 | es2::Texture2D *textureObject = isRect ? getTexture2DRect() : getTexture2D(); |
4418 | |
4419 | if(textureObject) |
4420 | { |
4421 | textureObject->bindTexImage(surface); |
4422 | } |
4423 | } |
4424 | |
4425 | EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel) |
4426 | { |
4427 | GLenum textureTarget = GL_NONE; |
4428 | |
4429 | switch(target) |
4430 | { |
4431 | case EGL_GL_TEXTURE_2D_KHR: textureTarget = GL_TEXTURE_2D; break; |
4432 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; break; |
4433 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; break; |
4434 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; break; |
4435 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; break; |
4436 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; break; |
4437 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; break; |
4438 | case EGL_GL_RENDERBUFFER_KHR: |
4439 | break; |
4440 | default: |
4441 | return EGL_BAD_PARAMETER; |
4442 | } |
4443 | |
4444 | if(textureLevel >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS) |
4445 | { |
4446 | return EGL_BAD_MATCH; |
4447 | } |
4448 | |
4449 | if(textureTarget != GL_NONE) |
4450 | { |
4451 | es2::Texture *texture = getTexture(name); |
4452 | |
4453 | if(!texture) |
4454 | { |
4455 | return EGL_BAD_PARAMETER; |
4456 | } |
4457 | |
4458 | if (texture->getTarget() != GL_TEXTURE_CUBE_MAP && texture->getTarget() != textureTarget) |
4459 | { |
4460 | return EGL_BAD_PARAMETER; |
4461 | } |
4462 | |
4463 | if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !IsCubemapTextureTarget(textureTarget)) |
4464 | { |
4465 | return EGL_BAD_PARAMETER; |
4466 | } |
4467 | |
4468 | if(texture->isShared(textureTarget, textureLevel)) // Bound to an EGLSurface or already an EGLImage sibling |
4469 | { |
4470 | return EGL_BAD_ACCESS; |
4471 | } |
4472 | |
4473 | if(textureLevel != 0 && !texture->isSamplerComplete(nullptr)) |
4474 | { |
4475 | return EGL_BAD_PARAMETER; |
4476 | } |
4477 | |
4478 | if(textureLevel == 0 && !texture->isSamplerComplete(nullptr) && texture->hasNonBaseLevels()) |
4479 | { |
4480 | return EGL_BAD_PARAMETER; |
4481 | } |
4482 | } |
4483 | else if(target == EGL_GL_RENDERBUFFER_KHR) |
4484 | { |
4485 | es2::Renderbuffer *renderbuffer = getRenderbuffer(name); |
4486 | |
4487 | if(!renderbuffer) |
4488 | { |
4489 | return EGL_BAD_PARAMETER; |
4490 | } |
4491 | |
4492 | if(renderbuffer->isShared()) // Already an EGLImage sibling |
4493 | { |
4494 | return EGL_BAD_ACCESS; |
4495 | } |
4496 | } |
4497 | else UNREACHABLE(target); |
4498 | |
4499 | return EGL_SUCCESS; |
4500 | } |
4501 | |
4502 | egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textureLevel) |
4503 | { |
4504 | GLenum textureTarget = GL_NONE; |
4505 | |
4506 | switch(target) |
4507 | { |
4508 | case EGL_GL_TEXTURE_2D_KHR: textureTarget = GL_TEXTURE_2D; break; |
4509 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; break; |
4510 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; break; |
4511 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; break; |
4512 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; break; |
4513 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; break; |
4514 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; break; |
4515 | } |
4516 | |
4517 | if(textureTarget != GL_NONE) |
4518 | { |
4519 | es2::Texture *texture = getTexture(name); |
4520 | |
4521 | return texture->createSharedImage(textureTarget, textureLevel); |
4522 | } |
4523 | else if(target == EGL_GL_RENDERBUFFER_KHR) |
4524 | { |
4525 | es2::Renderbuffer *renderbuffer = getRenderbuffer(name); |
4526 | |
4527 | return renderbuffer->createSharedImage(); |
4528 | } |
4529 | else UNREACHABLE(target); |
4530 | |
4531 | return nullptr; |
4532 | } |
4533 | |
4534 | egl::Image *Context::getSharedImage(GLeglImageOES image) |
4535 | { |
4536 | return display->getSharedImage(image); |
4537 | } |
4538 | |
4539 | Device *Context::getDevice() |
4540 | { |
4541 | return device; |
4542 | } |
4543 | |
4544 | const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const |
4545 | { |
4546 | // Keep list sorted in following order: |
4547 | // OES extensions |
4548 | // EXT extensions |
4549 | // Vendor extensions |
4550 | static const char *extensions[] = |
4551 | { |
4552 | "GL_OES_compressed_ETC1_RGB8_texture" , |
4553 | "GL_OES_depth24" , |
4554 | "GL_OES_depth32" , |
4555 | "GL_OES_depth_texture" , |
4556 | "GL_OES_depth_texture_cube_map" , |
4557 | "GL_OES_EGL_image" , |
4558 | "GL_OES_EGL_image_external" , |
4559 | "GL_OES_EGL_image_external_essl3" , // client version is always 3, so this is fine |
4560 | "GL_OES_EGL_sync" , |
4561 | "GL_OES_element_index_uint" , |
4562 | "GL_OES_fbo_render_mipmap" , |
4563 | "GL_OES_framebuffer_object" , |
4564 | "GL_OES_packed_depth_stencil" , |
4565 | "GL_OES_rgb8_rgba8" , |
4566 | "GL_OES_standard_derivatives" , |
4567 | "GL_OES_surfaceless_context" , |
4568 | "GL_OES_texture_float" , |
4569 | "GL_OES_texture_float_linear" , |
4570 | "GL_OES_texture_half_float" , |
4571 | "GL_OES_texture_half_float_linear" , |
4572 | "GL_OES_texture_npot" , |
4573 | "GL_OES_texture_3D" , |
4574 | "GL_OES_vertex_array_object" , |
4575 | "GL_OES_vertex_half_float" , |
4576 | "GL_EXT_blend_minmax" , |
4577 | "GL_EXT_color_buffer_float" , // OpenGL ES 3.0 specific. |
4578 | "GL_EXT_color_buffer_half_float" , |
4579 | "GL_EXT_draw_buffers" , |
4580 | "GL_EXT_float_blend" , |
4581 | "GL_EXT_instanced_arrays" , |
4582 | "GL_EXT_occlusion_query_boolean" , |
4583 | "GL_EXT_read_format_bgra" , |
4584 | "GL_EXT_texture_compression_dxt1" , |
4585 | "GL_EXT_texture_filter_anisotropic" , |
4586 | "GL_EXT_texture_format_BGRA8888" , |
4587 | "GL_EXT_texture_rg" , |
4588 | #if (ASTC_SUPPORT) |
4589 | "GL_KHR_texture_compression_astc_hdr" , |
4590 | "GL_KHR_texture_compression_astc_ldr" , |
4591 | #endif |
4592 | "GL_ARB_texture_rectangle" , |
4593 | "GL_ANGLE_framebuffer_blit" , |
4594 | "GL_ANGLE_framebuffer_multisample" , |
4595 | "GL_ANGLE_instanced_arrays" , |
4596 | "GL_ANGLE_texture_compression_dxt3" , |
4597 | "GL_ANGLE_texture_compression_dxt5" , |
4598 | "GL_APPLE_texture_format_BGRA8888" , |
4599 | "GL_CHROMIUM_color_buffer_float_rgba" , // A subset of EXT_color_buffer_float on top of OpenGL ES 2.0 |
4600 | "GL_CHROMIUM_texture_filtering_hint" , |
4601 | "GL_NV_depth_buffer_float2" , |
4602 | "GL_NV_fence" , |
4603 | "GL_NV_framebuffer_blit" , |
4604 | "GL_NV_read_depth" , |
4605 | "GL_NV_read_depth_stencil" , |
4606 | "GL_NV_read_stencil" , |
4607 | }; |
4608 | |
4609 | GLuint numExtensions = sizeof(extensions) / sizeof(extensions[0]); |
4610 | |
4611 | if(numExt) |
4612 | { |
4613 | *numExt = numExtensions; |
4614 | |
4615 | return nullptr; |
4616 | } |
4617 | |
4618 | if(index == GL_INVALID_INDEX) |
4619 | { |
4620 | static std::string extensionsCat; |
4621 | |
4622 | if(extensionsCat.empty() && (numExtensions > 0)) |
4623 | { |
4624 | for(const char *extension : extensions) |
4625 | { |
4626 | extensionsCat += std::string(extension) + " " ; |
4627 | } |
4628 | } |
4629 | |
4630 | return (const GLubyte*)extensionsCat.c_str(); |
4631 | } |
4632 | |
4633 | if(index >= numExtensions) |
4634 | { |
4635 | return nullptr; |
4636 | } |
4637 | |
4638 | return (const GLubyte*)extensions[index]; |
4639 | } |
4640 | |
4641 | } |
4642 | |
4643 | NO_SANITIZE_FUNCTION egl::Context *es2CreateContext(egl::Display *display, const egl::Context *shareContext, const egl::Config *config) |
4644 | { |
4645 | return new es2::Context(display, static_cast<const es2::Context*>(shareContext), config); |
4646 | } |
4647 | |