OSDN Git Service

Implement a Radiance prototype.
[android-x86/external-swiftshader.git] / src / Radiance / libRAD / Context.cpp
1 // SwiftShader Software Renderer\r
2 //\r
3 // Copyright(c) 2005-2013 TransGaming Inc.\r
4 //\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
10 //\r
11 \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
14 \r
15 #include "Context.h"\r
16 \r
17 #include "main.h"\r
18 #include "mathutil.h"\r
19 #include "utilities.h"\r
20 #include "ResourceManager.h"\r
21 #include "Buffer.h"\r
22 #include "Fence.h"\r
23 #include "Framebuffer.h"\r
24 #include "Program.h"\r
25 #include "Query.h"\r
26 #include "Renderbuffer.h"\r
27 #include "Shader.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
34 \r
35 #include <EGL/eglext.h>\r
36 \r
37 #undef near\r
38 #undef far\r
39 \r
40 namespace es2\r
41 {\r
42 Device *Context::device = 0;\r
43 \r
44 Context::Context(const egl::Config *config, const Context *shareContext) : mConfig(config)\r
45 {\r
46         device = getDevice();\r
47 \r
48     mFenceHandleAllocator.setBaseHandle(0);\r
49 \r
50     setClearColor(0.0f, 0.0f, 0.0f, 0.0f);\r
51 \r
52     mState.depthClearValue = 1.0f;\r
53     mState.stencilClearValue = 0;\r
54 \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
97 \r
98     mState.lineWidth = 1.0f;\r
99 \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
106 \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
111 \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
117 \r
118     if(shareContext != NULL)\r
119     {\r
120         mResourceManager = shareContext->mResourceManager;\r
121         mResourceManager->addRef();\r
122     }\r
123     else\r
124     {\r
125         mResourceManager = new ResourceManager();\r
126     }\r
127 \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
133 \r
134     mTexture2DZero.set(new Texture2D(0));\r
135     mTextureCubeMapZero.set(new TextureCubeMap(0));\r
136     mTextureExternalZero.set(new TextureExternal(0));\r
137 \r
138     mState.activeSampler = 0;\r
139     bindArrayBuffer(0);\r
140     bindElementArrayBuffer(0);\r
141     bindTextureCubeMap(0);\r
142     bindTexture2D(0);\r
143     bindReadFramebuffer(0);\r
144     bindDrawFramebuffer(0);\r
145     bindRenderbuffer(0);\r
146 \r
147     mState.currentProgram = 0;\r
148 \r
149     mState.packAlignment = 4;\r
150     mState.unpackAlignment = 4;\r
151 \r
152     mVertexDataManager = NULL;\r
153     mIndexDataManager = NULL;\r
154 \r
155     mInvalidEnum = false;\r
156     mInvalidValue = false;\r
157     mInvalidOperation = false;\r
158     mOutOfMemory = false;\r
159     mInvalidFramebufferOperation = false;\r
160 \r
161     mHasBeenCurrent = false;\r
162 \r
163     markAllStateDirty();\r
164 }\r
165 \r
166 Context::~Context()\r
167 {\r
168     if(mState.currentProgram != 0)\r
169     {\r
170         Program *programObject = mResourceManager->getProgram(mState.currentProgram);\r
171         if(programObject)\r
172         {\r
173             programObject->release();\r
174         }\r
175         mState.currentProgram = 0;\r
176     }\r
177 \r
178     while(!mFramebufferMap.empty())\r
179     {\r
180         deleteFramebuffer(mFramebufferMap.begin()->first);\r
181     }\r
182 \r
183     while(!mFenceMap.empty())\r
184     {\r
185         deleteFence(mFenceMap.begin()->first);\r
186     }\r
187 \r
188         while(!mQueryMap.empty())\r
189     {\r
190         deleteQuery(mQueryMap.begin()->first);\r
191     }\r
192 \r
193     for(int type = 0; type < TEXTURE_TYPE_COUNT; type++)\r
194     {\r
195         for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)\r
196         {\r
197             mState.samplerTexture[type][sampler].set(NULL);\r
198         }\r
199     }\r
200 \r
201     for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)\r
202     {\r
203         mState.vertexAttribute[i].mBoundBuffer.set(NULL);\r
204     }\r
205 \r
206         for(int i = 0; i < QUERY_TYPE_COUNT; i++)\r
207     {\r
208         mState.activeQuery[i].set(NULL);\r
209     }\r
210 \r
211     mState.arrayBuffer.set(NULL);\r
212     mState.elementArrayBuffer.set(NULL);\r
213     mState.renderbuffer.set(NULL);\r
214 \r
215     mTexture2DZero.set(NULL);\r
216     mTextureCubeMapZero.set(NULL);\r
217     mTextureExternalZero.set(NULL);\r
218 \r
219     delete mVertexDataManager;\r
220     delete mIndexDataManager;\r
221 \r
222     mResourceManager->release();\r
223 }\r
224 \r
225 void Context::makeCurrent(egl::Surface *surface)\r
226 {\r
227     if(!mHasBeenCurrent)\r
228     {\r
229         mVertexDataManager = new VertexDataManager(this);\r
230         mIndexDataManager = new IndexDataManager();\r
231 \r
232         mState.viewportX = 0;\r
233         mState.viewportY = 0;\r
234         mState.viewportWidth = surface->getWidth();\r
235         mState.viewportHeight = surface->getHeight();\r
236 \r
237         mState.scissorX = 0;\r
238         mState.scissorY = 0;\r
239         mState.scissorWidth = surface->getWidth();\r
240         mState.scissorHeight = surface->getHeight();\r
241 \r
242         mHasBeenCurrent = true;\r
243     }\r
244 \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
248 \r
249     Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);\r
250     DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);\r
251     Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);\r
252 \r
253     setFramebufferZero(framebufferZero);\r
254 \r
255     if(defaultRenderTarget)\r
256     {\r
257         defaultRenderTarget->release();\r
258     }\r
259 \r
260     if(depthStencil)\r
261     {\r
262         depthStencil->release();\r
263     }\r
264     \r
265     markAllStateDirty();\r
266 }\r
267 \r
268 void Context::destroy()\r
269 {\r
270         delete this;\r
271 }\r
272 \r
273 int Context::getClientVersion()\r
274 {\r
275         return 2;\r
276 }\r
277 \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
280 {\r
281     mAppliedProgramSerial = 0;\r
282 \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
291 }\r
292 \r
293 void Context::setClearColor(float red, float green, float blue, float alpha)\r
294 {\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
299 }\r
300 \r
301 void Context::setClearDepth(float depth)\r
302 {\r
303     mState.depthClearValue = depth;\r
304 }\r
305 \r
306 void Context::setClearStencil(int stencil)\r
307 {\r
308     mState.stencilClearValue = stencil;\r
309 }\r
310 \r
311 void Context::setCullFace(bool enabled)\r
312 {\r
313     mState.cullFace = enabled;\r
314 }\r
315 \r
316 bool Context::isCullFaceEnabled() const\r
317 {\r
318     return mState.cullFace;\r
319 }\r
320 \r
321 void Context::setCullMode(GLenum mode)\r
322 {\r
323    mState.cullMode = mode;\r
324 }\r
325 \r
326 void Context::setFrontFace(GLenum front)\r
327 {\r
328     if(mState.frontFace != front)\r
329     {\r
330         mState.frontFace = front;\r
331         mFrontFaceDirty = true;\r
332     }\r
333 }\r
334 \r
335 void Context::setDepthTest(bool enabled)\r
336 {\r
337     if(mState.depthTest != enabled)\r
338     {\r
339         mState.depthTest = enabled;\r
340         mDepthStateDirty = true;\r
341     }\r
342 }\r
343 \r
344 bool Context::isDepthTestEnabled() const\r
345 {\r
346     return mState.depthTest;\r
347 }\r
348 \r
349 void Context::setDepthFunc(GLenum depthFunc)\r
350 {\r
351     if(mState.depthFunc != depthFunc)\r
352     {\r
353         mState.depthFunc = depthFunc;\r
354         mDepthStateDirty = true;\r
355     }\r
356 }\r
357 \r
358 void Context::setDepthRange(float zNear, float zFar)\r
359 {\r
360     mState.zNear = zNear;\r
361     mState.zFar = zFar;\r
362 }\r
363 \r
364 void Context::setBlend(bool enabled)\r
365 {\r
366     if(mState.blend != enabled)\r
367     {\r
368         mState.blend = enabled;\r
369         mBlendStateDirty = true;\r
370     }\r
371 }\r
372 \r
373 bool Context::isBlendEnabled() const\r
374 {\r
375     return mState.blend;\r
376 }\r
377 \r
378 void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)\r
379 {\r
380     if(mState.sourceBlendRGB != sourceRGB ||\r
381        mState.sourceBlendAlpha != sourceAlpha ||\r
382        mState.destBlendRGB != destRGB ||\r
383        mState.destBlendAlpha != destAlpha)\r
384     {\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
390     }\r
391 }\r
392 \r
393 void Context::setBlendColor(float red, float green, float blue, float alpha)\r
394 {\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
399     {\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
405     }\r
406 }\r
407 \r
408 void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)\r
409 {\r
410     if(mState.blendEquationRGB != rgbEquation ||\r
411        mState.blendEquationAlpha != alphaEquation)\r
412     {\r
413         mState.blendEquationRGB = rgbEquation;\r
414         mState.blendEquationAlpha = alphaEquation;\r
415         mBlendStateDirty = true;\r
416     }\r
417 }\r
418 \r
419 void Context::setStencilTest(bool enabled)\r
420 {\r
421     if(mState.stencilTest != enabled)\r
422     {\r
423         mState.stencilTest = enabled;\r
424         mStencilStateDirty = true;\r
425     }\r
426 }\r
427 \r
428 bool Context::isStencilTestEnabled() const\r
429 {\r
430     return mState.stencilTest;\r
431 }\r
432 \r
433 void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)\r
434 {\r
435     if(mState.stencilFunc != stencilFunc ||\r
436         mState.stencilRef != stencilRef ||\r
437         mState.stencilMask != stencilMask)\r
438     {\r
439         mState.stencilFunc = stencilFunc;\r
440         mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;\r
441         mState.stencilMask = stencilMask;\r
442         mStencilStateDirty = true;\r
443     }\r
444 }\r
445 \r
446 void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)\r
447 {\r
448     if(mState.stencilBackFunc != stencilBackFunc ||\r
449         mState.stencilBackRef != stencilBackRef ||\r
450         mState.stencilBackMask != stencilBackMask)\r
451     {\r
452         mState.stencilBackFunc = stencilBackFunc;\r
453         mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;\r
454         mState.stencilBackMask = stencilBackMask;\r
455         mStencilStateDirty = true;\r
456     }\r
457 }\r
458 \r
459 void Context::setStencilWritemask(GLuint stencilWritemask)\r
460 {\r
461     if(mState.stencilWritemask != stencilWritemask)\r
462     {\r
463         mState.stencilWritemask = stencilWritemask;\r
464         mStencilStateDirty = true;\r
465     }\r
466 }\r
467 \r
468 void Context::setStencilBackWritemask(GLuint stencilBackWritemask)\r
469 {\r
470     if(mState.stencilBackWritemask != stencilBackWritemask)\r
471     {\r
472         mState.stencilBackWritemask = stencilBackWritemask;\r
473         mStencilStateDirty = true;\r
474     }\r
475 }\r
476 \r
477 void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)\r
478 {\r
479     if(mState.stencilFail != stencilFail ||\r
480         mState.stencilPassDepthFail != stencilPassDepthFail ||\r
481         mState.stencilPassDepthPass != stencilPassDepthPass)\r
482     {\r
483         mState.stencilFail = stencilFail;\r
484         mState.stencilPassDepthFail = stencilPassDepthFail;\r
485         mState.stencilPassDepthPass = stencilPassDepthPass;\r
486         mStencilStateDirty = true;\r
487     }\r
488 }\r
489 \r
490 void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)\r
491 {\r
492     if(mState.stencilBackFail != stencilBackFail ||\r
493         mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||\r
494         mState.stencilBackPassDepthPass != stencilBackPassDepthPass)\r
495     {\r
496         mState.stencilBackFail = stencilBackFail;\r
497         mState.stencilBackPassDepthFail = stencilBackPassDepthFail;\r
498         mState.stencilBackPassDepthPass = stencilBackPassDepthPass;\r
499         mStencilStateDirty = true;\r
500     }\r
501 }\r
502 \r
503 void Context::setPolygonOffsetFill(bool enabled)\r
504 {\r
505     if(mState.polygonOffsetFill != enabled)\r
506     {\r
507         mState.polygonOffsetFill = enabled;\r
508         mPolygonOffsetStateDirty = true;\r
509     }\r
510 }\r
511 \r
512 bool Context::isPolygonOffsetFillEnabled() const\r
513 {\r
514     return mState.polygonOffsetFill;\r
515 }\r
516 \r
517 void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)\r
518 {\r
519     if(mState.polygonOffsetFactor != factor ||\r
520         mState.polygonOffsetUnits != units)\r
521     {\r
522         mState.polygonOffsetFactor = factor;\r
523         mState.polygonOffsetUnits = units;\r
524         mPolygonOffsetStateDirty = true;\r
525     }\r
526 }\r
527 \r
528 void Context::setSampleAlphaToCoverage(bool enabled)\r
529 {\r
530     if(mState.sampleAlphaToCoverage != enabled)\r
531     {\r
532         mState.sampleAlphaToCoverage = enabled;\r
533         mSampleStateDirty = true;\r
534     }\r
535 }\r
536 \r
537 bool Context::isSampleAlphaToCoverageEnabled() const\r
538 {\r
539     return mState.sampleAlphaToCoverage;\r
540 }\r
541 \r
542 void Context::setSampleCoverage(bool enabled)\r
543 {\r
544     if(mState.sampleCoverage != enabled)\r
545     {\r
546         mState.sampleCoverage = enabled;\r
547         mSampleStateDirty = true;\r
548     }\r
549 }\r
550 \r
551 bool Context::isSampleCoverageEnabled() const\r
552 {\r
553     return mState.sampleCoverage;\r
554 }\r
555 \r
556 void Context::setSampleCoverageParams(GLclampf value, bool invert)\r
557 {\r
558     if(mState.sampleCoverageValue != value ||\r
559         mState.sampleCoverageInvert != invert)\r
560     {\r
561         mState.sampleCoverageValue = value;\r
562         mState.sampleCoverageInvert = invert;\r
563         mSampleStateDirty = true;\r
564     }\r
565 }\r
566 \r
567 void Context::setScissorTest(bool enabled)\r
568 {\r
569     mState.scissorTest = enabled;\r
570 }\r
571 \r
572 bool Context::isScissorTestEnabled() const\r
573 {\r
574     return mState.scissorTest;\r
575 }\r
576 \r
577 void Context::setDither(bool enabled)\r
578 {\r
579     if(mState.dither != enabled)\r
580     {\r
581         mState.dither = enabled;\r
582         mDitherStateDirty = true;\r
583     }\r
584 }\r
585 \r
586 bool Context::isDitherEnabled() const\r
587 {\r
588     return mState.dither;\r
589 }\r
590 \r
591 void Context::setLineWidth(GLfloat width)\r
592 {\r
593     mState.lineWidth = width;\r
594 }\r
595 \r
596 void Context::setGenerateMipmapHint(GLenum hint)\r
597 {\r
598     mState.generateMipmapHint = hint;\r
599 }\r
600 \r
601 void Context::setFragmentShaderDerivativeHint(GLenum hint)\r
602 {\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
607 }\r
608 \r
609 void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)\r
610 {\r
611     mState.viewportX = x;\r
612     mState.viewportY = y;\r
613     mState.viewportWidth = width;\r
614     mState.viewportHeight = height;\r
615 }\r
616 \r
617 void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)\r
618 {\r
619     mState.scissorX = x;\r
620     mState.scissorY = y;\r
621     mState.scissorWidth = width;\r
622     mState.scissorHeight = height;\r
623 }\r
624 \r
625 void Context::setColorMask(bool red, bool green, bool blue, bool alpha)\r
626 {\r
627     if(mState.colorMaskRed != red || mState.colorMaskGreen != green ||\r
628        mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)\r
629     {\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
635     }\r
636 }\r
637 \r
638 void Context::setDepthMask(bool mask)\r
639 {\r
640     if(mState.depthMask != mask)\r
641     {\r
642         mState.depthMask = mask;\r
643         mMaskStateDirty = true;\r
644     }\r
645 }\r
646 \r
647 void Context::setActiveSampler(unsigned int active)\r
648 {\r
649     mState.activeSampler = active;\r
650 }\r
651 \r
652 GLuint Context::getReadFramebufferHandle() const\r
653 {\r
654     return mState.readFramebuffer;\r
655 }\r
656 \r
657 GLuint Context::getDrawFramebufferHandle() const\r
658 {\r
659     return mState.drawFramebuffer;\r
660 }\r
661 \r
662 GLuint Context::getRenderbufferHandle() const\r
663 {\r
664     return mState.renderbuffer.id();\r
665 }\r
666 \r
667 GLuint Context::getArrayBufferHandle() const\r
668 {\r
669     return mState.arrayBuffer.id();\r
670 }\r
671 \r
672 GLuint Context::getActiveQuery(GLenum target) const\r
673 {\r
674     Query *queryObject = NULL;\r
675     \r
676     switch(target)\r
677     {\r
678     case GL_ANY_SAMPLES_PASSED_EXT:\r
679         queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();\r
680         break;\r
681     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:\r
682         queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();\r
683         break;\r
684     default:\r
685         ASSERT(false);\r
686     }\r
687 \r
688     if(queryObject)\r
689     {\r
690         return queryObject->id();\r
691     }\r
692     \r
693         return 0;\r
694 }\r
695 \r
696 void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)\r
697 {\r
698     mState.vertexAttribute[attribNum].mArrayEnabled = enabled;\r
699 }\r
700 \r
701 const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)\r
702 {\r
703     return mState.vertexAttribute[attribNum];\r
704 }\r
705 \r
706 void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,\r
707                                    GLsizei stride, const void *pointer)\r
708 {\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
715 }\r
716 \r
717 const void *Context::getVertexAttribPointer(unsigned int attribNum) const\r
718 {\r
719     return mState.vertexAttribute[attribNum].mPointer;\r
720 }\r
721 \r
722 const VertexAttributeArray &Context::getVertexAttributes()\r
723 {\r
724     return mState.vertexAttribute;\r
725 }\r
726 \r
727 void Context::setPackAlignment(GLint alignment)\r
728 {\r
729     mState.packAlignment = alignment;\r
730 }\r
731 \r
732 GLint Context::getPackAlignment() const\r
733 {\r
734     return mState.packAlignment;\r
735 }\r
736 \r
737 void Context::setUnpackAlignment(GLint alignment)\r
738 {\r
739     mState.unpackAlignment = alignment;\r
740 }\r
741 \r
742 GLint Context::getUnpackAlignment() const\r
743 {\r
744     return mState.unpackAlignment;\r
745 }\r
746 \r
747 GLuint Context::createBuffer()\r
748 {\r
749     return mResourceManager->createBuffer();\r
750 }\r
751 \r
752 GLuint Context::createProgram()\r
753 {\r
754     return mResourceManager->createProgram();\r
755 }\r
756 \r
757 GLuint Context::createShader(GLenum type)\r
758 {\r
759     return mResourceManager->createShader(type);\r
760 }\r
761 \r
762 GLuint Context::createTexture()\r
763 {\r
764     return mResourceManager->createTexture();\r
765 }\r
766 \r
767 GLuint Context::createRenderbuffer()\r
768 {\r
769     return mResourceManager->createRenderbuffer();\r
770 }\r
771 \r
772 // Returns an unused framebuffer name\r
773 GLuint Context::createFramebuffer()\r
774 {\r
775     GLuint handle = mFramebufferHandleAllocator.allocate();\r
776 \r
777     mFramebufferMap[handle] = NULL;\r
778 \r
779     return handle;\r
780 }\r
781 \r
782 GLuint Context::createFence()\r
783 {\r
784     GLuint handle = mFenceHandleAllocator.allocate();\r
785 \r
786     mFenceMap[handle] = new Fence;\r
787 \r
788     return handle;\r
789 }\r
790 \r
791 // Returns an unused query name\r
792 GLuint Context::createQuery()\r
793 {\r
794     GLuint handle = mQueryHandleAllocator.allocate();\r
795 \r
796     mQueryMap[handle] = NULL;\r
797 \r
798     return handle;\r
799 }\r
800 \r
801 void Context::deleteBuffer(GLuint buffer)\r
802 {\r
803     if(mResourceManager->getBuffer(buffer))\r
804     {\r
805         detachBuffer(buffer);\r
806     }\r
807     \r
808     mResourceManager->deleteBuffer(buffer);\r
809 }\r
810 \r
811 void Context::deleteShader(GLuint shader)\r
812 {\r
813     mResourceManager->deleteShader(shader);\r
814 }\r
815 \r
816 void Context::deleteProgram(GLuint program)\r
817 {\r
818     mResourceManager->deleteProgram(program);\r
819 }\r
820 \r
821 void Context::deleteTexture(GLuint texture)\r
822 {\r
823     if(mResourceManager->getTexture(texture))\r
824     {\r
825         detachTexture(texture);\r
826     }\r
827 \r
828     mResourceManager->deleteTexture(texture);\r
829 }\r
830 \r
831 void Context::deleteRenderbuffer(GLuint renderbuffer)\r
832 {\r
833     if(mResourceManager->getRenderbuffer(renderbuffer))\r
834     {\r
835         detachRenderbuffer(renderbuffer);\r
836     }\r
837     \r
838     mResourceManager->deleteRenderbuffer(renderbuffer);\r
839 }\r
840 \r
841 void Context::deleteFramebuffer(GLuint framebuffer)\r
842 {\r
843     FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);\r
844 \r
845     if(framebufferObject != mFramebufferMap.end())\r
846     {\r
847         detachFramebuffer(framebuffer);\r
848 \r
849         mFramebufferHandleAllocator.release(framebufferObject->first);\r
850         delete framebufferObject->second;\r
851         mFramebufferMap.erase(framebufferObject);\r
852     }\r
853 }\r
854 \r
855 void Context::deleteFence(GLuint fence)\r
856 {\r
857     FenceMap::iterator fenceObject = mFenceMap.find(fence);\r
858 \r
859     if(fenceObject != mFenceMap.end())\r
860     {\r
861         mFenceHandleAllocator.release(fenceObject->first);\r
862         delete fenceObject->second;\r
863         mFenceMap.erase(fenceObject);\r
864     }\r
865 }\r
866 \r
867 void Context::deleteQuery(GLuint query)\r
868 {\r
869     QueryMap::iterator queryObject = mQueryMap.find(query);\r
870     \r
871         if(queryObject != mQueryMap.end())\r
872     {\r
873         mQueryHandleAllocator.release(queryObject->first);\r
874         \r
875                 if(queryObject->second)\r
876         {\r
877             queryObject->second->release();\r
878         }\r
879         \r
880                 mQueryMap.erase(queryObject);\r
881     }\r
882 }\r
883 \r
884 Buffer *Context::getBuffer(GLuint handle)\r
885 {\r
886     return mResourceManager->getBuffer(handle);\r
887 }\r
888 \r
889 Shader *Context::getShader(GLuint handle)\r
890 {\r
891     return mResourceManager->getShader(handle);\r
892 }\r
893 \r
894 Program *Context::getProgram(GLuint handle)\r
895 {\r
896     return mResourceManager->getProgram(handle);\r
897 }\r
898 \r
899 Texture *Context::getTexture(GLuint handle)\r
900 {\r
901     return mResourceManager->getTexture(handle);\r
902 }\r
903 \r
904 Renderbuffer *Context::getRenderbuffer(GLuint handle)\r
905 {\r
906     return mResourceManager->getRenderbuffer(handle);\r
907 }\r
908 \r
909 Framebuffer *Context::getReadFramebuffer()\r
910 {\r
911     return getFramebuffer(mState.readFramebuffer);\r
912 }\r
913 \r
914 Framebuffer *Context::getDrawFramebuffer()\r
915 {\r
916     return getFramebuffer(mState.drawFramebuffer);\r
917 }\r
918 \r
919 void Context::bindArrayBuffer(unsigned int buffer)\r
920 {\r
921     mResourceManager->checkBufferAllocation(buffer);\r
922 \r
923     mState.arrayBuffer.set(getBuffer(buffer));\r
924 }\r
925 \r
926 void Context::bindElementArrayBuffer(unsigned int buffer)\r
927 {\r
928     mResourceManager->checkBufferAllocation(buffer);\r
929 \r
930     mState.elementArrayBuffer.set(getBuffer(buffer));\r
931 }\r
932 \r
933 void Context::bindTexture2D(GLuint texture)\r
934 {\r
935     mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);\r
936 \r
937     mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));\r
938 }\r
939 \r
940 void Context::bindTextureCubeMap(GLuint texture)\r
941 {\r
942     mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);\r
943 \r
944     mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));\r
945 }\r
946 \r
947 void Context::bindTextureExternal(GLuint texture)\r
948 {\r
949     mResourceManager->checkTextureAllocation(texture, TEXTURE_EXTERNAL);\r
950 \r
951     mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler].set(getTexture(texture));\r
952 }\r
953 \r
954 void Context::bindReadFramebuffer(GLuint framebuffer)\r
955 {\r
956     if(!getFramebuffer(framebuffer))\r
957     {\r
958         mFramebufferMap[framebuffer] = new Framebuffer();\r
959     }\r
960 \r
961     mState.readFramebuffer = framebuffer;\r
962 }\r
963 \r
964 void Context::bindDrawFramebuffer(GLuint framebuffer)\r
965 {\r
966     if(!getFramebuffer(framebuffer))\r
967     {\r
968         mFramebufferMap[framebuffer] = new Framebuffer();\r
969     }\r
970 \r
971     mState.drawFramebuffer = framebuffer;\r
972 }\r
973 \r
974 void Context::bindRenderbuffer(GLuint renderbuffer)\r
975 {\r
976     mState.renderbuffer.set(getRenderbuffer(renderbuffer));\r
977 }\r
978 \r
979 void Context::useProgram(GLuint program)\r
980 {\r
981     GLuint priorProgram = mState.currentProgram;\r
982     mState.currentProgram = program;               // Must switch before trying to delete, otherwise it only gets flagged.\r
983 \r
984     if(priorProgram != program)\r
985     {\r
986         Program *newProgram = mResourceManager->getProgram(program);\r
987         Program *oldProgram = mResourceManager->getProgram(priorProgram);\r
988 \r
989         if(newProgram)\r
990         {\r
991             newProgram->addRef();\r
992         }\r
993         \r
994         if(oldProgram)\r
995         {\r
996             oldProgram->release();\r
997         }\r
998     }\r
999 }\r
1000 \r
1001 void Context::beginQuery(GLenum target, GLuint query)\r
1002 {\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
1009     // generated.\r
1010 \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
1019     {\r
1020         if(mState.activeQuery[i].get() != NULL)\r
1021         {\r
1022             return error(GL_INVALID_OPERATION);\r
1023         }\r
1024     }\r
1025 \r
1026     QueryType qType;\r
1027     switch(target)\r
1028     {\r
1029     case GL_ANY_SAMPLES_PASSED_EXT: \r
1030         qType = QUERY_ANY_SAMPLES_PASSED; \r
1031         break;\r
1032     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: \r
1033         qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; \r
1034         break;\r
1035     default: \r
1036         ASSERT(false);\r
1037     }\r
1038 \r
1039     Query *queryObject = getQuery(query, true, target);\r
1040 \r
1041     // Check that name was obtained with glGenQueries\r
1042     if(!queryObject)\r
1043     {\r
1044         return error(GL_INVALID_OPERATION);\r
1045     }\r
1046 \r
1047     // Check for type mismatch\r
1048     if(queryObject->getType() != target)\r
1049     {\r
1050         return error(GL_INVALID_OPERATION);\r
1051     }\r
1052 \r
1053     // Set query as active for specified target\r
1054     mState.activeQuery[qType].set(queryObject);\r
1055 \r
1056     // Begin query\r
1057     queryObject->begin();\r
1058 }\r
1059 \r
1060 void Context::endQuery(GLenum target)\r
1061 {\r
1062     QueryType qType;\r
1063 \r
1064     switch(target)\r
1065     {\r
1066     case GL_ANY_SAMPLES_PASSED_EXT: \r
1067         qType = QUERY_ANY_SAMPLES_PASSED; \r
1068         break;\r
1069     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: \r
1070         qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; \r
1071         break;\r
1072     default: \r
1073         ASSERT(false);\r
1074     }\r
1075 \r
1076     Query *queryObject = mState.activeQuery[qType].get();\r
1077 \r
1078     if(queryObject == NULL)\r
1079     {\r
1080         return error(GL_INVALID_OPERATION);\r
1081     }\r
1082 \r
1083     queryObject->end();\r
1084 \r
1085     mState.activeQuery[qType].set(NULL);\r
1086 }\r
1087 \r
1088 void Context::setFramebufferZero(Framebuffer *buffer)\r
1089 {\r
1090     delete mFramebufferMap[0];\r
1091     mFramebufferMap[0] = buffer;\r
1092 }\r
1093 \r
1094 void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)\r
1095 {\r
1096     Renderbuffer *renderbufferObject = mState.renderbuffer.get();\r
1097     renderbufferObject->setStorage(renderbuffer);\r
1098 }\r
1099 \r
1100 Framebuffer *Context::getFramebuffer(unsigned int handle)\r
1101 {\r
1102     FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);\r
1103 \r
1104     if(framebuffer == mFramebufferMap.end())\r
1105     {\r
1106         return NULL;\r
1107     }\r
1108     else\r
1109     {\r
1110         return framebuffer->second;\r
1111     }\r
1112 }\r
1113 \r
1114 Fence *Context::getFence(unsigned int handle)\r
1115 {\r
1116     FenceMap::iterator fence = mFenceMap.find(handle);\r
1117 \r
1118     if(fence == mFenceMap.end())\r
1119     {\r
1120         return NULL;\r
1121     }\r
1122     else\r
1123     {\r
1124         return fence->second;\r
1125     }\r
1126 }\r
1127 \r
1128 Query *Context::getQuery(unsigned int handle, bool create, GLenum type)\r
1129 {\r
1130     QueryMap::iterator query = mQueryMap.find(handle);\r
1131 \r
1132     if(query == mQueryMap.end())\r
1133     {\r
1134         return NULL;\r
1135     }\r
1136     else\r
1137     {\r
1138         if(!query->second && create)\r
1139         {\r
1140             query->second = new Query(handle, type);\r
1141             query->second->addRef();\r
1142         }\r
1143 \r
1144         return query->second;\r
1145     }\r
1146 }\r
1147 \r
1148 Buffer *Context::getArrayBuffer()\r
1149 {\r
1150     return mState.arrayBuffer.get();\r
1151 }\r
1152 \r
1153 Buffer *Context::getElementArrayBuffer()\r
1154 {\r
1155     return mState.elementArrayBuffer.get();\r
1156 }\r
1157 \r
1158 Program *Context::getCurrentProgram()\r
1159 {\r
1160         return mState.program;\r
1161     //return mResourceManager->getProgram(mState.currentProgram);\r
1162 }\r
1163 \r
1164 Texture2D *Context::getTexture2D()\r
1165 {\r
1166     return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));\r
1167 }\r
1168 \r
1169 TextureCubeMap *Context::getTextureCubeMap()\r
1170 {\r
1171     return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));\r
1172 }\r
1173 \r
1174 TextureExternal *Context::getTextureExternal()\r
1175 {\r
1176     return static_cast<TextureExternal*>(getSamplerTexture(mState.activeSampler, TEXTURE_EXTERNAL));\r
1177 }\r
1178 \r
1179 Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)\r
1180 {\r
1181     GLuint texid = mState.samplerTexture[type][sampler].id();\r
1182 \r
1183     if(texid == 0)   // Special case: 0 refers to different initial textures based on the target\r
1184     {\r
1185         switch (type)\r
1186         {\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
1191         }\r
1192     }\r
1193 \r
1194     return mState.samplerTexture[type][sampler].get();\r
1195 }\r
1196 \r
1197 bool Context::getBooleanv(GLenum pname, GLboolean *params)\r
1198 {\r
1199     switch (pname)\r
1200     {\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
1209         break;\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
1219       default:\r
1220         return false;\r
1221     }\r
1222 \r
1223     return true;\r
1224 }\r
1225 \r
1226 bool Context::getFloatv(GLenum pname, GLfloat *params)\r
1227 {\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
1232     switch (pname)\r
1233     {\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
1242         break;\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
1246         break;\r
1247       case GL_DEPTH_RANGE:\r
1248         params[0] = mState.zNear;\r
1249         params[1] = mState.zFar;\r
1250         break;\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
1256         break;\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
1262         break;\r
1263           case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:\r
1264         *params = MAX_TEXTURE_MAX_ANISOTROPY;\r
1265                 break;\r
1266       default:\r
1267         return false;\r
1268     }\r
1269 \r
1270     return true;\r
1271 }\r
1272 \r
1273 bool Context::getIntegerv(GLenum pname, GLint *params)\r
1274 {\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
1280     switch (pname)\r
1281     {\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
1330         {\r
1331             if(S3TC_SUPPORT)\r
1332             {\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
1337                 *params = 4;\r
1338             }\r
1339             else\r
1340             {\r
1341                 *params = 0;\r
1342             }\r
1343         }\r
1344         break;\r
1345         case GL_MAX_SAMPLES_ANGLE:                *params = IMPLEMENTATION_MAX_SAMPLES; break;\r
1346     case GL_SAMPLE_BUFFERS:                   \r
1347     case GL_SAMPLES:\r
1348         {\r
1349             Framebuffer *framebuffer = getDrawFramebuffer();\r
1350                         int width, height, samples;\r
1351 \r
1352             if(framebuffer->completeness(width, height, samples) == GL_FRAMEBUFFER_COMPLETE)\r
1353             {\r
1354                 switch(pname)\r
1355                 {\r
1356                 case GL_SAMPLE_BUFFERS:\r
1357                     if(samples > 1)\r
1358                     {\r
1359                         *params = 1;\r
1360                     }\r
1361                     else\r
1362                     {\r
1363                         *params = 0;\r
1364                     }\r
1365                     break;\r
1366                 case GL_SAMPLES:\r
1367                     *params = samples & ~1;\r
1368                     break;\r
1369                 }\r
1370             }\r
1371             else\r
1372             {\r
1373                 *params = 0;\r
1374             }\r
1375         }\r
1376         break;\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
1380         {\r
1381                         int maxDimension = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE;\r
1382             params[0] = maxDimension;\r
1383             params[1] = maxDimension;\r
1384         }\r
1385         break;\r
1386     case GL_COMPRESSED_TEXTURE_FORMATS:\r
1387         {\r
1388             if(S3TC_SUPPORT)\r
1389             {\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
1394             }\r
1395         }\r
1396         break;\r
1397     case GL_VIEWPORT:\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
1402         break;\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
1408         break;\r
1409     case GL_CULL_FACE_MODE:                   *params = mState.cullMode;                 break;\r
1410     case GL_FRONT_FACE:                       *params = mState.frontFace;                break;\r
1411     case GL_RED_BITS:\r
1412     case GL_GREEN_BITS:\r
1413     case GL_BLUE_BITS:\r
1414     case GL_ALPHA_BITS:\r
1415         {\r
1416             Framebuffer *framebuffer = getDrawFramebuffer();\r
1417             Renderbuffer *colorbuffer = framebuffer->getColorbuffer();\r
1418 \r
1419             if(colorbuffer)\r
1420             {\r
1421                 switch (pname)\r
1422                 {\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
1427                 }\r
1428             }\r
1429             else\r
1430             {\r
1431                 *params = 0;\r
1432             }\r
1433         }\r
1434         break;\r
1435     case GL_DEPTH_BITS:\r
1436         {\r
1437             Framebuffer *framebuffer = getDrawFramebuffer();\r
1438             Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();\r
1439 \r
1440             if(depthbuffer)\r
1441             {\r
1442                 *params = depthbuffer->getDepthSize();\r
1443             }\r
1444             else\r
1445             {\r
1446                 *params = 0;\r
1447             }\r
1448         }\r
1449         break;\r
1450     case GL_STENCIL_BITS:\r
1451         {\r
1452             Framebuffer *framebuffer = getDrawFramebuffer();\r
1453             Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();\r
1454 \r
1455             if(stencilbuffer)\r
1456             {\r
1457                 *params = stencilbuffer->getStencilSize();\r
1458             }\r
1459             else\r
1460             {\r
1461                 *params = 0;\r
1462             }\r
1463         }\r
1464         break;\r
1465     case GL_TEXTURE_BINDING_2D:\r
1466         {\r
1467             if(mState.activeSampler < 0 || mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)\r
1468             {\r
1469                 error(GL_INVALID_OPERATION);\r
1470                 return false;\r
1471             }\r
1472 \r
1473             *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();\r
1474         }\r
1475         break;\r
1476     case GL_TEXTURE_BINDING_CUBE_MAP:\r
1477         {\r
1478             if(mState.activeSampler < 0 || mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)\r
1479             {\r
1480                 error(GL_INVALID_OPERATION);\r
1481                 return false;\r
1482             }\r
1483 \r
1484             *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();\r
1485         }\r
1486         break;\r
1487     case GL_TEXTURE_BINDING_EXTERNAL_OES:\r
1488         {\r
1489             if(mState.activeSampler < 0 || mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)\r
1490             {\r
1491                 error(GL_INVALID_OPERATION);\r
1492                 return false;\r
1493             }\r
1494 \r
1495             *params = mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler].id();\r
1496         }\r
1497         break;\r
1498     default:\r
1499         return false;\r
1500     }\r
1501 \r
1502     return true;\r
1503 }\r
1504 \r
1505 bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)\r
1506 {\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
1513     // application.\r
1514     switch (pname)\r
1515     {\r
1516       case GL_COMPRESSED_TEXTURE_FORMATS:\r
1517                 {\r
1518             *type = GL_INT;\r
1519             *numParams = S3TC_SUPPORT ? 4 : 0;\r
1520         }\r
1521                 break;\r
1522       case GL_SHADER_BINARY_FORMATS:\r
1523         {\r
1524             *type = GL_INT;\r
1525             *numParams = 0;\r
1526         }\r
1527         break;\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
1546       case GL_RED_BITS:\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
1582       case GL_SAMPLES:\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
1588         {\r
1589             *type = GL_INT;\r
1590             *numParams = 1;\r
1591         }\r
1592         break;\r
1593       case GL_MAX_SAMPLES_ANGLE:\r
1594         {\r
1595             *type = GL_INT;\r
1596             *numParams = 1;\r
1597         }\r
1598         break;\r
1599       case GL_MAX_VIEWPORT_DIMS:\r
1600         {\r
1601             *type = GL_INT;\r
1602             *numParams = 2;\r
1603         }\r
1604         break;\r
1605       case GL_VIEWPORT:\r
1606       case GL_SCISSOR_BOX:\r
1607         {\r
1608             *type = GL_INT;\r
1609             *numParams = 4;\r
1610         }\r
1611         break;\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
1622       case GL_BLEND:\r
1623       case GL_DITHER:\r
1624         {\r
1625             *type = GL_BOOL;\r
1626             *numParams = 1;\r
1627         }\r
1628         break;\r
1629       case GL_COLOR_WRITEMASK:\r
1630         {\r
1631             *type = GL_BOOL;\r
1632             *numParams = 4;\r
1633         }\r
1634         break;\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
1640         {\r
1641             *type = GL_FLOAT;\r
1642             *numParams = 1;\r
1643         }\r
1644         break;\r
1645       case GL_ALIASED_LINE_WIDTH_RANGE:\r
1646       case GL_ALIASED_POINT_SIZE_RANGE:\r
1647       case GL_DEPTH_RANGE:\r
1648         {\r
1649             *type = GL_FLOAT;\r
1650             *numParams = 2;\r
1651         }\r
1652         break;\r
1653       case GL_COLOR_CLEAR_VALUE:\r
1654       case GL_BLEND_COLOR:\r
1655         {\r
1656             *type = GL_FLOAT;\r
1657             *numParams = 4;\r
1658         }\r
1659         break;\r
1660           case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:\r
1661         *type = GL_FLOAT;\r
1662         *numParams = 1;\r
1663         break;\r
1664       default:\r
1665         return false;\r
1666     }\r
1667 \r
1668     return true;\r
1669 }\r
1670 \r
1671 // Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle\r
1672 bool Context::applyRenderTarget()\r
1673 {\r
1674     Framebuffer *framebuffer = getDrawFramebuffer();\r
1675         int width, height, samples;\r
1676 \r
1677     if(!framebuffer || framebuffer->completeness(width, height, samples) != GL_FRAMEBUFFER_COMPLETE)\r
1678     {\r
1679         return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);\r
1680     }\r
1681 \r
1682     egl::Image *renderTarget = mState.colorBuffer;//framebuffer->getRenderTarget();\r
1683         device->setRenderTarget(renderTarget);\r
1684         //if(renderTarget) renderTarget->release();\r
1685 \r
1686     egl::Image *depthStencil = mState.depthBuffer;//framebuffer->getDepthStencil();\r
1687     device->setDepthStencilSurface(depthStencil);\r
1688         //if(depthStencil) depthStencil->release();\r
1689 \r
1690     Viewport viewport;\r
1691     float zNear = clamp01(mState.zNear);\r
1692     float zFar = clamp01(mState.zFar);\r
1693 \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
1700 \r
1701     device->setViewport(viewport);\r
1702 \r
1703     if(mState.scissorTest)\r
1704     {\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
1707         \r
1708                 device->setScissorRect(scissor);\r
1709         device->setScissorEnable(true);\r
1710     }\r
1711     else\r
1712     {\r
1713         device->setScissorEnable(false);\r
1714     }\r
1715 \r
1716         Program *program = getCurrentProgram();\r
1717 \r
1718         if(program)\r
1719         {\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
1724     }\r
1725 \r
1726     return true;\r
1727 }\r
1728 \r
1729 // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc)\r
1730 void Context::applyState(GLenum drawMode)\r
1731 {\r
1732     Framebuffer *framebuffer = getDrawFramebuffer();\r
1733 \r
1734     if(mState.cullFace)\r
1735     {\r
1736         device->setCullMode(rad2sw::ConvertCullMode(mState.cullMode, mState.frontFace));\r
1737     }\r
1738     else\r
1739     {\r
1740                 device->setCullMode(sw::CULL_NONE);\r
1741     }\r
1742 \r
1743     if(mDepthStateDirty)\r
1744     {\r
1745         if(mState.depthTest)\r
1746         {\r
1747                         device->setDepthBufferEnable(true);\r
1748                         device->setDepthCompare(rad2sw::ConvertDepthComparison(mState.depthFunc));\r
1749         }\r
1750         else\r
1751         {\r
1752             device->setDepthBufferEnable(false);\r
1753         }\r
1754 \r
1755         mDepthStateDirty = false;\r
1756     }\r
1757 \r
1758     if(mBlendStateDirty)\r
1759     {\r
1760         if(mState.blend)\r
1761         {\r
1762                         device->setAlphaBlendEnable(true);\r
1763                         device->setSeparateAlphaBlendEnable(true);\r
1764 \r
1765             device->setBlendConstant(rad2sw::ConvertColor(mState.blendColor));\r
1766 \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
1770 \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
1774         }\r
1775         else\r
1776         {\r
1777                         device->setAlphaBlendEnable(false);\r
1778         }\r
1779 \r
1780         mBlendStateDirty = false;\r
1781     }\r
1782 \r
1783     if(mStencilStateDirty || mFrontFaceDirty)\r
1784     {\r
1785         if(mState.stencilTest && framebuffer->hasStencil())\r
1786         {\r
1787                         device->setStencilEnable(true);\r
1788                         device->setTwoSidedStencil(true);\r
1789 \r
1790             if(mState.stencilWritemask != mState.stencilBackWritemask || \r
1791                mState.stencilRef != mState.stencilBackRef || \r
1792                mState.stencilMask != mState.stencilBackMask)\r
1793             {\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
1796             }\r
1797 \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
1801 \r
1802                         if(mState.frontFace == GL_CCW)\r
1803                         {\r
1804                                 device->setStencilWriteMask(mState.stencilWritemask);\r
1805                                 device->setStencilCompare(rad2sw::ConvertStencilComparison(mState.stencilFunc));\r
1806 \r
1807                                 device->setStencilReference((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);\r
1808                                 device->setStencilMask(mState.stencilMask);\r
1809 \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
1813 \r
1814                                 device->setStencilWriteMaskCCW(mState.stencilBackWritemask);\r
1815                                 device->setStencilCompareCCW(rad2sw::ConvertStencilComparison(mState.stencilBackFunc));\r
1816 \r
1817                                 device->setStencilReferenceCCW((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);\r
1818                                 device->setStencilMaskCCW(mState.stencilBackMask);\r
1819 \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
1823                         }\r
1824                         else\r
1825                         {\r
1826                                 device->setStencilWriteMaskCCW(mState.stencilWritemask);\r
1827                                 device->setStencilCompareCCW(rad2sw::ConvertStencilComparison(mState.stencilFunc));\r
1828 \r
1829                                 device->setStencilReferenceCCW((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);\r
1830                                 device->setStencilMaskCCW(mState.stencilMask);\r
1831 \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
1835 \r
1836                                 device->setStencilWriteMask(mState.stencilBackWritemask);\r
1837                                 device->setStencilCompare(rad2sw::ConvertStencilComparison(mState.stencilBackFunc));\r
1838 \r
1839                                 device->setStencilReference((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);\r
1840                                 device->setStencilMask(mState.stencilBackMask);\r
1841 \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
1845                         }\r
1846         }\r
1847         else\r
1848         {\r
1849                         device->setStencilEnable(false);\r
1850         }\r
1851 \r
1852         mStencilStateDirty = false;\r
1853         mFrontFaceDirty = false;\r
1854     }\r
1855 \r
1856     if(mMaskStateDirty)\r
1857     {\r
1858                 device->setColorWriteMask(0, rad2sw::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha));\r
1859                 device->setDepthWriteEnable(mState.depthMask);\r
1860 \r
1861         mMaskStateDirty = false;\r
1862     }\r
1863 \r
1864     if(mPolygonOffsetStateDirty)\r
1865     {\r
1866         if(mState.polygonOffsetFill)\r
1867         {\r
1868             Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();\r
1869             if(depthbuffer)\r
1870             {\r
1871                                 device->setSlopeDepthBias(mState.polygonOffsetFactor);\r
1872                 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));\r
1873                                 device->setDepthBias(depthBias);\r
1874             }\r
1875         }\r
1876         else\r
1877         {\r
1878             device->setSlopeDepthBias(0);\r
1879             device->setDepthBias(0);\r
1880         }\r
1881 \r
1882         mPolygonOffsetStateDirty = false;\r
1883     }\r
1884 \r
1885     if(mSampleStateDirty)\r
1886     {\r
1887         if(mState.sampleAlphaToCoverage)\r
1888         {\r
1889             device->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE);\r
1890         }\r
1891                 else\r
1892                 {\r
1893                         device->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE);\r
1894                 }\r
1895 \r
1896         if(mState.sampleCoverage)\r
1897         {\r
1898             unsigned int mask = 0;\r
1899             if(mState.sampleCoverageValue != 0)\r
1900             {\r
1901                                 int width, height, samples;\r
1902                                 framebuffer->completeness(width, height, samples);\r
1903 \r
1904                 float threshold = 0.5f;\r
1905 \r
1906                 for(int i = 0; i < samples; i++)\r
1907                 {\r
1908                     mask <<= 1;\r
1909 \r
1910                     if((i + 1) * mState.sampleCoverageValue >= threshold)\r
1911                     {\r
1912                         threshold += 1.0f;\r
1913                         mask |= 1;\r
1914                     }\r
1915                 }\r
1916             }\r
1917             \r
1918             if(mState.sampleCoverageInvert)\r
1919             {\r
1920                 mask = ~mask;\r
1921             }\r
1922 \r
1923                         device->setMultiSampleMask(mask);\r
1924         }\r
1925         else\r
1926         {\r
1927                         device->setMultiSampleMask(0xFFFFFFFF);\r
1928         }\r
1929 \r
1930         mSampleStateDirty = false;\r
1931     }\r
1932 \r
1933     if(mDitherStateDirty)\r
1934     {\r
1935     //  UNIMPLEMENTED();   // FIXME\r
1936 \r
1937         mDitherStateDirty = false;\r
1938     }\r
1939 }\r
1940 \r
1941 GLenum Context::applyVertexBuffer(GLint base, GLint first, GLsizei count)\r
1942 {\r
1943     TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];\r
1944 \r
1945     GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes);\r
1946     if(err != GL_NO_ERROR)\r
1947     {\r
1948         return err;\r
1949     }\r
1950 \r
1951         Program *program = getCurrentProgram();\r
1952 \r
1953         device->resetInputStreams(false);\r
1954 \r
1955     for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)\r
1956         {\r
1957                 if(program->getAttributeStream(i) == -1)\r
1958                 {\r
1959                         continue;\r
1960                 }\r
1961 \r
1962                 sw::Resource *resource = attributes[i].vertexBuffer;\r
1963                 const void *buffer = (char*)resource->getBuffer() + attributes[i].offset;\r
1964                         \r
1965                 int stride = attributes[i].stride;\r
1966 \r
1967                 buffer = (char*)buffer + stride * base;\r
1968 \r
1969                 sw::Stream attribute(resource, buffer, stride);\r
1970 \r
1971                 attribute.type = attributes[i].type;\r
1972                 attribute.count = attributes[i].count;\r
1973                 attribute.normalized = attributes[i].normalized;\r
1974 \r
1975                 int stream = program->getAttributeStream(i);\r
1976                 device->setInputStream(stream, attribute);\r
1977         }\r
1978 \r
1979         return GL_NO_ERROR;\r
1980 }\r
1981 \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
1984 {\r
1985     GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);\r
1986 \r
1987     if(err == GL_NO_ERROR)\r
1988     {\r
1989         device->setIndexBuffer(indexInfo->indexBuffer);\r
1990     }\r
1991 \r
1992     return err;\r
1993 }\r
1994 \r
1995 // Applies the shaders and shader constants\r
1996 void Context::applyShaders()\r
1997 {\r
1998     Program *programObject = getCurrentProgram();\r
1999     sw::VertexShader *vertexShader = programObject->getVertexShader();\r
2000         sw::PixelShader *pixelShader = programObject->getPixelShader();\r
2001 \r
2002     device->setVertexShader(vertexShader);\r
2003     device->setPixelShader(pixelShader);\r
2004 \r
2005     if(programObject->getSerial() != mAppliedProgramSerial)\r
2006     {\r
2007         programObject->dirtyAllUniforms();\r
2008         mAppliedProgramSerial = programObject->getSerial();\r
2009     }\r
2010 \r
2011     programObject->applyUniforms();\r
2012 }\r
2013 \r
2014 void Context::applyTextures()\r
2015 {\r
2016     applyTextures(sw::SAMPLER_PIXEL);\r
2017         applyTextures(sw::SAMPLER_VERTEX);\r
2018 }\r
2019 \r
2020 void Context::applyTextures(sw::SamplerType samplerType)\r
2021 {\r
2022     Program *programObject = getCurrentProgram();\r
2023 \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
2025 \r
2026     for(int samplerIndex = 0; samplerIndex < samplerCount; samplerIndex++)\r
2027     {\r
2028         int textureUnit = programObject->getSamplerMapping(samplerType, samplerIndex);   // OpenGL texture image unit index\r
2029 \r
2030         if(textureUnit != -1)\r
2031         {\r
2032             TextureType textureType = programObject->getSamplerTextureType(samplerType, samplerIndex);\r
2033 \r
2034             Texture *texture = getSamplerTexture(textureUnit, textureType);\r
2035 \r
2036                         if(texture->isSamplerComplete())\r
2037             {\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
2043 \r
2044                                 device->setAddressingModeU(samplerType, samplerIndex, rad2sw::ConvertTextureWrap(wrapS));\r
2045                 device->setAddressingModeV(samplerType, samplerIndex, rad2sw::ConvertTextureWrap(wrapT));\r
2046 \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
2051 \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
2056 \r
2057                                 applyTexture(samplerType, samplerIndex, texture);\r
2058             }\r
2059             else\r
2060             {\r
2061                 applyTexture(samplerType, samplerIndex, 0);\r
2062             }\r
2063         }\r
2064         else\r
2065         {\r
2066             applyTexture(samplerType, samplerIndex, NULL);\r
2067         }\r
2068     }\r
2069 }\r
2070 \r
2071 void Context::applyTexture(sw::SamplerType type, int index, Texture *baseTexture)\r
2072 {\r
2073         //Program *program = getCurrentProgram();\r
2074         int sampler = (type == sw::SAMPLER_PIXEL) ? index : 16 + index;\r
2075         bool textureUsed = true;\r
2076 \r
2077         //if(type == sw::SAMPLER_PIXEL)\r
2078         //{\r
2079         //      textureUsed = program->getPixelShader()->usesSampler(index);\r
2080         //}\r
2081         //else if(type == sw::SAMPLER_VERTEX)\r
2082         //{\r
2083         //      textureUsed = program->getVertexShader()->usesSampler(index);\r
2084         //}\r
2085         //else UNREACHABLE();\r
2086 \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
2092 //\r
2093 //      device->setAddressingModeU(type, index, rad2sw::ConvertTextureWrap(wrapS));\r
2094 //    device->setAddressingModeV(type, index, rad2sw::ConvertTextureWrap(wrapT));\r
2095 //\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
2100 \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
2105 \r
2106         sw::Resource *resource = 0;\r
2107 \r
2108         if(baseTexture && textureUsed)\r
2109         {\r
2110                 resource = baseTexture->getResource();\r
2111         }\r
2112 \r
2113         device->setTextureResource(sampler, resource);\r
2114                         \r
2115         if(baseTexture && textureUsed)\r
2116         {\r
2117                 int levelCount = baseTexture->getLevelCount();\r
2118 \r
2119                 if(baseTexture->getTarget() == GL_TEXTURE_2D || baseTexture->getTarget() == GL_TEXTURE_EXTERNAL_OES)\r
2120                 {\r
2121                         Texture2D *texture = static_cast<Texture2D*>(baseTexture);\r
2122 \r
2123                         for(int mipmapLevel = 0; mipmapLevel < MIPMAP_LEVELS; mipmapLevel++)\r
2124                         {\r
2125                                 int surfaceLevel = mipmapLevel;\r
2126 \r
2127                                 if(surfaceLevel < 0)\r
2128                                 {\r
2129                                         surfaceLevel = 0;\r
2130                                 }\r
2131                                 else if(surfaceLevel >= levelCount)\r
2132                                 {\r
2133                                         surfaceLevel = levelCount - 1;\r
2134                                 }\r
2135 \r
2136                                 egl::Image *surface = texture->getImage(surfaceLevel);\r
2137                                 device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D);\r
2138                         }\r
2139                 }\r
2140                 else if(baseTexture->getTarget() == GL_TEXTURE_CUBE_MAP)\r
2141                 {\r
2142                         for(int face = 0; face < 6; face++)\r
2143                         {\r
2144                                 TextureCubeMap *cubeTexture = static_cast<TextureCubeMap*>(baseTexture);\r
2145 \r
2146                                 for(int mipmapLevel = 0; mipmapLevel < MIPMAP_LEVELS; mipmapLevel++)\r
2147                                 {\r
2148                                         int surfaceLevel = mipmapLevel;\r
2149 \r
2150                                         if(surfaceLevel < 0)\r
2151                                         {\r
2152                                                 surfaceLevel = 0;\r
2153                                         }\r
2154                                         else if(surfaceLevel >= levelCount)\r
2155                                         {\r
2156                                                 surfaceLevel = levelCount - 1;\r
2157                                         }\r
2158 \r
2159                                         egl::Image *surface = cubeTexture->getImage(face, surfaceLevel);\r
2160                                         device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);\r
2161                                 }\r
2162                         }\r
2163                 }\r
2164                 else UNIMPLEMENTED();\r
2165         }\r
2166         else\r
2167         {\r
2168                 device->setTextureLevel(sampler, 0, 0, 0, sw::TEXTURE_NULL);\r
2169         }\r
2170 }\r
2171 \r
2172 void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,\r
2173                          GLenum format, GLenum type, GLsizei *bufSize, void* pixels)\r
2174 {\r
2175     Framebuffer *framebuffer = getReadFramebuffer();\r
2176         int framebufferWidth, framebufferHeight, framebufferSamples;\r
2177 \r
2178     if(framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE)\r
2179     {\r
2180         return error(GL_INVALID_FRAMEBUFFER_OPERATION);\r
2181     }\r
2182 \r
2183     if(getReadFramebufferHandle() != 0 && framebufferSamples != 0)\r
2184     {\r
2185         return error(GL_INVALID_OPERATION);\r
2186     }\r
2187 \r
2188         GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);\r
2189     \r
2190         // Sized query sanity check\r
2191     if(bufSize)\r
2192     {\r
2193         int requiredSize = outputPitch * height;\r
2194         if(requiredSize > *bufSize)\r
2195         {\r
2196             return error(GL_INVALID_OPERATION);\r
2197         }\r
2198     }\r
2199 \r
2200     egl::Image *renderTarget = framebuffer->getRenderTarget();\r
2201 \r
2202     if(!renderTarget)\r
2203     {\r
2204         return error(GL_OUT_OF_MEMORY);\r
2205     }\r
2206 \r
2207         sw::Rect rect = {x, y, x + width, y + height};\r
2208         rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight());\r
2209 \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
2214 \r
2215     for(int j = 0; j < rect.y1 - rect.y0; j++)\r
2216     {\r
2217         if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 &&\r
2218            format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE)\r
2219         {\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
2223         }\r
2224                 else\r
2225                 {\r
2226                         for(int i = 0; i < rect.x1 - rect.x0; i++)\r
2227                         {\r
2228                                 float r;\r
2229                                 float g;\r
2230                                 float b;\r
2231                                 float a;\r
2232 \r
2233                                 switch(renderTarget->getInternalFormat())\r
2234                                 {\r
2235                                 case sw::FORMAT_R5G6B5:\r
2236                                         {\r
2237                                                 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);\r
2238 \r
2239                                                 a = 1.0f;\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
2243                                         }\r
2244                                         break;\r
2245                                 case sw::FORMAT_A1R5G5B5:\r
2246                                         {\r
2247                                                 unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);\r
2248 \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
2253                                         }\r
2254                                         break;\r
2255                                 case sw::FORMAT_A8R8G8B8:\r
2256                                         {\r
2257                                                 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);\r
2258 \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
2263                                         }\r
2264                                         break;\r
2265                                 case sw::FORMAT_X8R8G8B8:\r
2266                                         {\r
2267                                                 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);\r
2268 \r
2269                                                 a = 1.0f;\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
2273                                         }\r
2274                                         break;\r
2275                                 case sw::FORMAT_A2R10G10B10:\r
2276                                         {\r
2277                                                 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);\r
2278 \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
2283                                         }\r
2284                                         break;\r
2285                                 case sw::FORMAT_A32B32G32R32F:\r
2286                                         {\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
2291                                         }\r
2292                                         break;\r
2293                                 case sw::FORMAT_A16B16G16R16F:\r
2294                                         {\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
2299                                         }\r
2300                                         break;\r
2301                                 default:\r
2302                                         UNIMPLEMENTED();   // FIXME\r
2303                                         UNREACHABLE();\r
2304                                 }\r
2305 \r
2306                                 switch(format)\r
2307                                 {\r
2308                                 case GL_RGBA:\r
2309                                         switch(type)\r
2310                                         {\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
2316                                                 break;\r
2317                                         default: UNREACHABLE();\r
2318                                         }\r
2319                                         break;\r
2320                                 case GL_BGRA_EXT:\r
2321                                         switch(type)\r
2322                                         {\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
2328                                                 break;\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
2342                                                 break;\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
2356                                                 break;\r
2357                                         default: UNREACHABLE();\r
2358                                         }\r
2359                                         break;\r
2360                                 case GL_RGB:   // IMPLEMENTATION_COLOR_READ_FORMAT\r
2361                                         switch(type)\r
2362                                         {\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
2368                                                 break;\r
2369                                         default: UNREACHABLE();\r
2370                                         }\r
2371                                         break;\r
2372                                 default: UNREACHABLE();\r
2373                                 }\r
2374                         }\r
2375         }\r
2376     }\r
2377 \r
2378         renderTarget->unlock();\r
2379         renderTarget->release();\r
2380 }\r
2381 \r
2382 void Context::clear(GLbitfield mask)\r
2383 {\r
2384     Framebuffer *framebuffer = getDrawFramebuffer();\r
2385 \r
2386     if(!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)\r
2387     {\r
2388         return error(GL_INVALID_FRAMEBUFFER_OPERATION);\r
2389     }\r
2390 \r
2391     if(!applyRenderTarget())\r
2392     {\r
2393         return;\r
2394     }\r
2395         \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
2402 \r
2403         if(mask & GL_COLOR_BUFFER_BIT)\r
2404         {\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
2409 \r
2410                 if(rgbaMask != 0)\r
2411                 {\r
2412                         device->clearColor(color, rgbaMask);\r
2413                 }\r
2414         }\r
2415 \r
2416         if(mask & GL_DEPTH_BUFFER_BIT)\r
2417         {\r
2418                 if(mState.depthMask != 0)\r
2419                 {\r
2420                         device->clearDepth(depth);\r
2421                 }\r
2422         }\r
2423 \r
2424         if(mask & GL_STENCIL_BUFFER_BIT)\r
2425         {\r
2426                 if(mState.stencilWritemask != 0)\r
2427                 {\r
2428                         device->clearStencil(stencil, mState.stencilWritemask);\r
2429                 }\r
2430         }\r
2431 }\r
2432 \r
2433 void Context::drawArrays(GLenum mode, GLint first, GLsizei count)\r
2434 {\r
2435     if(!mState.currentProgram)\r
2436     {\r
2437         return error(GL_INVALID_OPERATION);\r
2438     }\r
2439 \r
2440     PrimitiveType primitiveType;\r
2441     int primitiveCount;\r
2442 \r
2443     if(!rad2sw::ConvertPrimitiveType(mode, count, primitiveType, primitiveCount))\r
2444         return error(GL_INVALID_ENUM);\r
2445 \r
2446     if(primitiveCount <= 0)\r
2447     {\r
2448         return;\r
2449     }\r
2450 \r
2451     if(!applyRenderTarget())\r
2452     {\r
2453         return;\r
2454     }\r
2455 \r
2456     applyState(mode);\r
2457 \r
2458     GLenum err = applyVertexBuffer(0, first, count);\r
2459     if(err != GL_NO_ERROR)\r
2460     {\r
2461         return error(err);\r
2462     }\r
2463 \r
2464     applyShaders();\r
2465     applyTextures();\r
2466 \r
2467     if(!getCurrentProgram()->validateSamplers(false))\r
2468     {\r
2469         return error(GL_INVALID_OPERATION);\r
2470     }\r
2471 \r
2472     if(!cullSkipsDraw(mode))\r
2473     {\r
2474         device->drawPrimitive(primitiveType, primitiveCount);\r
2475     }\r
2476 }\r
2477 \r
2478 void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)\r
2479 {\r
2480     if(!mState.currentProgram && !mState.program)\r
2481     {\r
2482         return error(GL_INVALID_OPERATION);\r
2483     }\r
2484 \r
2485     if(!indices && !mState.elementArrayBuffer)\r
2486     {\r
2487         return error(GL_INVALID_OPERATION);\r
2488     }\r
2489 \r
2490     PrimitiveType primitiveType;\r
2491     int primitiveCount;\r
2492 \r
2493     if(!rad2sw::ConvertPrimitiveType(mode, count, primitiveType, primitiveCount))\r
2494         return error(GL_INVALID_ENUM);\r
2495 \r
2496     if(primitiveCount <= 0)\r
2497     {\r
2498         return;\r
2499     }\r
2500 \r
2501     if(!applyRenderTarget())\r
2502     {\r
2503         return;\r
2504     }\r
2505 \r
2506     applyState(mode);\r
2507 \r
2508     TranslatedIndexData indexInfo;\r
2509     GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);\r
2510     if(err != GL_NO_ERROR)\r
2511     {\r
2512         return error(err);\r
2513     }\r
2514 \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
2518     {\r
2519         return error(err);\r
2520     }\r
2521 \r
2522     applyShaders();\r
2523     //applyTextures();\r
2524 \r
2525     if(!getCurrentProgram()->validateSamplers(false))\r
2526     {\r
2527         return error(GL_INVALID_OPERATION);\r
2528     }\r
2529 \r
2530     if(!cullSkipsDraw(mode))\r
2531     {\r
2532                 device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, primitiveCount, IndexDataManager::typeSize(type));\r
2533     }\r
2534 }\r
2535 \r
2536 void Context::finish()\r
2537 {\r
2538         device->finish();\r
2539 }\r
2540 \r
2541 void Context::flush()\r
2542 {\r
2543     // We don't queue anything without processing it as fast as possible\r
2544 }\r
2545 \r
2546 void Context::recordInvalidEnum()\r
2547 {\r
2548     mInvalidEnum = true;\r
2549 }\r
2550 \r
2551 void Context::recordInvalidValue()\r
2552 {\r
2553     mInvalidValue = true;\r
2554 }\r
2555 \r
2556 void Context::recordInvalidOperation()\r
2557 {\r
2558     mInvalidOperation = true;\r
2559 }\r
2560 \r
2561 void Context::recordOutOfMemory()\r
2562 {\r
2563     mOutOfMemory = true;\r
2564 }\r
2565 \r
2566 void Context::recordInvalidFramebufferOperation()\r
2567 {\r
2568     mInvalidFramebufferOperation = true;\r
2569 }\r
2570 \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
2574 {\r
2575     if(mInvalidEnum)\r
2576     {\r
2577         mInvalidEnum = false;\r
2578 \r
2579         return GL_INVALID_ENUM;\r
2580     }\r
2581 \r
2582     if(mInvalidValue)\r
2583     {\r
2584         mInvalidValue = false;\r
2585 \r
2586         return GL_INVALID_VALUE;\r
2587     }\r
2588 \r
2589     if(mInvalidOperation)\r
2590     {\r
2591         mInvalidOperation = false;\r
2592 \r
2593         return GL_INVALID_OPERATION;\r
2594     }\r
2595 \r
2596     if(mOutOfMemory)\r
2597     {\r
2598         mOutOfMemory = false;\r
2599 \r
2600         return GL_OUT_OF_MEMORY;\r
2601     }\r
2602 \r
2603     if(mInvalidFramebufferOperation)\r
2604     {\r
2605         mInvalidFramebufferOperation = false;\r
2606 \r
2607         return GL_INVALID_FRAMEBUFFER_OPERATION;\r
2608     }\r
2609 \r
2610     return GL_NO_ERROR;\r
2611 }\r
2612 \r
2613 int Context::getSupportedMultiSampleDepth(sw::Format format, int requested)\r
2614 {\r
2615     if(requested <= 1)\r
2616     {\r
2617         return 1;\r
2618     }\r
2619         \r
2620         if(requested == 2)\r
2621         {\r
2622                 return 2;\r
2623         }\r
2624         \r
2625         return 4;\r
2626 }\r
2627 \r
2628 void Context::detachBuffer(GLuint buffer)\r
2629 {\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
2633 \r
2634     if(mState.arrayBuffer.id() == buffer)\r
2635     {\r
2636         mState.arrayBuffer.set(NULL);\r
2637     }\r
2638 \r
2639     if(mState.elementArrayBuffer.id() == buffer)\r
2640     {\r
2641         mState.elementArrayBuffer.set(NULL);\r
2642     }\r
2643 \r
2644     for(int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)\r
2645     {\r
2646         if(mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)\r
2647         {\r
2648             mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);\r
2649         }\r
2650     }\r
2651 }\r
2652 \r
2653 void Context::detachTexture(GLuint texture)\r
2654 {\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
2658 \r
2659     for(int type = 0; type < TEXTURE_TYPE_COUNT; type++)\r
2660     {\r
2661         for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)\r
2662         {\r
2663             if(mState.samplerTexture[type][sampler].id() == texture)\r
2664             {\r
2665                 mState.samplerTexture[type][sampler].set(NULL);\r
2666             }\r
2667         }\r
2668     }\r
2669 \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
2674 \r
2675     Framebuffer *readFramebuffer = getReadFramebuffer();\r
2676     Framebuffer *drawFramebuffer = getDrawFramebuffer();\r
2677 \r
2678     if(readFramebuffer)\r
2679     {\r
2680         readFramebuffer->detachTexture(texture);\r
2681     }\r
2682 \r
2683     if(drawFramebuffer && drawFramebuffer != readFramebuffer)\r
2684     {\r
2685         drawFramebuffer->detachTexture(texture);\r
2686     }\r
2687 }\r
2688 \r
2689 void Context::detachFramebuffer(GLuint framebuffer)\r
2690 {\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
2694 \r
2695     if(mState.readFramebuffer == framebuffer)\r
2696     {\r
2697         bindReadFramebuffer(0);\r
2698     }\r
2699 \r
2700     if(mState.drawFramebuffer == framebuffer)\r
2701     {\r
2702         bindDrawFramebuffer(0);\r
2703     }\r
2704 }\r
2705 \r
2706 void Context::detachRenderbuffer(GLuint renderbuffer)\r
2707 {\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
2711 \r
2712     if(mState.renderbuffer.id() == renderbuffer)\r
2713     {\r
2714         bindRenderbuffer(0);\r
2715     }\r
2716 \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
2721 \r
2722     Framebuffer *readFramebuffer = getReadFramebuffer();\r
2723     Framebuffer *drawFramebuffer = getDrawFramebuffer();\r
2724 \r
2725     if(readFramebuffer)\r
2726     {\r
2727         readFramebuffer->detachRenderbuffer(renderbuffer);\r
2728     }\r
2729 \r
2730     if(drawFramebuffer && drawFramebuffer != readFramebuffer)\r
2731     {\r
2732         drawFramebuffer->detachRenderbuffer(renderbuffer);\r
2733     }\r
2734 }\r
2735 \r
2736 bool Context::cullSkipsDraw(GLenum drawMode)\r
2737 {\r
2738     return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);\r
2739 }\r
2740 \r
2741 bool Context::isTriangleMode(GLenum drawMode)\r
2742 {\r
2743     switch (drawMode)\r
2744     {\r
2745       case GL_TRIANGLES:\r
2746       case GL_TRIANGLE_FAN:\r
2747       case GL_TRIANGLE_STRIP:\r
2748         return true;\r
2749       case GL_POINTS:\r
2750       case GL_LINES:\r
2751       case GL_LINE_LOOP:\r
2752       case GL_LINE_STRIP:\r
2753         return false;\r
2754       default: UNREACHABLE();\r
2755     }\r
2756 \r
2757     return false;\r
2758 }\r
2759 \r
2760 void Context::setVertexAttrib(GLuint index, const GLfloat *values)\r
2761 {\r
2762     ASSERT(index < MAX_VERTEX_ATTRIBS);\r
2763 \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
2768 \r
2769     mVertexDataManager->dirtyCurrentValue(index);\r
2770 }\r
2771 \r
2772 void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, \r
2773                               GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,\r
2774                               GLbitfield mask)\r
2775 {\r
2776     Framebuffer *readFramebuffer = getReadFramebuffer();\r
2777     Framebuffer *drawFramebuffer = getDrawFramebuffer();\r
2778 \r
2779         int readBufferWidth, readBufferHeight, readBufferSamples;\r
2780     int drawBufferWidth, drawBufferHeight, drawBufferSamples;\r
2781 \r
2782     if(!readFramebuffer || readFramebuffer->completeness(readBufferWidth, readBufferHeight, readBufferSamples) != GL_FRAMEBUFFER_COMPLETE ||\r
2783        !drawFramebuffer || drawFramebuffer->completeness(drawBufferWidth, drawBufferHeight, drawBufferSamples) != GL_FRAMEBUFFER_COMPLETE)\r
2784     {\r
2785         return error(GL_INVALID_FRAMEBUFFER_OPERATION);\r
2786     }\r
2787 \r
2788     if(drawBufferSamples > 1)\r
2789     {\r
2790         return error(GL_INVALID_OPERATION);\r
2791     }\r
2792 \r
2793     sw::Rect sourceRect;\r
2794     sw::Rect destRect;\r
2795 \r
2796     if(srcX0 < srcX1)\r
2797     {\r
2798         sourceRect.x0 = srcX0;\r
2799         sourceRect.x1 = srcX1;\r
2800         destRect.x0 = dstX0;\r
2801         destRect.x1 = dstX1;\r
2802     }\r
2803     else\r
2804     {\r
2805         sourceRect.x0 = srcX1;\r
2806         destRect.x0 = dstX1;\r
2807         sourceRect.x1 = srcX0;\r
2808         destRect.x1 = dstX0;\r
2809     }\r
2810 \r
2811     if(srcY0 < srcY1)\r
2812     {\r
2813         sourceRect.y0 = srcY0;\r
2814         destRect.y0 = dstY0;\r
2815         sourceRect.y1 = srcY1;\r
2816         destRect.y1 = dstY1;\r
2817     }\r
2818     else\r
2819     {\r
2820         sourceRect.y0 = srcY1;\r
2821         destRect.y0 = dstY1;\r
2822         sourceRect.y1 = srcY0;\r
2823         destRect.y1 = dstY0;\r
2824     }\r
2825 \r
2826     sw::Rect sourceScissoredRect = sourceRect;\r
2827     sw::Rect destScissoredRect = destRect;\r
2828 \r
2829     if(mState.scissorTest)   // Only write to parts of the destination framebuffer which pass the scissor test\r
2830     {\r
2831         if(destRect.x0 < mState.scissorX)\r
2832         {\r
2833             int xDiff = mState.scissorX - destRect.x0;\r
2834             destScissoredRect.x0 = mState.scissorX;\r
2835             sourceScissoredRect.x0 += xDiff;\r
2836         }\r
2837 \r
2838         if(destRect.x1 > mState.scissorX + mState.scissorWidth)\r
2839         {\r
2840             int xDiff = destRect.x1 - (mState.scissorX + mState.scissorWidth);\r
2841             destScissoredRect.x1 = mState.scissorX + mState.scissorWidth;\r
2842             sourceScissoredRect.x1 -= xDiff;\r
2843         }\r
2844 \r
2845         if(destRect.y0 < mState.scissorY)\r
2846         {\r
2847             int yDiff = mState.scissorY - destRect.y0;\r
2848             destScissoredRect.y0 = mState.scissorY;\r
2849             sourceScissoredRect.y0 += yDiff;\r
2850         }\r
2851 \r
2852         if(destRect.y1 > mState.scissorY + mState.scissorHeight)\r
2853         {\r
2854             int yDiff = destRect.y1 - (mState.scissorY + mState.scissorHeight);\r
2855             destScissoredRect.y1 = mState.scissorY + mState.scissorHeight;\r
2856             sourceScissoredRect.y1 -= yDiff;\r
2857         }\r
2858     }\r
2859 \r
2860     sw::Rect sourceTrimmedRect = sourceScissoredRect;\r
2861     sw::Rect destTrimmedRect = destScissoredRect;\r
2862 \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
2866     {\r
2867         int xDiff = 0 - sourceTrimmedRect.x0;\r
2868         sourceTrimmedRect.x0 = 0;\r
2869         destTrimmedRect.x0 += xDiff;\r
2870     }\r
2871 \r
2872     if(sourceTrimmedRect.x1 > readBufferWidth)\r
2873     {\r
2874         int xDiff = sourceTrimmedRect.x1 - readBufferWidth;\r
2875         sourceTrimmedRect.x1 = readBufferWidth;\r
2876         destTrimmedRect.x1 -= xDiff;\r
2877     }\r
2878 \r
2879     if(sourceTrimmedRect.y0 < 0)\r
2880     {\r
2881         int yDiff = 0 - sourceTrimmedRect.y0;\r
2882         sourceTrimmedRect.y0 = 0;\r
2883         destTrimmedRect.y0 += yDiff;\r
2884     }\r
2885 \r
2886     if(sourceTrimmedRect.y1 > readBufferHeight)\r
2887     {\r
2888         int yDiff = sourceTrimmedRect.y1 - readBufferHeight;\r
2889         sourceTrimmedRect.y1 = readBufferHeight;\r
2890         destTrimmedRect.y1 -= yDiff;\r
2891     }\r
2892 \r
2893     if(destTrimmedRect.x0 < 0)\r
2894     {\r
2895         int xDiff = 0 - destTrimmedRect.x0;\r
2896         destTrimmedRect.x0 = 0;\r
2897         sourceTrimmedRect.x0 += xDiff;\r
2898     }\r
2899 \r
2900     if(destTrimmedRect.x1 > drawBufferWidth)\r
2901     {\r
2902         int xDiff = destTrimmedRect.x1 - drawBufferWidth;\r
2903         destTrimmedRect.x1 = drawBufferWidth;\r
2904         sourceTrimmedRect.x1 -= xDiff;\r
2905     }\r
2906 \r
2907     if(destTrimmedRect.y0 < 0)\r
2908     {\r
2909         int yDiff = 0 - destTrimmedRect.y0;\r
2910         destTrimmedRect.y0 = 0;\r
2911         sourceTrimmedRect.y0 += yDiff;\r
2912     }\r
2913 \r
2914     if(destTrimmedRect.y1 > drawBufferHeight)\r
2915     {\r
2916         int yDiff = destTrimmedRect.y1 - drawBufferHeight;\r
2917         destTrimmedRect.y1 = drawBufferHeight;\r
2918         sourceTrimmedRect.y1 -= yDiff;\r
2919     }\r
2920 \r
2921     bool partialBufferCopy = false;\r
2922 \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
2928     {\r
2929         partialBufferCopy = true;\r
2930     }\r
2931 \r
2932         bool blitRenderTarget = false;\r
2933     bool blitDepthStencil = false;\r
2934 \r
2935     if(mask & GL_COLOR_BUFFER_BIT)\r
2936     {\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
2943         {\r
2944             ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");\r
2945             return error(GL_INVALID_OPERATION);\r
2946         }\r
2947         \r
2948         if(partialBufferCopy && readBufferSamples > 1)\r
2949         {\r
2950             return error(GL_INVALID_OPERATION);\r
2951         }\r
2952 \r
2953         blitRenderTarget = true;\r
2954     }\r
2955 \r
2956     if(mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))\r
2957     {\r
2958         Renderbuffer *readDSBuffer = NULL;\r
2959         Renderbuffer *drawDSBuffer = NULL;\r
2960 \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
2963 \r
2964         if(mask & GL_DEPTH_BUFFER_BIT)\r
2965         {\r
2966             if(readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())\r
2967             {\r
2968                 if(readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||\r
2969                    readFramebuffer->getDepthbuffer()->getInternalFormat() != drawFramebuffer->getDepthbuffer()->getInternalFormat())\r
2970                 {\r
2971                     return error(GL_INVALID_OPERATION);\r
2972                 }\r
2973 \r
2974                 blitDepthStencil = true;\r
2975                 readDSBuffer = readFramebuffer->getDepthbuffer();\r
2976                 drawDSBuffer = drawFramebuffer->getDepthbuffer();\r
2977             }\r
2978         }\r
2979 \r
2980         if(mask & GL_STENCIL_BUFFER_BIT)\r
2981         {\r
2982             if(readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())\r
2983             {\r
2984                 if(readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||\r
2985                    readFramebuffer->getStencilbuffer()->getInternalFormat() != drawFramebuffer->getStencilbuffer()->getInternalFormat())\r
2986                 {\r
2987                     return error(GL_INVALID_OPERATION);\r
2988                 }\r
2989 \r
2990                 blitDepthStencil = true;\r
2991                 readDSBuffer = readFramebuffer->getStencilbuffer();\r
2992                 drawDSBuffer = drawFramebuffer->getStencilbuffer();\r
2993             }\r
2994         }\r
2995 \r
2996         if(partialBufferCopy)\r
2997         {\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
3000         }\r
3001 \r
3002         if((drawDSBuffer && drawDSBuffer->getSamples() > 1) || \r
3003            (readDSBuffer && readDSBuffer->getSamples() > 1))\r
3004         {\r
3005             return error(GL_INVALID_OPERATION);\r
3006         }\r
3007     }\r
3008 \r
3009     if(blitRenderTarget || blitDepthStencil)\r
3010     {\r
3011         if(blitRenderTarget)\r
3012         {\r
3013             egl::Image *readRenderTarget = readFramebuffer->getRenderTarget();\r
3014             egl::Image *drawRenderTarget = drawFramebuffer->getRenderTarget();\r
3015  \r
3016             bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, false);\r
3017 \r
3018             readRenderTarget->release();\r
3019             drawRenderTarget->release();\r
3020 \r
3021             if(!success)\r
3022             {\r
3023                 ERR("BlitFramebufferANGLE failed.");\r
3024                 return;\r
3025             }\r
3026         }\r
3027 \r
3028         if(blitDepthStencil)\r
3029         {\r
3030             bool success = device->stretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, false);\r
3031 \r
3032             if(!success)\r
3033             {\r
3034                 ERR("BlitFramebufferANGLE failed.");\r
3035                 return;\r
3036             }\r
3037         }\r
3038     }\r
3039 }\r
3040 \r
3041 void Context::bindTexImage(egl::Surface *surface)\r
3042 {\r
3043         es2::Texture2D *textureObject = getTexture2D();\r
3044 \r
3045     if(textureObject)\r
3046     {\r
3047                 textureObject->bindTexImage(surface);\r
3048         }\r
3049 }\r
3050 \r
3051 EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel)\r
3052 {\r
3053     GLenum textureTarget = GL_NONE;\r
3054 \r
3055     switch(target)\r
3056     {\r
3057     case EGL_GL_TEXTURE_2D_KHR:\r
3058         textureTarget = GL_TEXTURE_2D;\r
3059         break;\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
3067         break;\r
3068     case EGL_GL_RENDERBUFFER_KHR:\r
3069         break;\r
3070     default:\r
3071         return EGL_BAD_PARAMETER;\r
3072     }\r
3073         \r
3074     if(textureLevel >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)\r
3075     {\r
3076         return EGL_BAD_MATCH;\r
3077     }\r
3078 \r
3079     if(textureTarget != GL_NONE)\r
3080     {\r
3081         es2::Texture *texture = getTexture(name);\r
3082 \r
3083         if(!texture || texture->getTarget() != textureTarget)\r
3084         {\r
3085             return EGL_BAD_PARAMETER;\r
3086         }\r
3087 \r
3088         if(texture->isShared(textureTarget, textureLevel))   // Bound to an EGLSurface or already an EGLImage sibling\r
3089         {\r
3090             return EGL_BAD_ACCESS;\r
3091         }\r
3092 \r
3093         if(textureLevel != 0 && !texture->isSamplerComplete())\r
3094         {\r
3095             return EGL_BAD_PARAMETER;\r
3096         }\r
3097 \r
3098         if(textureLevel == 0 && !(texture->isSamplerComplete() && texture->getLevelCount() == 1))\r
3099         {\r
3100             return EGL_BAD_PARAMETER;\r
3101         }\r
3102     }\r
3103     else if(target == EGL_GL_RENDERBUFFER_KHR)\r
3104     {\r
3105         es2::Renderbuffer *renderbuffer = getRenderbuffer(name);\r
3106 \r
3107         if(!renderbuffer)\r
3108         {\r
3109             return EGL_BAD_PARAMETER;\r
3110         }\r
3111 \r
3112         if(renderbuffer->isShared())   // Already an EGLImage sibling\r
3113         {\r
3114             return EGL_BAD_ACCESS;\r
3115         }\r
3116     }\r
3117     else UNREACHABLE();\r
3118 \r
3119         return EGL_SUCCESS;\r
3120 }\r
3121 \r
3122 egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textureLevel)\r
3123 {\r
3124         GLenum textureTarget = GL_NONE;\r
3125 \r
3126     switch(target)\r
3127     {\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
3135     }\r
3136 \r
3137     if(textureTarget != GL_NONE)\r
3138     {\r
3139         es2::Texture *texture = getTexture(name);\r
3140 \r
3141         return texture->createSharedImage(textureTarget, textureLevel);\r
3142     }\r
3143     else if(target == EGL_GL_RENDERBUFFER_KHR)\r
3144     {\r
3145         es2::Renderbuffer *renderbuffer = getRenderbuffer(name);\r
3146 \r
3147         return renderbuffer->createSharedImage();\r
3148     }\r
3149     else UNREACHABLE();\r
3150 \r
3151         return 0;\r
3152 }\r
3153 \r
3154 Device *Context::getDevice()\r
3155 {\r
3156         if(!device)\r
3157         {\r
3158                 sw::Context *context = new sw::Context();\r
3159                 device = new es2::Device(context);\r
3160         }\r
3161 \r
3162         return device;\r
3163 }\r
3164 \r
3165 }\r
3166 \r
3167 // Exported functions for use by EGL\r
3168 extern "C"\r
3169 {\r
3170         es2::Context *glCreateContext(const egl::Config *config, const es2::Context *shareContext)\r
3171         {\r
3172                 return new es2::Context(config, shareContext);\r
3173         }\r
3174 }\r