1 // SwiftShader Software Renderer
\r
3 // Copyright(c) 2005-2013 TransGaming Inc.
\r
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
\r
6 // transcribed, stored in a retrieval system, translated into any human or computer
\r
7 // language by any means, or disclosed to third parties without the explicit written
\r
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
\r
9 // or implied, including but not limited to any patent rights, are granted to you.
\r
12 // Context.cpp: Implements the es2::Context class, managing all GL state and performing
\r
13 // rendering operations. It is the GLES2 specific implementation of EGLContext.
\r
15 #include "Context.h"
\r
18 #include "mathutil.h"
\r
19 #include "utilities.h"
\r
20 #include "ResourceManager.h"
\r
23 #include "Framebuffer.h"
\r
24 #include "Program.h"
\r
26 #include "Renderbuffer.h"
\r
28 #include "Texture.h"
\r
29 #include "VertexDataManager.h"
\r
30 #include "IndexDataManager.h"
\r
31 #include "libEGL/Display.h"
\r
32 #include "libEGL/Surface.h"
\r
33 #include "Common/Half.hpp"
\r
35 #include <EGL/eglext.h>
\r
42 Device *Context::device = 0;
\r
44 Context::Context(const egl::Config *config, const Context *shareContext) : mConfig(config)
\r
46 device = getDevice();
\r
48 mFenceHandleAllocator.setBaseHandle(0);
\r
50 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
\r
52 mState.depthClearValue = 1.0f;
\r
53 mState.stencilClearValue = 0;
\r
55 mState.cullFace = false;
\r
56 mState.cullMode = GL_BACK;
\r
57 mState.frontFace = GL_CCW;
\r
58 mState.depthTest = false;
\r
59 mState.depthFunc = GL_LESS;
\r
60 mState.blend = false;
\r
61 mState.sourceBlendRGB = GL_ONE;
\r
62 mState.sourceBlendAlpha = GL_ONE;
\r
63 mState.destBlendRGB = GL_ZERO;
\r
64 mState.destBlendAlpha = GL_ZERO;
\r
65 mState.blendEquationRGB = GL_FUNC_ADD;
\r
66 mState.blendEquationAlpha = GL_FUNC_ADD;
\r
67 mState.blendColor.red = 0;
\r
68 mState.blendColor.green = 0;
\r
69 mState.blendColor.blue = 0;
\r
70 mState.blendColor.alpha = 0;
\r
71 mState.stencilTest = false;
\r
72 mState.stencilFunc = GL_ALWAYS;
\r
73 mState.stencilRef = 0;
\r
74 mState.stencilMask = -1;
\r
75 mState.stencilWritemask = -1;
\r
76 mState.stencilBackFunc = GL_ALWAYS;
\r
77 mState.stencilBackRef = 0;
\r
78 mState.stencilBackMask = - 1;
\r
79 mState.stencilBackWritemask = -1;
\r
80 mState.stencilFail = GL_KEEP;
\r
81 mState.stencilPassDepthFail = GL_KEEP;
\r
82 mState.stencilPassDepthPass = GL_KEEP;
\r
83 mState.stencilBackFail = GL_KEEP;
\r
84 mState.stencilBackPassDepthFail = GL_KEEP;
\r
85 mState.stencilBackPassDepthPass = GL_KEEP;
\r
86 mState.polygonOffsetFill = false;
\r
87 mState.polygonOffsetFactor = 0.0f;
\r
88 mState.polygonOffsetUnits = 0.0f;
\r
89 mState.sampleAlphaToCoverage = false;
\r
90 mState.sampleCoverage = false;
\r
91 mState.sampleCoverageValue = 1.0f;
\r
92 mState.sampleCoverageInvert = false;
\r
93 mState.scissorTest = false;
\r
94 mState.dither = true;
\r
95 mState.generateMipmapHint = GL_DONT_CARE;
\r
96 mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
\r
98 mState.lineWidth = 1.0f;
\r
100 mState.viewportX = 0;
\r
101 mState.viewportY = 0;
\r
102 mState.viewportWidth = config->mDisplayMode.width;
\r
103 mState.viewportHeight = config->mDisplayMode.height;
\r
104 mState.zNear = 0.0f;
\r
105 mState.zFar = 1.0f;
\r
107 mState.scissorX = 0;
\r
108 mState.scissorY = 0;
\r
109 mState.scissorWidth = config->mDisplayMode.width;
\r
110 mState.scissorHeight = config->mDisplayMode.height;
\r
112 mState.colorMaskRed = true;
\r
113 mState.colorMaskGreen = true;
\r
114 mState.colorMaskBlue = true;
\r
115 mState.colorMaskAlpha = true;
\r
116 mState.depthMask = true;
\r
118 if(shareContext != NULL)
\r
120 mResourceManager = shareContext->mResourceManager;
\r
121 mResourceManager->addRef();
\r
125 mResourceManager = new ResourceManager();
\r
128 // [OpenGL ES 2.0.24] section 3.7 page 83:
\r
129 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
\r
130 // and cube map texture state vectors respectively associated with them.
\r
131 // In order that access to these initial textures not be lost, they are treated as texture
\r
132 // objects all of whose names are 0.
\r
134 mTexture2DZero.set(new Texture2D(0));
\r
135 mTextureCubeMapZero.set(new TextureCubeMap(0));
\r
136 mTextureExternalZero.set(new TextureExternal(0));
\r
138 mState.activeSampler = 0;
\r
139 bindArrayBuffer(0);
\r
140 bindElementArrayBuffer(0);
\r
141 bindTextureCubeMap(0);
\r
143 bindReadFramebuffer(0);
\r
144 bindDrawFramebuffer(0);
\r
145 bindRenderbuffer(0);
\r
147 mState.currentProgram = 0;
\r
149 mState.packAlignment = 4;
\r
150 mState.unpackAlignment = 4;
\r
152 mVertexDataManager = NULL;
\r
153 mIndexDataManager = NULL;
\r
155 mInvalidEnum = false;
\r
156 mInvalidValue = false;
\r
157 mInvalidOperation = false;
\r
158 mOutOfMemory = false;
\r
159 mInvalidFramebufferOperation = false;
\r
161 mHasBeenCurrent = false;
\r
163 markAllStateDirty();
\r
166 Context::~Context()
\r
168 if(mState.currentProgram != 0)
\r
170 Program *programObject = mResourceManager->getProgram(mState.currentProgram);
\r
173 programObject->release();
\r
175 mState.currentProgram = 0;
\r
178 while(!mFramebufferMap.empty())
\r
180 deleteFramebuffer(mFramebufferMap.begin()->first);
\r
183 while(!mFenceMap.empty())
\r
185 deleteFence(mFenceMap.begin()->first);
\r
188 while(!mQueryMap.empty())
\r
190 deleteQuery(mQueryMap.begin()->first);
\r
193 for(int type = 0; type < TEXTURE_TYPE_COUNT; type++)
\r
195 for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
\r
197 mState.samplerTexture[type][sampler].set(NULL);
\r
201 for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
\r
203 mState.vertexAttribute[i].mBoundBuffer.set(NULL);
\r
206 for(int i = 0; i < QUERY_TYPE_COUNT; i++)
\r
208 mState.activeQuery[i].set(NULL);
\r
211 mState.arrayBuffer.set(NULL);
\r
212 mState.elementArrayBuffer.set(NULL);
\r
213 mState.renderbuffer.set(NULL);
\r
215 mTexture2DZero.set(NULL);
\r
216 mTextureCubeMapZero.set(NULL);
\r
217 mTextureExternalZero.set(NULL);
\r
219 delete mVertexDataManager;
\r
220 delete mIndexDataManager;
\r
222 mResourceManager->release();
\r
225 void Context::makeCurrent(egl::Surface *surface)
\r
227 if(!mHasBeenCurrent)
\r
229 mVertexDataManager = new VertexDataManager(this);
\r
230 mIndexDataManager = new IndexDataManager();
\r
232 mState.viewportX = 0;
\r
233 mState.viewportY = 0;
\r
234 mState.viewportWidth = surface->getWidth();
\r
235 mState.viewportHeight = surface->getHeight();
\r
237 mState.scissorX = 0;
\r
238 mState.scissorY = 0;
\r
239 mState.scissorWidth = surface->getWidth();
\r
240 mState.scissorHeight = surface->getHeight();
\r
242 mHasBeenCurrent = true;
\r
245 // Wrap the existing resources into GL objects and assign them to the '0' names
\r
246 egl::Image *defaultRenderTarget = surface->getRenderTarget();
\r
247 egl::Image *depthStencil = surface->getDepthStencil();
\r
249 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
\r
250 DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
\r
251 Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);
\r
253 setFramebufferZero(framebufferZero);
\r
255 if(defaultRenderTarget)
\r
257 defaultRenderTarget->release();
\r
262 depthStencil->release();
\r
265 markAllStateDirty();
\r
268 void Context::destroy()
\r
273 int Context::getClientVersion()
\r
278 // This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
\r
279 void Context::markAllStateDirty()
\r
281 mAppliedProgramSerial = 0;
\r
283 mDepthStateDirty = true;
\r
284 mMaskStateDirty = true;
\r
285 mBlendStateDirty = true;
\r
286 mStencilStateDirty = true;
\r
287 mPolygonOffsetStateDirty = true;
\r
288 mSampleStateDirty = true;
\r
289 mDitherStateDirty = true;
\r
290 mFrontFaceDirty = true;
\r
293 void Context::setClearColor(float red, float green, float blue, float alpha)
\r
295 mState.colorClearValue.red = red;
\r
296 mState.colorClearValue.green = green;
\r
297 mState.colorClearValue.blue = blue;
\r
298 mState.colorClearValue.alpha = alpha;
\r
301 void Context::setClearDepth(float depth)
\r
303 mState.depthClearValue = depth;
\r
306 void Context::setClearStencil(int stencil)
\r
308 mState.stencilClearValue = stencil;
\r
311 void Context::setCullFace(bool enabled)
\r
313 mState.cullFace = enabled;
\r
316 bool Context::isCullFaceEnabled() const
\r
318 return mState.cullFace;
\r
321 void Context::setCullMode(GLenum mode)
\r
323 mState.cullMode = mode;
\r
326 void Context::setFrontFace(GLenum front)
\r
328 if(mState.frontFace != front)
\r
330 mState.frontFace = front;
\r
331 mFrontFaceDirty = true;
\r
335 void Context::setDepthTest(bool enabled)
\r
337 if(mState.depthTest != enabled)
\r
339 mState.depthTest = enabled;
\r
340 mDepthStateDirty = true;
\r
344 bool Context::isDepthTestEnabled() const
\r
346 return mState.depthTest;
\r
349 void Context::setDepthFunc(GLenum depthFunc)
\r
351 if(mState.depthFunc != depthFunc)
\r
353 mState.depthFunc = depthFunc;
\r
354 mDepthStateDirty = true;
\r
358 void Context::setDepthRange(float zNear, float zFar)
\r
360 mState.zNear = zNear;
\r
361 mState.zFar = zFar;
\r
364 void Context::setBlend(bool enabled)
\r
366 if(mState.blend != enabled)
\r
368 mState.blend = enabled;
\r
369 mBlendStateDirty = true;
\r
373 bool Context::isBlendEnabled() const
\r
375 return mState.blend;
\r
378 void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
\r
380 if(mState.sourceBlendRGB != sourceRGB ||
\r
381 mState.sourceBlendAlpha != sourceAlpha ||
\r
382 mState.destBlendRGB != destRGB ||
\r
383 mState.destBlendAlpha != destAlpha)
\r
385 mState.sourceBlendRGB = sourceRGB;
\r
386 mState.destBlendRGB = destRGB;
\r
387 mState.sourceBlendAlpha = sourceAlpha;
\r
388 mState.destBlendAlpha = destAlpha;
\r
389 mBlendStateDirty = true;
\r
393 void Context::setBlendColor(float red, float green, float blue, float alpha)
\r
395 if(mState.blendColor.red != red ||
\r
396 mState.blendColor.green != green ||
\r
397 mState.blendColor.blue != blue ||
\r
398 mState.blendColor.alpha != alpha)
\r
400 mState.blendColor.red = red;
\r
401 mState.blendColor.green = green;
\r
402 mState.blendColor.blue = blue;
\r
403 mState.blendColor.alpha = alpha;
\r
404 mBlendStateDirty = true;
\r
408 void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
\r
410 if(mState.blendEquationRGB != rgbEquation ||
\r
411 mState.blendEquationAlpha != alphaEquation)
\r
413 mState.blendEquationRGB = rgbEquation;
\r
414 mState.blendEquationAlpha = alphaEquation;
\r
415 mBlendStateDirty = true;
\r
419 void Context::setStencilTest(bool enabled)
\r
421 if(mState.stencilTest != enabled)
\r
423 mState.stencilTest = enabled;
\r
424 mStencilStateDirty = true;
\r
428 bool Context::isStencilTestEnabled() const
\r
430 return mState.stencilTest;
\r
433 void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
\r
435 if(mState.stencilFunc != stencilFunc ||
\r
436 mState.stencilRef != stencilRef ||
\r
437 mState.stencilMask != stencilMask)
\r
439 mState.stencilFunc = stencilFunc;
\r
440 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
\r
441 mState.stencilMask = stencilMask;
\r
442 mStencilStateDirty = true;
\r
446 void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
\r
448 if(mState.stencilBackFunc != stencilBackFunc ||
\r
449 mState.stencilBackRef != stencilBackRef ||
\r
450 mState.stencilBackMask != stencilBackMask)
\r
452 mState.stencilBackFunc = stencilBackFunc;
\r
453 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
\r
454 mState.stencilBackMask = stencilBackMask;
\r
455 mStencilStateDirty = true;
\r
459 void Context::setStencilWritemask(GLuint stencilWritemask)
\r
461 if(mState.stencilWritemask != stencilWritemask)
\r
463 mState.stencilWritemask = stencilWritemask;
\r
464 mStencilStateDirty = true;
\r
468 void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
\r
470 if(mState.stencilBackWritemask != stencilBackWritemask)
\r
472 mState.stencilBackWritemask = stencilBackWritemask;
\r
473 mStencilStateDirty = true;
\r
477 void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
\r
479 if(mState.stencilFail != stencilFail ||
\r
480 mState.stencilPassDepthFail != stencilPassDepthFail ||
\r
481 mState.stencilPassDepthPass != stencilPassDepthPass)
\r
483 mState.stencilFail = stencilFail;
\r
484 mState.stencilPassDepthFail = stencilPassDepthFail;
\r
485 mState.stencilPassDepthPass = stencilPassDepthPass;
\r
486 mStencilStateDirty = true;
\r
490 void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
\r
492 if(mState.stencilBackFail != stencilBackFail ||
\r
493 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
\r
494 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
\r
496 mState.stencilBackFail = stencilBackFail;
\r
497 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
\r
498 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
\r
499 mStencilStateDirty = true;
\r
503 void Context::setPolygonOffsetFill(bool enabled)
\r
505 if(mState.polygonOffsetFill != enabled)
\r
507 mState.polygonOffsetFill = enabled;
\r
508 mPolygonOffsetStateDirty = true;
\r
512 bool Context::isPolygonOffsetFillEnabled() const
\r
514 return mState.polygonOffsetFill;
\r
517 void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
\r
519 if(mState.polygonOffsetFactor != factor ||
\r
520 mState.polygonOffsetUnits != units)
\r
522 mState.polygonOffsetFactor = factor;
\r
523 mState.polygonOffsetUnits = units;
\r
524 mPolygonOffsetStateDirty = true;
\r
528 void Context::setSampleAlphaToCoverage(bool enabled)
\r
530 if(mState.sampleAlphaToCoverage != enabled)
\r
532 mState.sampleAlphaToCoverage = enabled;
\r
533 mSampleStateDirty = true;
\r
537 bool Context::isSampleAlphaToCoverageEnabled() const
\r
539 return mState.sampleAlphaToCoverage;
\r
542 void Context::setSampleCoverage(bool enabled)
\r
544 if(mState.sampleCoverage != enabled)
\r
546 mState.sampleCoverage = enabled;
\r
547 mSampleStateDirty = true;
\r
551 bool Context::isSampleCoverageEnabled() const
\r
553 return mState.sampleCoverage;
\r
556 void Context::setSampleCoverageParams(GLclampf value, bool invert)
\r
558 if(mState.sampleCoverageValue != value ||
\r
559 mState.sampleCoverageInvert != invert)
\r
561 mState.sampleCoverageValue = value;
\r
562 mState.sampleCoverageInvert = invert;
\r
563 mSampleStateDirty = true;
\r
567 void Context::setScissorTest(bool enabled)
\r
569 mState.scissorTest = enabled;
\r
572 bool Context::isScissorTestEnabled() const
\r
574 return mState.scissorTest;
\r
577 void Context::setDither(bool enabled)
\r
579 if(mState.dither != enabled)
\r
581 mState.dither = enabled;
\r
582 mDitherStateDirty = true;
\r
586 bool Context::isDitherEnabled() const
\r
588 return mState.dither;
\r
591 void Context::setLineWidth(GLfloat width)
\r
593 mState.lineWidth = width;
\r
596 void Context::setGenerateMipmapHint(GLenum hint)
\r
598 mState.generateMipmapHint = hint;
\r
601 void Context::setFragmentShaderDerivativeHint(GLenum hint)
\r
603 mState.fragmentShaderDerivativeHint = hint;
\r
604 // TODO: Propagate the hint to shader translator so we can write
\r
605 // ddx, ddx_coarse, or ddx_fine depending on the hint.
\r
606 // Ignore for now. It is valid for implementations to ignore hint.
\r
609 void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
\r
611 mState.viewportX = x;
\r
612 mState.viewportY = y;
\r
613 mState.viewportWidth = width;
\r
614 mState.viewportHeight = height;
\r
617 void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
\r
619 mState.scissorX = x;
\r
620 mState.scissorY = y;
\r
621 mState.scissorWidth = width;
\r
622 mState.scissorHeight = height;
\r
625 void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
\r
627 if(mState.colorMaskRed != red || mState.colorMaskGreen != green ||
\r
628 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
\r
630 mState.colorMaskRed = red;
\r
631 mState.colorMaskGreen = green;
\r
632 mState.colorMaskBlue = blue;
\r
633 mState.colorMaskAlpha = alpha;
\r
634 mMaskStateDirty = true;
\r
638 void Context::setDepthMask(bool mask)
\r
640 if(mState.depthMask != mask)
\r
642 mState.depthMask = mask;
\r
643 mMaskStateDirty = true;
\r
647 void Context::setActiveSampler(unsigned int active)
\r
649 mState.activeSampler = active;
\r
652 GLuint Context::getReadFramebufferHandle() const
\r
654 return mState.readFramebuffer;
\r
657 GLuint Context::getDrawFramebufferHandle() const
\r
659 return mState.drawFramebuffer;
\r
662 GLuint Context::getRenderbufferHandle() const
\r
664 return mState.renderbuffer.id();
\r
667 GLuint Context::getArrayBufferHandle() const
\r
669 return mState.arrayBuffer.id();
\r
672 GLuint Context::getActiveQuery(GLenum target) const
\r
674 Query *queryObject = NULL;
\r
678 case GL_ANY_SAMPLES_PASSED_EXT:
\r
679 queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();
\r
681 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
\r
682 queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();
\r
690 return queryObject->id();
\r
696 void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
\r
698 mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
\r
701 const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
\r
703 return mState.vertexAttribute[attribNum];
\r
706 void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
\r
707 GLsizei stride, const void *pointer)
\r
709 mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
\r
710 mState.vertexAttribute[attribNum].mSize = size;
\r
711 mState.vertexAttribute[attribNum].mType = type;
\r
712 mState.vertexAttribute[attribNum].mNormalized = normalized;
\r
713 mState.vertexAttribute[attribNum].mStride = stride;
\r
714 mState.vertexAttribute[attribNum].mPointer = pointer;
\r
717 const void *Context::getVertexAttribPointer(unsigned int attribNum) const
\r
719 return mState.vertexAttribute[attribNum].mPointer;
\r
722 const VertexAttributeArray &Context::getVertexAttributes()
\r
724 return mState.vertexAttribute;
\r
727 void Context::setPackAlignment(GLint alignment)
\r
729 mState.packAlignment = alignment;
\r
732 GLint Context::getPackAlignment() const
\r
734 return mState.packAlignment;
\r
737 void Context::setUnpackAlignment(GLint alignment)
\r
739 mState.unpackAlignment = alignment;
\r
742 GLint Context::getUnpackAlignment() const
\r
744 return mState.unpackAlignment;
\r
747 GLuint Context::createBuffer()
\r
749 return mResourceManager->createBuffer();
\r
752 GLuint Context::createProgram()
\r
754 return mResourceManager->createProgram();
\r
757 GLuint Context::createShader(GLenum type)
\r
759 return mResourceManager->createShader(type);
\r
762 GLuint Context::createTexture()
\r
764 return mResourceManager->createTexture();
\r
767 GLuint Context::createRenderbuffer()
\r
769 return mResourceManager->createRenderbuffer();
\r
772 // Returns an unused framebuffer name
\r
773 GLuint Context::createFramebuffer()
\r
775 GLuint handle = mFramebufferHandleAllocator.allocate();
\r
777 mFramebufferMap[handle] = NULL;
\r
782 GLuint Context::createFence()
\r
784 GLuint handle = mFenceHandleAllocator.allocate();
\r
786 mFenceMap[handle] = new Fence;
\r
791 // Returns an unused query name
\r
792 GLuint Context::createQuery()
\r
794 GLuint handle = mQueryHandleAllocator.allocate();
\r
796 mQueryMap[handle] = NULL;
\r
801 void Context::deleteBuffer(GLuint buffer)
\r
803 if(mResourceManager->getBuffer(buffer))
\r
805 detachBuffer(buffer);
\r
808 mResourceManager->deleteBuffer(buffer);
\r
811 void Context::deleteShader(GLuint shader)
\r
813 mResourceManager->deleteShader(shader);
\r
816 void Context::deleteProgram(GLuint program)
\r
818 mResourceManager->deleteProgram(program);
\r
821 void Context::deleteTexture(GLuint texture)
\r
823 if(mResourceManager->getTexture(texture))
\r
825 detachTexture(texture);
\r
828 mResourceManager->deleteTexture(texture);
\r
831 void Context::deleteRenderbuffer(GLuint renderbuffer)
\r
833 if(mResourceManager->getRenderbuffer(renderbuffer))
\r
835 detachRenderbuffer(renderbuffer);
\r
838 mResourceManager->deleteRenderbuffer(renderbuffer);
\r
841 void Context::deleteFramebuffer(GLuint framebuffer)
\r
843 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
\r
845 if(framebufferObject != mFramebufferMap.end())
\r
847 detachFramebuffer(framebuffer);
\r
849 mFramebufferHandleAllocator.release(framebufferObject->first);
\r
850 delete framebufferObject->second;
\r
851 mFramebufferMap.erase(framebufferObject);
\r
855 void Context::deleteFence(GLuint fence)
\r
857 FenceMap::iterator fenceObject = mFenceMap.find(fence);
\r
859 if(fenceObject != mFenceMap.end())
\r
861 mFenceHandleAllocator.release(fenceObject->first);
\r
862 delete fenceObject->second;
\r
863 mFenceMap.erase(fenceObject);
\r
867 void Context::deleteQuery(GLuint query)
\r
869 QueryMap::iterator queryObject = mQueryMap.find(query);
\r
871 if(queryObject != mQueryMap.end())
\r
873 mQueryHandleAllocator.release(queryObject->first);
\r
875 if(queryObject->second)
\r
877 queryObject->second->release();
\r
880 mQueryMap.erase(queryObject);
\r
884 Buffer *Context::getBuffer(GLuint handle)
\r
886 return mResourceManager->getBuffer(handle);
\r
889 Shader *Context::getShader(GLuint handle)
\r
891 return mResourceManager->getShader(handle);
\r
894 Program *Context::getProgram(GLuint handle)
\r
896 return mResourceManager->getProgram(handle);
\r
899 Texture *Context::getTexture(GLuint handle)
\r
901 return mResourceManager->getTexture(handle);
\r
904 Renderbuffer *Context::getRenderbuffer(GLuint handle)
\r
906 return mResourceManager->getRenderbuffer(handle);
\r
909 Framebuffer *Context::getReadFramebuffer()
\r
911 return getFramebuffer(mState.readFramebuffer);
\r
914 Framebuffer *Context::getDrawFramebuffer()
\r
916 return getFramebuffer(mState.drawFramebuffer);
\r
919 void Context::bindArrayBuffer(unsigned int buffer)
\r
921 mResourceManager->checkBufferAllocation(buffer);
\r
923 mState.arrayBuffer.set(getBuffer(buffer));
\r
926 void Context::bindElementArrayBuffer(unsigned int buffer)
\r
928 mResourceManager->checkBufferAllocation(buffer);
\r
930 mState.elementArrayBuffer.set(getBuffer(buffer));
\r
933 void Context::bindTexture2D(GLuint texture)
\r
935 mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
\r
937 mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
\r
940 void Context::bindTextureCubeMap(GLuint texture)
\r
942 mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
\r
944 mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
\r
947 void Context::bindTextureExternal(GLuint texture)
\r
949 mResourceManager->checkTextureAllocation(texture, TEXTURE_EXTERNAL);
\r
951 mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler].set(getTexture(texture));
\r
954 void Context::bindReadFramebuffer(GLuint framebuffer)
\r
956 if(!getFramebuffer(framebuffer))
\r
958 mFramebufferMap[framebuffer] = new Framebuffer();
\r
961 mState.readFramebuffer = framebuffer;
\r
964 void Context::bindDrawFramebuffer(GLuint framebuffer)
\r
966 if(!getFramebuffer(framebuffer))
\r
968 mFramebufferMap[framebuffer] = new Framebuffer();
\r
971 mState.drawFramebuffer = framebuffer;
\r
974 void Context::bindRenderbuffer(GLuint renderbuffer)
\r
976 mState.renderbuffer.set(getRenderbuffer(renderbuffer));
\r
979 void Context::useProgram(GLuint program)
\r
981 GLuint priorProgram = mState.currentProgram;
\r
982 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
\r
984 if(priorProgram != program)
\r
986 Program *newProgram = mResourceManager->getProgram(program);
\r
987 Program *oldProgram = mResourceManager->getProgram(priorProgram);
\r
991 newProgram->addRef();
\r
996 oldProgram->release();
\r
1001 void Context::beginQuery(GLenum target, GLuint query)
\r
1003 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
\r
1004 // of zero, if the active query object name for <target> is non-zero (for the
\r
1005 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
\r
1006 // the active query for either target is non-zero), if <id> is the name of an
\r
1007 // existing query object whose type does not match <target>, or if <id> is the
\r
1008 // active query object name for any query type, the error INVALID_OPERATION is
\r
1011 // Ensure no other queries are active
\r
1012 // NOTE: If other queries than occlusion are supported, we will need to check
\r
1013 // separately that:
\r
1014 // a) The query ID passed is not the current active query for any target/type
\r
1015 // b) There are no active queries for the requested target (and in the case
\r
1016 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
\r
1017 // no query may be active for either if glBeginQuery targets either.
\r
1018 for(int i = 0; i < QUERY_TYPE_COUNT; i++)
\r
1020 if(mState.activeQuery[i].get() != NULL)
\r
1022 return error(GL_INVALID_OPERATION);
\r
1029 case GL_ANY_SAMPLES_PASSED_EXT:
\r
1030 qType = QUERY_ANY_SAMPLES_PASSED;
\r
1032 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
\r
1033 qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
\r
1039 Query *queryObject = getQuery(query, true, target);
\r
1041 // Check that name was obtained with glGenQueries
\r
1044 return error(GL_INVALID_OPERATION);
\r
1047 // Check for type mismatch
\r
1048 if(queryObject->getType() != target)
\r
1050 return error(GL_INVALID_OPERATION);
\r
1053 // Set query as active for specified target
\r
1054 mState.activeQuery[qType].set(queryObject);
\r
1057 queryObject->begin();
\r
1060 void Context::endQuery(GLenum target)
\r
1066 case GL_ANY_SAMPLES_PASSED_EXT:
\r
1067 qType = QUERY_ANY_SAMPLES_PASSED;
\r
1069 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
\r
1070 qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
\r
1076 Query *queryObject = mState.activeQuery[qType].get();
\r
1078 if(queryObject == NULL)
\r
1080 return error(GL_INVALID_OPERATION);
\r
1083 queryObject->end();
\r
1085 mState.activeQuery[qType].set(NULL);
\r
1088 void Context::setFramebufferZero(Framebuffer *buffer)
\r
1090 delete mFramebufferMap[0];
\r
1091 mFramebufferMap[0] = buffer;
\r
1094 void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
\r
1096 Renderbuffer *renderbufferObject = mState.renderbuffer.get();
\r
1097 renderbufferObject->setStorage(renderbuffer);
\r
1100 Framebuffer *Context::getFramebuffer(unsigned int handle)
\r
1102 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
\r
1104 if(framebuffer == mFramebufferMap.end())
\r
1110 return framebuffer->second;
\r
1114 Fence *Context::getFence(unsigned int handle)
\r
1116 FenceMap::iterator fence = mFenceMap.find(handle);
\r
1118 if(fence == mFenceMap.end())
\r
1124 return fence->second;
\r
1128 Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
\r
1130 QueryMap::iterator query = mQueryMap.find(handle);
\r
1132 if(query == mQueryMap.end())
\r
1138 if(!query->second && create)
\r
1140 query->second = new Query(handle, type);
\r
1141 query->second->addRef();
\r
1144 return query->second;
\r
1148 Buffer *Context::getArrayBuffer()
\r
1150 return mState.arrayBuffer.get();
\r
1153 Buffer *Context::getElementArrayBuffer()
\r
1155 return mState.elementArrayBuffer.get();
\r
1158 Program *Context::getCurrentProgram()
\r
1160 return mState.program;
\r
1161 //return mResourceManager->getProgram(mState.currentProgram);
\r
1164 Texture2D *Context::getTexture2D()
\r
1166 return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
\r
1169 TextureCubeMap *Context::getTextureCubeMap()
\r
1171 return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
\r
1174 TextureExternal *Context::getTextureExternal()
\r
1176 return static_cast<TextureExternal*>(getSamplerTexture(mState.activeSampler, TEXTURE_EXTERNAL));
\r
1179 Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
\r
1181 GLuint texid = mState.samplerTexture[type][sampler].id();
\r
1183 if(texid == 0) // Special case: 0 refers to different initial textures based on the target
\r
1187 case TEXTURE_2D: return mTexture2DZero.get();
\r
1188 case TEXTURE_CUBE: return mTextureCubeMapZero.get();
\r
1189 case TEXTURE_EXTERNAL: return mTextureExternalZero.get();
\r
1190 default: UNREACHABLE();
\r
1194 return mState.samplerTexture[type][sampler].get();
\r
1197 bool Context::getBooleanv(GLenum pname, GLboolean *params)
\r
1201 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
\r
1202 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
\r
1203 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
\r
1204 case GL_COLOR_WRITEMASK:
\r
1205 params[0] = mState.colorMaskRed;
\r
1206 params[1] = mState.colorMaskGreen;
\r
1207 params[2] = mState.colorMaskBlue;
\r
1208 params[3] = mState.colorMaskAlpha;
\r
1210 case GL_CULL_FACE: *params = mState.cullFace; break;
\r
1211 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break;
\r
1212 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break;
\r
1213 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break;
\r
1214 case GL_SCISSOR_TEST: *params = mState.scissorTest; break;
\r
1215 case GL_STENCIL_TEST: *params = mState.stencilTest; break;
\r
1216 case GL_DEPTH_TEST: *params = mState.depthTest; break;
\r
1217 case GL_BLEND: *params = mState.blend; break;
\r
1218 case GL_DITHER: *params = mState.dither; break;
\r
1226 bool Context::getFloatv(GLenum pname, GLfloat *params)
\r
1228 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
\r
1229 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
\r
1230 // GetIntegerv as its native query function. As it would require conversion in any
\r
1231 // case, this should make no difference to the calling application.
\r
1234 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
\r
1235 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
\r
1236 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
\r
1237 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
\r
1238 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
\r
1239 case GL_ALIASED_LINE_WIDTH_RANGE:
\r
1240 params[0] = ALIASED_LINE_WIDTH_RANGE_MIN;
\r
1241 params[1] = ALIASED_LINE_WIDTH_RANGE_MAX;
\r
1243 case GL_ALIASED_POINT_SIZE_RANGE:
\r
1244 params[0] = ALIASED_POINT_SIZE_RANGE_MIN;
\r
1245 params[1] = ALIASED_POINT_SIZE_RANGE_MAX;
\r
1247 case GL_DEPTH_RANGE:
\r
1248 params[0] = mState.zNear;
\r
1249 params[1] = mState.zFar;
\r
1251 case GL_COLOR_CLEAR_VALUE:
\r
1252 params[0] = mState.colorClearValue.red;
\r
1253 params[1] = mState.colorClearValue.green;
\r
1254 params[2] = mState.colorClearValue.blue;
\r
1255 params[3] = mState.colorClearValue.alpha;
\r
1257 case GL_BLEND_COLOR:
\r
1258 params[0] = mState.blendColor.red;
\r
1259 params[1] = mState.blendColor.green;
\r
1260 params[2] = mState.blendColor.blue;
\r
1261 params[3] = mState.blendColor.alpha;
\r
1263 case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
\r
1264 *params = MAX_TEXTURE_MAX_ANISOTROPY;
\r
1273 bool Context::getIntegerv(GLenum pname, GLint *params)
\r
1275 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
\r
1276 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
\r
1277 // GetIntegerv as its native query function. As it would require conversion in any
\r
1278 // case, this should make no difference to the calling application. You may find it in
\r
1279 // Context::getFloatv.
\r
1282 case GL_MAX_VERTEX_ATTRIBS: *params = MAX_VERTEX_ATTRIBS; break;
\r
1283 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = MAX_VERTEX_UNIFORM_VECTORS; break;
\r
1284 case GL_MAX_VARYING_VECTORS: *params = MAX_VARYING_VECTORS; break;
\r
1285 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
\r
1286 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
\r
1287 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = MAX_TEXTURE_IMAGE_UNITS; break;
\r
1288 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = MAX_FRAGMENT_UNIFORM_VECTORS; break;
\r
1289 case GL_MAX_RENDERBUFFER_SIZE: *params = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE; break;
\r
1290 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
\r
1291 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
\r
1292 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break;
\r
1293 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break;
\r
1294 // case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
\r
1295 case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break;
\r
1296 case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break;
\r
1297 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break;
\r
1298 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
\r
1299 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
\r
1300 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
\r
1301 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
\r
1302 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
\r
1303 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
\r
1304 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
\r
1305 case GL_STENCIL_REF: *params = mState.stencilRef; break;
\r
1306 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
\r
1307 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
\r
1308 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
\r
1309 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
\r
1310 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
\r
1311 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
\r
1312 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
\r
1313 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
\r
1314 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
\r
1315 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
\r
1316 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
\r
1317 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
\r
1318 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
\r
1319 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
\r
1320 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
\r
1321 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
\r
1322 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
\r
1323 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
\r
1324 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
\r
1325 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
\r
1326 case GL_SUBPIXEL_BITS: *params = 4; break;
\r
1327 case GL_MAX_TEXTURE_SIZE: *params = IMPLEMENTATION_MAX_TEXTURE_SIZE; break;
\r
1328 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE; break;
\r
1329 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
\r
1333 // GL_COMPRESSED_RGB_S3TC_DXT1_EXT
\r
1334 // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
\r
1335 // GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE
\r
1336 // GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE
\r
1345 case GL_MAX_SAMPLES_ANGLE: *params = IMPLEMENTATION_MAX_SAMPLES; break;
\r
1346 case GL_SAMPLE_BUFFERS:
\r
1349 Framebuffer *framebuffer = getDrawFramebuffer();
\r
1350 int width, height, samples;
\r
1352 if(framebuffer->completeness(width, height, samples) == GL_FRAMEBUFFER_COMPLETE)
\r
1356 case GL_SAMPLE_BUFFERS:
\r
1367 *params = samples & ~1;
\r
1377 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = IMPLEMENTATION_COLOR_READ_TYPE; break;
\r
1378 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = IMPLEMENTATION_COLOR_READ_FORMAT; break;
\r
1379 case GL_MAX_VIEWPORT_DIMS:
\r
1381 int maxDimension = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE;
\r
1382 params[0] = maxDimension;
\r
1383 params[1] = maxDimension;
\r
1386 case GL_COMPRESSED_TEXTURE_FORMATS:
\r
1390 params[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
\r
1391 params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
\r
1392 params[2] = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
\r
1393 params[3] = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
\r
1398 params[0] = mState.viewportX;
\r
1399 params[1] = mState.viewportY;
\r
1400 params[2] = mState.viewportWidth;
\r
1401 params[3] = mState.viewportHeight;
\r
1403 case GL_SCISSOR_BOX:
\r
1404 params[0] = mState.scissorX;
\r
1405 params[1] = mState.scissorY;
\r
1406 params[2] = mState.scissorWidth;
\r
1407 params[3] = mState.scissorHeight;
\r
1409 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
\r
1410 case GL_FRONT_FACE: *params = mState.frontFace; break;
\r
1412 case GL_GREEN_BITS:
\r
1413 case GL_BLUE_BITS:
\r
1414 case GL_ALPHA_BITS:
\r
1416 Framebuffer *framebuffer = getDrawFramebuffer();
\r
1417 Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
\r
1423 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
\r
1424 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
\r
1425 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
\r
1426 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
\r
1435 case GL_DEPTH_BITS:
\r
1437 Framebuffer *framebuffer = getDrawFramebuffer();
\r
1438 Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
\r
1442 *params = depthbuffer->getDepthSize();
\r
1450 case GL_STENCIL_BITS:
\r
1452 Framebuffer *framebuffer = getDrawFramebuffer();
\r
1453 Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
\r
1457 *params = stencilbuffer->getStencilSize();
\r
1465 case GL_TEXTURE_BINDING_2D:
\r
1467 if(mState.activeSampler < 0 || mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
\r
1469 error(GL_INVALID_OPERATION);
\r
1473 *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();
\r
1476 case GL_TEXTURE_BINDING_CUBE_MAP:
\r
1478 if(mState.activeSampler < 0 || mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
\r
1480 error(GL_INVALID_OPERATION);
\r
1484 *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
\r
1487 case GL_TEXTURE_BINDING_EXTERNAL_OES:
\r
1489 if(mState.activeSampler < 0 || mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
\r
1491 error(GL_INVALID_OPERATION);
\r
1495 *params = mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler].id();
\r
1505 bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
\r
1507 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
\r
1508 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
\r
1509 // to the fact that it is stored internally as a float, and so would require conversion
\r
1510 // if returned from Context::getIntegerv. Since this conversion is already implemented
\r
1511 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
\r
1512 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
\r
1516 case GL_COMPRESSED_TEXTURE_FORMATS:
\r
1519 *numParams = S3TC_SUPPORT ? 4 : 0;
\r
1522 case GL_SHADER_BINARY_FORMATS:
\r
1528 case GL_MAX_VERTEX_ATTRIBS:
\r
1529 case GL_MAX_VERTEX_UNIFORM_VECTORS:
\r
1530 case GL_MAX_VARYING_VECTORS:
\r
1531 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
\r
1532 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
\r
1533 case GL_MAX_TEXTURE_IMAGE_UNITS:
\r
1534 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
\r
1535 case GL_MAX_RENDERBUFFER_SIZE:
\r
1536 case GL_NUM_SHADER_BINARY_FORMATS:
\r
1537 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
\r
1538 case GL_ARRAY_BUFFER_BINDING:
\r
1539 case GL_FRAMEBUFFER_BINDING:
\r
1540 case GL_RENDERBUFFER_BINDING:
\r
1541 case GL_CURRENT_PROGRAM:
\r
1542 case GL_PACK_ALIGNMENT:
\r
1543 case GL_UNPACK_ALIGNMENT:
\r
1544 case GL_GENERATE_MIPMAP_HINT:
\r
1545 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
\r
1547 case GL_GREEN_BITS:
\r
1548 case GL_BLUE_BITS:
\r
1549 case GL_ALPHA_BITS:
\r
1550 case GL_DEPTH_BITS:
\r
1551 case GL_STENCIL_BITS:
\r
1552 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
\r
1553 case GL_CULL_FACE_MODE:
\r
1554 case GL_FRONT_FACE:
\r
1555 case GL_ACTIVE_TEXTURE:
\r
1556 case GL_STENCIL_FUNC:
\r
1557 case GL_STENCIL_VALUE_MASK:
\r
1558 case GL_STENCIL_REF:
\r
1559 case GL_STENCIL_FAIL:
\r
1560 case GL_STENCIL_PASS_DEPTH_FAIL:
\r
1561 case GL_STENCIL_PASS_DEPTH_PASS:
\r
1562 case GL_STENCIL_BACK_FUNC:
\r
1563 case GL_STENCIL_BACK_VALUE_MASK:
\r
1564 case GL_STENCIL_BACK_REF:
\r
1565 case GL_STENCIL_BACK_FAIL:
\r
1566 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
\r
1567 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
\r
1568 case GL_DEPTH_FUNC:
\r
1569 case GL_BLEND_SRC_RGB:
\r
1570 case GL_BLEND_SRC_ALPHA:
\r
1571 case GL_BLEND_DST_RGB:
\r
1572 case GL_BLEND_DST_ALPHA:
\r
1573 case GL_BLEND_EQUATION_RGB:
\r
1574 case GL_BLEND_EQUATION_ALPHA:
\r
1575 case GL_STENCIL_WRITEMASK:
\r
1576 case GL_STENCIL_BACK_WRITEMASK:
\r
1577 case GL_STENCIL_CLEAR_VALUE:
\r
1578 case GL_SUBPIXEL_BITS:
\r
1579 case GL_MAX_TEXTURE_SIZE:
\r
1580 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
\r
1581 case GL_SAMPLE_BUFFERS:
\r
1583 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
\r
1584 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
\r
1585 case GL_TEXTURE_BINDING_2D:
\r
1586 case GL_TEXTURE_BINDING_CUBE_MAP:
\r
1587 case GL_TEXTURE_BINDING_EXTERNAL_OES:
\r
1593 case GL_MAX_SAMPLES_ANGLE:
\r
1599 case GL_MAX_VIEWPORT_DIMS:
\r
1606 case GL_SCISSOR_BOX:
\r
1612 case GL_SHADER_COMPILER:
\r
1613 case GL_SAMPLE_COVERAGE_INVERT:
\r
1614 case GL_DEPTH_WRITEMASK:
\r
1615 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
\r
1616 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
\r
1617 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
\r
1618 case GL_SAMPLE_COVERAGE:
\r
1619 case GL_SCISSOR_TEST:
\r
1620 case GL_STENCIL_TEST:
\r
1621 case GL_DEPTH_TEST:
\r
1629 case GL_COLOR_WRITEMASK:
\r
1635 case GL_POLYGON_OFFSET_FACTOR:
\r
1636 case GL_POLYGON_OFFSET_UNITS:
\r
1637 case GL_SAMPLE_COVERAGE_VALUE:
\r
1638 case GL_DEPTH_CLEAR_VALUE:
\r
1639 case GL_LINE_WIDTH:
\r
1645 case GL_ALIASED_LINE_WIDTH_RANGE:
\r
1646 case GL_ALIASED_POINT_SIZE_RANGE:
\r
1647 case GL_DEPTH_RANGE:
\r
1653 case GL_COLOR_CLEAR_VALUE:
\r
1654 case GL_BLEND_COLOR:
\r
1660 case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
\r
1671 // Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle
\r
1672 bool Context::applyRenderTarget()
\r
1674 Framebuffer *framebuffer = getDrawFramebuffer();
\r
1675 int width, height, samples;
\r
1677 if(!framebuffer || framebuffer->completeness(width, height, samples) != GL_FRAMEBUFFER_COMPLETE)
\r
1679 return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
\r
1682 egl::Image *renderTarget = mState.colorBuffer;//framebuffer->getRenderTarget();
\r
1683 device->setRenderTarget(renderTarget);
\r
1684 //if(renderTarget) renderTarget->release();
\r
1686 egl::Image *depthStencil = mState.depthBuffer;//framebuffer->getDepthStencil();
\r
1687 device->setDepthStencilSurface(depthStencil);
\r
1688 //if(depthStencil) depthStencil->release();
\r
1690 Viewport viewport;
\r
1691 float zNear = clamp01(mState.zNear);
\r
1692 float zFar = clamp01(mState.zFar);
\r
1694 viewport.x0 = mState.viewportX;
\r
1695 viewport.y0 = mState.viewportY;
\r
1696 viewport.width = mState.viewportWidth;
\r
1697 viewport.height = mState.viewportHeight;
\r
1698 viewport.minZ = zNear;
\r
1699 viewport.maxZ = zFar;
\r
1701 device->setViewport(viewport);
\r
1703 if(mState.scissorTest)
\r
1705 sw::Rect scissor = {mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight};
\r
1706 scissor.clip(0, 0, width, height);
\r
1708 device->setScissorRect(scissor);
\r
1709 device->setScissorEnable(true);
\r
1713 device->setScissorEnable(false);
\r
1716 Program *program = getCurrentProgram();
\r
1720 GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};
\r
1721 program->setUniform1fv(program->getUniformLocation("gl_DepthRange.near"), 1, &nearFarDiff[0]);
\r
1722 program->setUniform1fv(program->getUniformLocation("gl_DepthRange.far"), 1, &nearFarDiff[1]);
\r
1723 program->setUniform1fv(program->getUniformLocation("gl_DepthRange.diff"), 1, &nearFarDiff[2]);
\r
1729 // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc)
\r
1730 void Context::applyState(GLenum drawMode)
\r
1732 Framebuffer *framebuffer = getDrawFramebuffer();
\r
1734 if(mState.cullFace)
\r
1736 device->setCullMode(rad2sw::ConvertCullMode(mState.cullMode, mState.frontFace));
\r
1740 device->setCullMode(sw::CULL_NONE);
\r
1743 if(mDepthStateDirty)
\r
1745 if(mState.depthTest)
\r
1747 device->setDepthBufferEnable(true);
\r
1748 device->setDepthCompare(rad2sw::ConvertDepthComparison(mState.depthFunc));
\r
1752 device->setDepthBufferEnable(false);
\r
1755 mDepthStateDirty = false;
\r
1758 if(mBlendStateDirty)
\r
1762 device->setAlphaBlendEnable(true);
\r
1763 device->setSeparateAlphaBlendEnable(true);
\r
1765 device->setBlendConstant(rad2sw::ConvertColor(mState.blendColor));
\r
1767 device->setSourceBlendFactor(rad2sw::ConvertBlendFunc(mState.sourceBlendRGB));
\r
1768 device->setDestBlendFactor(rad2sw::ConvertBlendFunc(mState.destBlendRGB));
\r
1769 device->setBlendOperation(rad2sw::ConvertBlendOp(mState.blendEquationRGB));
\r
1771 device->setSourceBlendFactorAlpha(rad2sw::ConvertBlendFunc(mState.sourceBlendAlpha));
\r
1772 device->setDestBlendFactorAlpha(rad2sw::ConvertBlendFunc(mState.destBlendAlpha));
\r
1773 device->setBlendOperationAlpha(rad2sw::ConvertBlendOp(mState.blendEquationAlpha));
\r
1777 device->setAlphaBlendEnable(false);
\r
1780 mBlendStateDirty = false;
\r
1783 if(mStencilStateDirty || mFrontFaceDirty)
\r
1785 if(mState.stencilTest && framebuffer->hasStencil())
\r
1787 device->setStencilEnable(true);
\r
1788 device->setTwoSidedStencil(true);
\r
1790 if(mState.stencilWritemask != mState.stencilBackWritemask ||
\r
1791 mState.stencilRef != mState.stencilBackRef ||
\r
1792 mState.stencilMask != mState.stencilBackMask)
\r
1794 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
\r
1795 return error(GL_INVALID_OPERATION);
\r
1798 // get the maximum size of the stencil ref
\r
1799 Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
\r
1800 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
\r
1802 if(mState.frontFace == GL_CCW)
\r
1804 device->setStencilWriteMask(mState.stencilWritemask);
\r
1805 device->setStencilCompare(rad2sw::ConvertStencilComparison(mState.stencilFunc));
\r
1807 device->setStencilReference((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
\r
1808 device->setStencilMask(mState.stencilMask);
\r
1810 device->setStencilFailOperation(rad2sw::ConvertStencilOp(mState.stencilFail));
\r
1811 device->setStencilZFailOperation(rad2sw::ConvertStencilOp(mState.stencilPassDepthFail));
\r
1812 device->setStencilPassOperation(rad2sw::ConvertStencilOp(mState.stencilPassDepthPass));
\r
1814 device->setStencilWriteMaskCCW(mState.stencilBackWritemask);
\r
1815 device->setStencilCompareCCW(rad2sw::ConvertStencilComparison(mState.stencilBackFunc));
\r
1817 device->setStencilReferenceCCW((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
\r
1818 device->setStencilMaskCCW(mState.stencilBackMask);
\r
1820 device->setStencilFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilBackFail));
\r
1821 device->setStencilZFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthFail));
\r
1822 device->setStencilPassOperationCCW(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthPass));
\r
1826 device->setStencilWriteMaskCCW(mState.stencilWritemask);
\r
1827 device->setStencilCompareCCW(rad2sw::ConvertStencilComparison(mState.stencilFunc));
\r
1829 device->setStencilReferenceCCW((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
\r
1830 device->setStencilMaskCCW(mState.stencilMask);
\r
1832 device->setStencilFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilFail));
\r
1833 device->setStencilZFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilPassDepthFail));
\r
1834 device->setStencilPassOperationCCW(rad2sw::ConvertStencilOp(mState.stencilPassDepthPass));
\r
1836 device->setStencilWriteMask(mState.stencilBackWritemask);
\r
1837 device->setStencilCompare(rad2sw::ConvertStencilComparison(mState.stencilBackFunc));
\r
1839 device->setStencilReference((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
\r
1840 device->setStencilMask(mState.stencilBackMask);
\r
1842 device->setStencilFailOperation(rad2sw::ConvertStencilOp(mState.stencilBackFail));
\r
1843 device->setStencilZFailOperation(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthFail));
\r
1844 device->setStencilPassOperation(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthPass));
\r
1849 device->setStencilEnable(false);
\r
1852 mStencilStateDirty = false;
\r
1853 mFrontFaceDirty = false;
\r
1856 if(mMaskStateDirty)
\r
1858 device->setColorWriteMask(0, rad2sw::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha));
\r
1859 device->setDepthWriteEnable(mState.depthMask);
\r
1861 mMaskStateDirty = false;
\r
1864 if(mPolygonOffsetStateDirty)
\r
1866 if(mState.polygonOffsetFill)
\r
1868 Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
\r
1871 device->setSlopeDepthBias(mState.polygonOffsetFactor);
\r
1872 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
\r
1873 device->setDepthBias(depthBias);
\r
1878 device->setSlopeDepthBias(0);
\r
1879 device->setDepthBias(0);
\r
1882 mPolygonOffsetStateDirty = false;
\r
1885 if(mSampleStateDirty)
\r
1887 if(mState.sampleAlphaToCoverage)
\r
1889 device->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE);
\r
1893 device->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE);
\r
1896 if(mState.sampleCoverage)
\r
1898 unsigned int mask = 0;
\r
1899 if(mState.sampleCoverageValue != 0)
\r
1901 int width, height, samples;
\r
1902 framebuffer->completeness(width, height, samples);
\r
1904 float threshold = 0.5f;
\r
1906 for(int i = 0; i < samples; i++)
\r
1910 if((i + 1) * mState.sampleCoverageValue >= threshold)
\r
1912 threshold += 1.0f;
\r
1918 if(mState.sampleCoverageInvert)
\r
1923 device->setMultiSampleMask(mask);
\r
1927 device->setMultiSampleMask(0xFFFFFFFF);
\r
1930 mSampleStateDirty = false;
\r
1933 if(mDitherStateDirty)
\r
1935 // UNIMPLEMENTED(); // FIXME
\r
1937 mDitherStateDirty = false;
\r
1941 GLenum Context::applyVertexBuffer(GLint base, GLint first, GLsizei count)
\r
1943 TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];
\r
1945 GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes);
\r
1946 if(err != GL_NO_ERROR)
\r
1951 Program *program = getCurrentProgram();
\r
1953 device->resetInputStreams(false);
\r
1955 for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
\r
1957 if(program->getAttributeStream(i) == -1)
\r
1962 sw::Resource *resource = attributes[i].vertexBuffer;
\r
1963 const void *buffer = (char*)resource->getBuffer() + attributes[i].offset;
\r
1965 int stride = attributes[i].stride;
\r
1967 buffer = (char*)buffer + stride * base;
\r
1969 sw::Stream attribute(resource, buffer, stride);
\r
1971 attribute.type = attributes[i].type;
\r
1972 attribute.count = attributes[i].count;
\r
1973 attribute.normalized = attributes[i].normalized;
\r
1975 int stream = program->getAttributeStream(i);
\r
1976 device->setInputStream(stream, attribute);
\r
1979 return GL_NO_ERROR;
\r
1982 // Applies the indices and element array bindings
\r
1983 GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
\r
1985 GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
\r
1987 if(err == GL_NO_ERROR)
\r
1989 device->setIndexBuffer(indexInfo->indexBuffer);
\r
1995 // Applies the shaders and shader constants
\r
1996 void Context::applyShaders()
\r
1998 Program *programObject = getCurrentProgram();
\r
1999 sw::VertexShader *vertexShader = programObject->getVertexShader();
\r
2000 sw::PixelShader *pixelShader = programObject->getPixelShader();
\r
2002 device->setVertexShader(vertexShader);
\r
2003 device->setPixelShader(pixelShader);
\r
2005 if(programObject->getSerial() != mAppliedProgramSerial)
\r
2007 programObject->dirtyAllUniforms();
\r
2008 mAppliedProgramSerial = programObject->getSerial();
\r
2011 programObject->applyUniforms();
\r
2014 void Context::applyTextures()
\r
2016 applyTextures(sw::SAMPLER_PIXEL);
\r
2017 applyTextures(sw::SAMPLER_VERTEX);
\r
2020 void Context::applyTextures(sw::SamplerType samplerType)
\r
2022 Program *programObject = getCurrentProgram();
\r
2024 int samplerCount = (samplerType == sw::SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS; // Range of samplers of given sampler type
\r
2026 for(int samplerIndex = 0; samplerIndex < samplerCount; samplerIndex++)
\r
2028 int textureUnit = programObject->getSamplerMapping(samplerType, samplerIndex); // OpenGL texture image unit index
\r
2030 if(textureUnit != -1)
\r
2032 TextureType textureType = programObject->getSamplerTextureType(samplerType, samplerIndex);
\r
2034 Texture *texture = getSamplerTexture(textureUnit, textureType);
\r
2036 if(texture->isSamplerComplete())
\r
2038 GLenum wrapS = texture->getWrapS();
\r
2039 GLenum wrapT = texture->getWrapT();
\r
2040 GLenum texFilter = texture->getMinFilter();
\r
2041 GLenum magFilter = texture->getMagFilter();
\r
2042 GLfloat maxAnisotropy = texture->getMaxAnisotropy();
\r
2044 device->setAddressingModeU(samplerType, samplerIndex, rad2sw::ConvertTextureWrap(wrapS));
\r
2045 device->setAddressingModeV(samplerType, samplerIndex, rad2sw::ConvertTextureWrap(wrapT));
\r
2047 sw::FilterType minFilter;
\r
2048 sw::MipmapType mipFilter;
\r
2049 rad2sw::ConvertMinFilter(texFilter, &minFilter, &mipFilter, maxAnisotropy);
\r
2050 // ASSERT(minFilter == rad2sw::ConvertMagFilter(magFilter));
\r
2052 device->setTextureFilter(samplerType, samplerIndex, minFilter);
\r
2053 // device->setTextureFilter(samplerType, samplerIndex, rad2sw::ConvertMagFilter(magFilter));
\r
2054 device->setMipmapFilter(samplerType, samplerIndex, mipFilter);
\r
2055 device->setMaxAnisotropy(samplerType, samplerIndex, maxAnisotropy);
\r
2057 applyTexture(samplerType, samplerIndex, texture);
\r
2061 applyTexture(samplerType, samplerIndex, 0);
\r
2066 applyTexture(samplerType, samplerIndex, NULL);
\r
2071 void Context::applyTexture(sw::SamplerType type, int index, Texture *baseTexture)
\r
2073 //Program *program = getCurrentProgram();
\r
2074 int sampler = (type == sw::SAMPLER_PIXEL) ? index : 16 + index;
\r
2075 bool textureUsed = true;
\r
2077 //if(type == sw::SAMPLER_PIXEL)
\r
2079 // textureUsed = program->getPixelShader()->usesSampler(index);
\r
2081 //else if(type == sw::SAMPLER_VERTEX)
\r
2083 // textureUsed = program->getVertexShader()->usesSampler(index);
\r
2085 //else UNREACHABLE();
\r
2087 // GLenum wrapS = baseTexture->getWrapS();
\r
2088 // GLenum wrapT = baseTexture->getWrapT();
\r
2089 // GLenum texFilter = baseTexture->getMinFilter();
\r
2090 // GLenum magFilter = baseTexture->getMagFilter();
\r
2091 // GLenum maxAnisotropy = baseTexture->getMaxAnisotropy();
\r
2093 // device->setAddressingModeU(type, index, rad2sw::ConvertTextureWrap(wrapS));
\r
2094 // device->setAddressingModeV(type, index, rad2sw::ConvertTextureWrap(wrapT));
\r
2096 // sw::FilterType minFilter;
\r
2097 // sw::MipmapType mipFilter;
\r
2098 // rad2sw::ConvertMinFilter(texFilter, &minFilter, &mipFilter, maxAnisotropy);
\r
2099 //// ASSERT(minFilter == rad2sw::ConvertMagFilter(magFilter));
\r
2101 device->setTextureFilter(type, index, sw::FILTER_LINEAR);
\r
2102 // device->setTextureFilter(type, index, rad2sw::ConvertMagFilter(magFilter));
\r
2103 device->setMipmapFilter(type, index, sw::MIPMAP_NONE);
\r
2104 device->setMaxAnisotropy(type, index, 1.0f);
\r
2106 sw::Resource *resource = 0;
\r
2108 if(baseTexture && textureUsed)
\r
2110 resource = baseTexture->getResource();
\r
2113 device->setTextureResource(sampler, resource);
\r
2115 if(baseTexture && textureUsed)
\r
2117 int levelCount = baseTexture->getLevelCount();
\r
2119 if(baseTexture->getTarget() == GL_TEXTURE_2D || baseTexture->getTarget() == GL_TEXTURE_EXTERNAL_OES)
\r
2121 Texture2D *texture = static_cast<Texture2D*>(baseTexture);
\r
2123 for(int mipmapLevel = 0; mipmapLevel < MIPMAP_LEVELS; mipmapLevel++)
\r
2125 int surfaceLevel = mipmapLevel;
\r
2127 if(surfaceLevel < 0)
\r
2131 else if(surfaceLevel >= levelCount)
\r
2133 surfaceLevel = levelCount - 1;
\r
2136 egl::Image *surface = texture->getImage(surfaceLevel);
\r
2137 device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D);
\r
2140 else if(baseTexture->getTarget() == GL_TEXTURE_CUBE_MAP)
\r
2142 for(int face = 0; face < 6; face++)
\r
2144 TextureCubeMap *cubeTexture = static_cast<TextureCubeMap*>(baseTexture);
\r
2146 for(int mipmapLevel = 0; mipmapLevel < MIPMAP_LEVELS; mipmapLevel++)
\r
2148 int surfaceLevel = mipmapLevel;
\r
2150 if(surfaceLevel < 0)
\r
2154 else if(surfaceLevel >= levelCount)
\r
2156 surfaceLevel = levelCount - 1;
\r
2159 egl::Image *surface = cubeTexture->getImage(face, surfaceLevel);
\r
2160 device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
\r
2164 else UNIMPLEMENTED();
\r
2168 device->setTextureLevel(sampler, 0, 0, 0, sw::TEXTURE_NULL);
\r
2172 void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
\r
2173 GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
\r
2175 Framebuffer *framebuffer = getReadFramebuffer();
\r
2176 int framebufferWidth, framebufferHeight, framebufferSamples;
\r
2178 if(framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE)
\r
2180 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
\r
2183 if(getReadFramebufferHandle() != 0 && framebufferSamples != 0)
\r
2185 return error(GL_INVALID_OPERATION);
\r
2188 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
\r
2190 // Sized query sanity check
\r
2193 int requiredSize = outputPitch * height;
\r
2194 if(requiredSize > *bufSize)
\r
2196 return error(GL_INVALID_OPERATION);
\r
2200 egl::Image *renderTarget = framebuffer->getRenderTarget();
\r
2204 return error(GL_OUT_OF_MEMORY);
\r
2207 sw::Rect rect = {x, y, x + width, y + height};
\r
2208 rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight());
\r
2210 unsigned char *source = (unsigned char*)renderTarget->lock(rect.x0, rect.y0, sw::LOCK_READONLY);
\r
2211 unsigned char *dest = (unsigned char*)pixels;
\r
2212 unsigned short *dest16 = (unsigned short*)pixels;
\r
2213 int inputPitch = (int)renderTarget->getPitch();
\r
2215 for(int j = 0; j < rect.y1 - rect.y0; j++)
\r
2217 if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 &&
\r
2218 format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE)
\r
2220 // Fast path for EXT_read_format_bgra, given an RGBA source buffer
\r
2221 // Note that buffers with no alpha go through the slow path below
\r
2222 memcpy(dest + j * outputPitch, source + j * inputPitch, (rect.x1 - rect.x0) * 4);
\r
2226 for(int i = 0; i < rect.x1 - rect.x0; i++)
\r
2233 switch(renderTarget->getInternalFormat())
\r
2235 case sw::FORMAT_R5G6B5:
\r
2237 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
\r
2240 b = (rgb & 0x001F) * (1.0f / 0x001F);
\r
2241 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
\r
2242 r = (rgb & 0xF800) * (1.0f / 0xF800);
\r
2245 case sw::FORMAT_A1R5G5B5:
\r
2247 unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
\r
2249 a = (argb & 0x8000) ? 1.0f : 0.0f;
\r
2250 b = (argb & 0x001F) * (1.0f / 0x001F);
\r
2251 g = (argb & 0x03E0) * (1.0f / 0x03E0);
\r
2252 r = (argb & 0x7C00) * (1.0f / 0x7C00);
\r
2255 case sw::FORMAT_A8R8G8B8:
\r
2257 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
\r
2259 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
\r
2260 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
\r
2261 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
\r
2262 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
\r
2265 case sw::FORMAT_X8R8G8B8:
\r
2267 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
\r
2270 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
\r
2271 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
\r
2272 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
\r
2275 case sw::FORMAT_A2R10G10B10:
\r
2277 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
\r
2279 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
\r
2280 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
\r
2281 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
\r
2282 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
\r
2285 case sw::FORMAT_A32B32G32R32F:
\r
2287 r = *((float*)(source + 16 * i + j * inputPitch) + 0);
\r
2288 g = *((float*)(source + 16 * i + j * inputPitch) + 1);
\r
2289 b = *((float*)(source + 16 * i + j * inputPitch) + 2);
\r
2290 a = *((float*)(source + 16 * i + j * inputPitch) + 3);
\r
2293 case sw::FORMAT_A16B16G16R16F:
\r
2295 r = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 0);
\r
2296 g = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 1);
\r
2297 b = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 2);
\r
2298 a = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 3);
\r
2302 UNIMPLEMENTED(); // FIXME
\r
2311 case GL_UNSIGNED_BYTE:
\r
2312 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
\r
2313 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
\r
2314 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
\r
2315 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
\r
2317 default: UNREACHABLE();
\r
2323 case GL_UNSIGNED_BYTE:
\r
2324 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
\r
2325 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
\r
2326 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
\r
2327 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
\r
2329 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
\r
2330 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
\r
2331 // this type is packed as follows:
\r
2332 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
\r
2333 // --------------------------------------------------------------------------------
\r
2334 // | 4th | 3rd | 2nd | 1st component |
\r
2335 // --------------------------------------------------------------------------------
\r
2336 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
\r
2337 dest16[i + j * outputPitch / sizeof(unsigned short)] =
\r
2338 ((unsigned short)(15 * a + 0.5f) << 12)|
\r
2339 ((unsigned short)(15 * r + 0.5f) << 8) |
\r
2340 ((unsigned short)(15 * g + 0.5f) << 4) |
\r
2341 ((unsigned short)(15 * b + 0.5f) << 0);
\r
2343 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
\r
2344 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
\r
2345 // this type is packed as follows:
\r
2346 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
\r
2347 // --------------------------------------------------------------------------------
\r
2348 // | 4th | 3rd | 2nd | 1st component |
\r
2349 // --------------------------------------------------------------------------------
\r
2350 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
\r
2351 dest16[i + j * outputPitch / sizeof(unsigned short)] =
\r
2352 ((unsigned short)( a + 0.5f) << 15) |
\r
2353 ((unsigned short)(31 * r + 0.5f) << 10) |
\r
2354 ((unsigned short)(31 * g + 0.5f) << 5) |
\r
2355 ((unsigned short)(31 * b + 0.5f) << 0);
\r
2357 default: UNREACHABLE();
\r
2360 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
\r
2363 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
\r
2364 dest16[i + j * outputPitch / sizeof(unsigned short)] =
\r
2365 ((unsigned short)(31 * b + 0.5f) << 0) |
\r
2366 ((unsigned short)(63 * g + 0.5f) << 5) |
\r
2367 ((unsigned short)(31 * r + 0.5f) << 11);
\r
2369 default: UNREACHABLE();
\r
2372 default: UNREACHABLE();
\r
2378 renderTarget->unlock();
\r
2379 renderTarget->release();
\r
2382 void Context::clear(GLbitfield mask)
\r
2384 Framebuffer *framebuffer = getDrawFramebuffer();
\r
2386 if(!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
\r
2388 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
\r
2391 if(!applyRenderTarget())
\r
2396 unsigned int color = (unorm<8>(mState.colorClearValue.alpha) << 24) |
\r
2397 (unorm<8>(mState.colorClearValue.red) << 16) |
\r
2398 (unorm<8>(mState.colorClearValue.green) << 8) |
\r
2399 (unorm<8>(mState.colorClearValue.blue) << 0);
\r
2400 float depth = clamp01(mState.depthClearValue);
\r
2401 int stencil = mState.stencilClearValue & 0x000000FF;
\r
2403 if(mask & GL_COLOR_BUFFER_BIT)
\r
2405 unsigned int rgbaMask = (mState.colorMaskRed ? 0x1 : 0) |
\r
2406 (mState.colorMaskGreen ? 0x2 : 0) |
\r
2407 (mState.colorMaskBlue ? 0x4 : 0) |
\r
2408 (mState.colorMaskAlpha ? 0x8 : 0);
\r
2412 device->clearColor(color, rgbaMask);
\r
2416 if(mask & GL_DEPTH_BUFFER_BIT)
\r
2418 if(mState.depthMask != 0)
\r
2420 device->clearDepth(depth);
\r
2424 if(mask & GL_STENCIL_BUFFER_BIT)
\r
2426 if(mState.stencilWritemask != 0)
\r
2428 device->clearStencil(stencil, mState.stencilWritemask);
\r
2433 void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
\r
2435 if(!mState.currentProgram)
\r
2437 return error(GL_INVALID_OPERATION);
\r
2440 PrimitiveType primitiveType;
\r
2441 int primitiveCount;
\r
2443 if(!rad2sw::ConvertPrimitiveType(mode, count, primitiveType, primitiveCount))
\r
2444 return error(GL_INVALID_ENUM);
\r
2446 if(primitiveCount <= 0)
\r
2451 if(!applyRenderTarget())
\r
2458 GLenum err = applyVertexBuffer(0, first, count);
\r
2459 if(err != GL_NO_ERROR)
\r
2461 return error(err);
\r
2467 if(!getCurrentProgram()->validateSamplers(false))
\r
2469 return error(GL_INVALID_OPERATION);
\r
2472 if(!cullSkipsDraw(mode))
\r
2474 device->drawPrimitive(primitiveType, primitiveCount);
\r
2478 void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
\r
2480 if(!mState.currentProgram && !mState.program)
\r
2482 return error(GL_INVALID_OPERATION);
\r
2485 if(!indices && !mState.elementArrayBuffer)
\r
2487 return error(GL_INVALID_OPERATION);
\r
2490 PrimitiveType primitiveType;
\r
2491 int primitiveCount;
\r
2493 if(!rad2sw::ConvertPrimitiveType(mode, count, primitiveType, primitiveCount))
\r
2494 return error(GL_INVALID_ENUM);
\r
2496 if(primitiveCount <= 0)
\r
2501 if(!applyRenderTarget())
\r
2508 TranslatedIndexData indexInfo;
\r
2509 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
\r
2510 if(err != GL_NO_ERROR)
\r
2512 return error(err);
\r
2515 GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
\r
2516 err = applyVertexBuffer(-(int)indexInfo.minIndex, indexInfo.minIndex, vertexCount);
\r
2517 if(err != GL_NO_ERROR)
\r
2519 return error(err);
\r
2523 //applyTextures();
\r
2525 if(!getCurrentProgram()->validateSamplers(false))
\r
2527 return error(GL_INVALID_OPERATION);
\r
2530 if(!cullSkipsDraw(mode))
\r
2532 device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, primitiveCount, IndexDataManager::typeSize(type));
\r
2536 void Context::finish()
\r
2541 void Context::flush()
\r
2543 // We don't queue anything without processing it as fast as possible
\r
2546 void Context::recordInvalidEnum()
\r
2548 mInvalidEnum = true;
\r
2551 void Context::recordInvalidValue()
\r
2553 mInvalidValue = true;
\r
2556 void Context::recordInvalidOperation()
\r
2558 mInvalidOperation = true;
\r
2561 void Context::recordOutOfMemory()
\r
2563 mOutOfMemory = true;
\r
2566 void Context::recordInvalidFramebufferOperation()
\r
2568 mInvalidFramebufferOperation = true;
\r
2571 // Get one of the recorded errors and clear its flag, if any.
\r
2572 // [OpenGL ES 2.0.24] section 2.5 page 13.
\r
2573 GLenum Context::getError()
\r
2577 mInvalidEnum = false;
\r
2579 return GL_INVALID_ENUM;
\r
2584 mInvalidValue = false;
\r
2586 return GL_INVALID_VALUE;
\r
2589 if(mInvalidOperation)
\r
2591 mInvalidOperation = false;
\r
2593 return GL_INVALID_OPERATION;
\r
2598 mOutOfMemory = false;
\r
2600 return GL_OUT_OF_MEMORY;
\r
2603 if(mInvalidFramebufferOperation)
\r
2605 mInvalidFramebufferOperation = false;
\r
2607 return GL_INVALID_FRAMEBUFFER_OPERATION;
\r
2610 return GL_NO_ERROR;
\r
2613 int Context::getSupportedMultiSampleDepth(sw::Format format, int requested)
\r
2615 if(requested <= 1)
\r
2620 if(requested == 2)
\r
2628 void Context::detachBuffer(GLuint buffer)
\r
2630 // [OpenGL ES 2.0.24] section 2.9 page 22:
\r
2631 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
\r
2632 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
\r
2634 if(mState.arrayBuffer.id() == buffer)
\r
2636 mState.arrayBuffer.set(NULL);
\r
2639 if(mState.elementArrayBuffer.id() == buffer)
\r
2641 mState.elementArrayBuffer.set(NULL);
\r
2644 for(int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
\r
2646 if(mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
\r
2648 mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
\r
2653 void Context::detachTexture(GLuint texture)
\r
2655 // [OpenGL ES 2.0.24] section 3.8 page 84:
\r
2656 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
\r
2657 // rebound to texture object zero
\r
2659 for(int type = 0; type < TEXTURE_TYPE_COUNT; type++)
\r
2661 for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
\r
2663 if(mState.samplerTexture[type][sampler].id() == texture)
\r
2665 mState.samplerTexture[type][sampler].set(NULL);
\r
2670 // [OpenGL ES 2.0.24] section 4.4 page 112:
\r
2671 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
\r
2672 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
\r
2673 // image was attached in the currently bound framebuffer.
\r
2675 Framebuffer *readFramebuffer = getReadFramebuffer();
\r
2676 Framebuffer *drawFramebuffer = getDrawFramebuffer();
\r
2678 if(readFramebuffer)
\r
2680 readFramebuffer->detachTexture(texture);
\r
2683 if(drawFramebuffer && drawFramebuffer != readFramebuffer)
\r
2685 drawFramebuffer->detachTexture(texture);
\r
2689 void Context::detachFramebuffer(GLuint framebuffer)
\r
2691 // [OpenGL ES 2.0.24] section 4.4 page 107:
\r
2692 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
\r
2693 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
\r
2695 if(mState.readFramebuffer == framebuffer)
\r
2697 bindReadFramebuffer(0);
\r
2700 if(mState.drawFramebuffer == framebuffer)
\r
2702 bindDrawFramebuffer(0);
\r
2706 void Context::detachRenderbuffer(GLuint renderbuffer)
\r
2708 // [OpenGL ES 2.0.24] section 4.4 page 109:
\r
2709 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
\r
2710 // had been executed with the target RENDERBUFFER and name of zero.
\r
2712 if(mState.renderbuffer.id() == renderbuffer)
\r
2714 bindRenderbuffer(0);
\r
2717 // [OpenGL ES 2.0.24] section 4.4 page 111:
\r
2718 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
\r
2719 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
\r
2720 // point to which this image was attached in the currently bound framebuffer.
\r
2722 Framebuffer *readFramebuffer = getReadFramebuffer();
\r
2723 Framebuffer *drawFramebuffer = getDrawFramebuffer();
\r
2725 if(readFramebuffer)
\r
2727 readFramebuffer->detachRenderbuffer(renderbuffer);
\r
2730 if(drawFramebuffer && drawFramebuffer != readFramebuffer)
\r
2732 drawFramebuffer->detachRenderbuffer(renderbuffer);
\r
2736 bool Context::cullSkipsDraw(GLenum drawMode)
\r
2738 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
\r
2741 bool Context::isTriangleMode(GLenum drawMode)
\r
2745 case GL_TRIANGLES:
\r
2746 case GL_TRIANGLE_FAN:
\r
2747 case GL_TRIANGLE_STRIP:
\r
2751 case GL_LINE_LOOP:
\r
2752 case GL_LINE_STRIP:
\r
2754 default: UNREACHABLE();
\r
2760 void Context::setVertexAttrib(GLuint index, const GLfloat *values)
\r
2762 ASSERT(index < MAX_VERTEX_ATTRIBS);
\r
2764 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
\r
2765 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
\r
2766 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
\r
2767 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
\r
2769 mVertexDataManager->dirtyCurrentValue(index);
\r
2772 void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
\r
2773 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
\r
2776 Framebuffer *readFramebuffer = getReadFramebuffer();
\r
2777 Framebuffer *drawFramebuffer = getDrawFramebuffer();
\r
2779 int readBufferWidth, readBufferHeight, readBufferSamples;
\r
2780 int drawBufferWidth, drawBufferHeight, drawBufferSamples;
\r
2782 if(!readFramebuffer || readFramebuffer->completeness(readBufferWidth, readBufferHeight, readBufferSamples) != GL_FRAMEBUFFER_COMPLETE ||
\r
2783 !drawFramebuffer || drawFramebuffer->completeness(drawBufferWidth, drawBufferHeight, drawBufferSamples) != GL_FRAMEBUFFER_COMPLETE)
\r
2785 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
\r
2788 if(drawBufferSamples > 1)
\r
2790 return error(GL_INVALID_OPERATION);
\r
2793 sw::Rect sourceRect;
\r
2794 sw::Rect destRect;
\r
2798 sourceRect.x0 = srcX0;
\r
2799 sourceRect.x1 = srcX1;
\r
2800 destRect.x0 = dstX0;
\r
2801 destRect.x1 = dstX1;
\r
2805 sourceRect.x0 = srcX1;
\r
2806 destRect.x0 = dstX1;
\r
2807 sourceRect.x1 = srcX0;
\r
2808 destRect.x1 = dstX0;
\r
2813 sourceRect.y0 = srcY0;
\r
2814 destRect.y0 = dstY0;
\r
2815 sourceRect.y1 = srcY1;
\r
2816 destRect.y1 = dstY1;
\r
2820 sourceRect.y0 = srcY1;
\r
2821 destRect.y0 = dstY1;
\r
2822 sourceRect.y1 = srcY0;
\r
2823 destRect.y1 = dstY0;
\r
2826 sw::Rect sourceScissoredRect = sourceRect;
\r
2827 sw::Rect destScissoredRect = destRect;
\r
2829 if(mState.scissorTest) // Only write to parts of the destination framebuffer which pass the scissor test
\r
2831 if(destRect.x0 < mState.scissorX)
\r
2833 int xDiff = mState.scissorX - destRect.x0;
\r
2834 destScissoredRect.x0 = mState.scissorX;
\r
2835 sourceScissoredRect.x0 += xDiff;
\r
2838 if(destRect.x1 > mState.scissorX + mState.scissorWidth)
\r
2840 int xDiff = destRect.x1 - (mState.scissorX + mState.scissorWidth);
\r
2841 destScissoredRect.x1 = mState.scissorX + mState.scissorWidth;
\r
2842 sourceScissoredRect.x1 -= xDiff;
\r
2845 if(destRect.y0 < mState.scissorY)
\r
2847 int yDiff = mState.scissorY - destRect.y0;
\r
2848 destScissoredRect.y0 = mState.scissorY;
\r
2849 sourceScissoredRect.y0 += yDiff;
\r
2852 if(destRect.y1 > mState.scissorY + mState.scissorHeight)
\r
2854 int yDiff = destRect.y1 - (mState.scissorY + mState.scissorHeight);
\r
2855 destScissoredRect.y1 = mState.scissorY + mState.scissorHeight;
\r
2856 sourceScissoredRect.y1 -= yDiff;
\r
2860 sw::Rect sourceTrimmedRect = sourceScissoredRect;
\r
2861 sw::Rect destTrimmedRect = destScissoredRect;
\r
2863 // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of
\r
2864 // the actual draw and read surfaces.
\r
2865 if(sourceTrimmedRect.x0 < 0)
\r
2867 int xDiff = 0 - sourceTrimmedRect.x0;
\r
2868 sourceTrimmedRect.x0 = 0;
\r
2869 destTrimmedRect.x0 += xDiff;
\r
2872 if(sourceTrimmedRect.x1 > readBufferWidth)
\r
2874 int xDiff = sourceTrimmedRect.x1 - readBufferWidth;
\r
2875 sourceTrimmedRect.x1 = readBufferWidth;
\r
2876 destTrimmedRect.x1 -= xDiff;
\r
2879 if(sourceTrimmedRect.y0 < 0)
\r
2881 int yDiff = 0 - sourceTrimmedRect.y0;
\r
2882 sourceTrimmedRect.y0 = 0;
\r
2883 destTrimmedRect.y0 += yDiff;
\r
2886 if(sourceTrimmedRect.y1 > readBufferHeight)
\r
2888 int yDiff = sourceTrimmedRect.y1 - readBufferHeight;
\r
2889 sourceTrimmedRect.y1 = readBufferHeight;
\r
2890 destTrimmedRect.y1 -= yDiff;
\r
2893 if(destTrimmedRect.x0 < 0)
\r
2895 int xDiff = 0 - destTrimmedRect.x0;
\r
2896 destTrimmedRect.x0 = 0;
\r
2897 sourceTrimmedRect.x0 += xDiff;
\r
2900 if(destTrimmedRect.x1 > drawBufferWidth)
\r
2902 int xDiff = destTrimmedRect.x1 - drawBufferWidth;
\r
2903 destTrimmedRect.x1 = drawBufferWidth;
\r
2904 sourceTrimmedRect.x1 -= xDiff;
\r
2907 if(destTrimmedRect.y0 < 0)
\r
2909 int yDiff = 0 - destTrimmedRect.y0;
\r
2910 destTrimmedRect.y0 = 0;
\r
2911 sourceTrimmedRect.y0 += yDiff;
\r
2914 if(destTrimmedRect.y1 > drawBufferHeight)
\r
2916 int yDiff = destTrimmedRect.y1 - drawBufferHeight;
\r
2917 destTrimmedRect.y1 = drawBufferHeight;
\r
2918 sourceTrimmedRect.y1 -= yDiff;
\r
2921 bool partialBufferCopy = false;
\r
2923 if(sourceTrimmedRect.y1 - sourceTrimmedRect.y0 < readBufferHeight ||
\r
2924 sourceTrimmedRect.x1 - sourceTrimmedRect.x0 < readBufferWidth ||
\r
2925 destTrimmedRect.y1 - destTrimmedRect.y0 < drawBufferHeight ||
\r
2926 destTrimmedRect.x1 - destTrimmedRect.x0 < drawBufferWidth ||
\r
2927 sourceTrimmedRect.y0 != 0 || destTrimmedRect.y0 != 0 || sourceTrimmedRect.x0 != 0 || destTrimmedRect.x0 != 0)
\r
2929 partialBufferCopy = true;
\r
2932 bool blitRenderTarget = false;
\r
2933 bool blitDepthStencil = false;
\r
2935 if(mask & GL_COLOR_BUFFER_BIT)
\r
2937 const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
\r
2938 readFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
\r
2939 const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
\r
2940 drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
\r
2941 if(!validReadType || !validDrawType ||
\r
2942 readFramebuffer->getColorbuffer()->getInternalFormat() != drawFramebuffer->getColorbuffer()->getInternalFormat())
\r
2944 ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
\r
2945 return error(GL_INVALID_OPERATION);
\r
2948 if(partialBufferCopy && readBufferSamples > 1)
\r
2950 return error(GL_INVALID_OPERATION);
\r
2953 blitRenderTarget = true;
\r
2956 if(mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
\r
2958 Renderbuffer *readDSBuffer = NULL;
\r
2959 Renderbuffer *drawDSBuffer = NULL;
\r
2961 // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
\r
2962 // both a depth and stencil buffer, it will be the same buffer.
\r
2964 if(mask & GL_DEPTH_BUFFER_BIT)
\r
2966 if(readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
\r
2968 if(readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
\r
2969 readFramebuffer->getDepthbuffer()->getInternalFormat() != drawFramebuffer->getDepthbuffer()->getInternalFormat())
\r
2971 return error(GL_INVALID_OPERATION);
\r
2974 blitDepthStencil = true;
\r
2975 readDSBuffer = readFramebuffer->getDepthbuffer();
\r
2976 drawDSBuffer = drawFramebuffer->getDepthbuffer();
\r
2980 if(mask & GL_STENCIL_BUFFER_BIT)
\r
2982 if(readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
\r
2984 if(readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
\r
2985 readFramebuffer->getStencilbuffer()->getInternalFormat() != drawFramebuffer->getStencilbuffer()->getInternalFormat())
\r
2987 return error(GL_INVALID_OPERATION);
\r
2990 blitDepthStencil = true;
\r
2991 readDSBuffer = readFramebuffer->getStencilbuffer();
\r
2992 drawDSBuffer = drawFramebuffer->getStencilbuffer();
\r
2996 if(partialBufferCopy)
\r
2998 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
\r
2999 return error(GL_INVALID_OPERATION); // Only whole-buffer copies are permitted
\r
3002 if((drawDSBuffer && drawDSBuffer->getSamples() > 1) ||
\r
3003 (readDSBuffer && readDSBuffer->getSamples() > 1))
\r
3005 return error(GL_INVALID_OPERATION);
\r
3009 if(blitRenderTarget || blitDepthStencil)
\r
3011 if(blitRenderTarget)
\r
3013 egl::Image *readRenderTarget = readFramebuffer->getRenderTarget();
\r
3014 egl::Image *drawRenderTarget = drawFramebuffer->getRenderTarget();
\r
3016 bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, false);
\r
3018 readRenderTarget->release();
\r
3019 drawRenderTarget->release();
\r
3023 ERR("BlitFramebufferANGLE failed.");
\r
3028 if(blitDepthStencil)
\r
3030 bool success = device->stretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, false);
\r
3034 ERR("BlitFramebufferANGLE failed.");
\r
3041 void Context::bindTexImage(egl::Surface *surface)
\r
3043 es2::Texture2D *textureObject = getTexture2D();
\r
3047 textureObject->bindTexImage(surface);
\r
3051 EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel)
\r
3053 GLenum textureTarget = GL_NONE;
\r
3057 case EGL_GL_TEXTURE_2D_KHR:
\r
3058 textureTarget = GL_TEXTURE_2D;
\r
3060 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
\r
3061 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
\r
3062 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
\r
3063 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
\r
3064 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
\r
3065 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
\r
3066 textureTarget = GL_TEXTURE_CUBE_MAP;
\r
3068 case EGL_GL_RENDERBUFFER_KHR:
\r
3071 return EGL_BAD_PARAMETER;
\r
3074 if(textureLevel >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
\r
3076 return EGL_BAD_MATCH;
\r
3079 if(textureTarget != GL_NONE)
\r
3081 es2::Texture *texture = getTexture(name);
\r
3083 if(!texture || texture->getTarget() != textureTarget)
\r
3085 return EGL_BAD_PARAMETER;
\r
3088 if(texture->isShared(textureTarget, textureLevel)) // Bound to an EGLSurface or already an EGLImage sibling
\r
3090 return EGL_BAD_ACCESS;
\r
3093 if(textureLevel != 0 && !texture->isSamplerComplete())
\r
3095 return EGL_BAD_PARAMETER;
\r
3098 if(textureLevel == 0 && !(texture->isSamplerComplete() && texture->getLevelCount() == 1))
\r
3100 return EGL_BAD_PARAMETER;
\r
3103 else if(target == EGL_GL_RENDERBUFFER_KHR)
\r
3105 es2::Renderbuffer *renderbuffer = getRenderbuffer(name);
\r
3109 return EGL_BAD_PARAMETER;
\r
3112 if(renderbuffer->isShared()) // Already an EGLImage sibling
\r
3114 return EGL_BAD_ACCESS;
\r
3117 else UNREACHABLE();
\r
3119 return EGL_SUCCESS;
\r
3122 egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textureLevel)
\r
3124 GLenum textureTarget = GL_NONE;
\r
3128 case EGL_GL_TEXTURE_2D_KHR: textureTarget = GL_TEXTURE_2D; break;
\r
3129 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; break;
\r
3130 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; break;
\r
3131 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; break;
\r
3132 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; break;
\r
3133 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; break;
\r
3134 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; break;
\r
3137 if(textureTarget != GL_NONE)
\r
3139 es2::Texture *texture = getTexture(name);
\r
3141 return texture->createSharedImage(textureTarget, textureLevel);
\r
3143 else if(target == EGL_GL_RENDERBUFFER_KHR)
\r
3145 es2::Renderbuffer *renderbuffer = getRenderbuffer(name);
\r
3147 return renderbuffer->createSharedImage();
\r
3149 else UNREACHABLE();
\r
3154 Device *Context::getDevice()
\r
3158 sw::Context *context = new sw::Context();
\r
3159 device = new es2::Device(context);
\r
3167 // Exported functions for use by EGL
\r
3170 es2::Context *glCreateContext(const egl::Config *config, const es2::Context *shareContext)
\r
3172 return new es2::Context(config, shareContext);
\r