blob: e674e20b6e5dd75333238c83bdfeabaca249d903 [file] [log] [blame]
John Bauman19bac1e2014-05-06 15:23:49 -04001// SwiftShader Software Renderer
John Bauman89401822014-05-06 15:04:28 -04002//
John Bauman19bac1e2014-05-06 15:23:49 -04003// Copyright(c) 2005-2012 TransGaming Inc.
4//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
John Bauman89401822014-05-06 15:04:28 -040010//
11
12// Context.cpp: Implements the gl::Context class, managing all GL state and performing
13// rendering operations. It is the GLES2 specific implementation of EGLContext.
14
15#include "Context.h"
16
17#include "main.h"
18#include "mathutil.h"
19#include "utilities.h"
20#include "ResourceManager.h"
21#include "Buffer.h"
22#include "Fence.h"
23#include "FrameBuffer.h"
24#include "Program.h"
John Bauman19bac1e2014-05-06 15:23:49 -040025#include "Query.h"
John Bauman89401822014-05-06 15:04:28 -040026#include "RenderBuffer.h"
27#include "Shader.h"
28#include "Texture.h"
29#include "VertexDataManager.h"
30#include "IndexDataManager.h"
31#include "libEGL/Display.h"
32#include "Common/Half.hpp"
33
34#include <algorithm>
35
36#undef near
37#undef far
38
39namespace gl
40{
41Context::Context(const egl::Config *config, const Context *shareContext) : mConfig(config)
42{
43 mFenceHandleAllocator.setBaseHandle(0);
44
45 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
46
47 mState.depthClearValue = 1.0f;
48 mState.stencilClearValue = 0;
49
50 mState.cullFace = false;
51 mState.cullMode = GL_BACK;
52 mState.frontFace = GL_CCW;
53 mState.depthTest = false;
54 mState.depthFunc = GL_LESS;
55 mState.blend = false;
56 mState.sourceBlendRGB = GL_ONE;
57 mState.sourceBlendAlpha = GL_ONE;
58 mState.destBlendRGB = GL_ZERO;
59 mState.destBlendAlpha = GL_ZERO;
60 mState.blendEquationRGB = GL_FUNC_ADD;
61 mState.blendEquationAlpha = GL_FUNC_ADD;
62 mState.blendColor.red = 0;
63 mState.blendColor.green = 0;
64 mState.blendColor.blue = 0;
65 mState.blendColor.alpha = 0;
66 mState.stencilTest = false;
67 mState.stencilFunc = GL_ALWAYS;
68 mState.stencilRef = 0;
69 mState.stencilMask = -1;
70 mState.stencilWritemask = -1;
71 mState.stencilBackFunc = GL_ALWAYS;
72 mState.stencilBackRef = 0;
73 mState.stencilBackMask = - 1;
74 mState.stencilBackWritemask = -1;
75 mState.stencilFail = GL_KEEP;
76 mState.stencilPassDepthFail = GL_KEEP;
77 mState.stencilPassDepthPass = GL_KEEP;
78 mState.stencilBackFail = GL_KEEP;
79 mState.stencilBackPassDepthFail = GL_KEEP;
80 mState.stencilBackPassDepthPass = GL_KEEP;
81 mState.polygonOffsetFill = false;
82 mState.polygonOffsetFactor = 0.0f;
83 mState.polygonOffsetUnits = 0.0f;
84 mState.sampleAlphaToCoverage = false;
85 mState.sampleCoverage = false;
86 mState.sampleCoverageValue = 1.0f;
87 mState.sampleCoverageInvert = false;
88 mState.scissorTest = false;
89 mState.dither = true;
90 mState.generateMipmapHint = GL_DONT_CARE;
91 mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
92
93 mState.lineWidth = 1.0f;
94
95 mState.viewportX = 0;
96 mState.viewportY = 0;
97 mState.viewportWidth = config->mDisplayMode.width;
98 mState.viewportHeight = config->mDisplayMode.height;
99 mState.zNear = 0.0f;
100 mState.zFar = 1.0f;
101
102 mState.scissorX = 0;
103 mState.scissorY = 0;
104 mState.scissorWidth = config->mDisplayMode.width;
105 mState.scissorHeight = config->mDisplayMode.height;
106
107 mState.colorMaskRed = true;
108 mState.colorMaskGreen = true;
109 mState.colorMaskBlue = true;
110 mState.colorMaskAlpha = true;
111 mState.depthMask = true;
112
113 if(shareContext != NULL)
114 {
115 mResourceManager = shareContext->mResourceManager;
116 mResourceManager->addRef();
117 }
118 else
119 {
120 mResourceManager = new ResourceManager();
121 }
122
123 // [OpenGL ES 2.0.24] section 3.7 page 83:
124 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
125 // and cube map texture state vectors respectively associated with them.
126 // In order that access to these initial textures not be lost, they are treated as texture
127 // objects all of whose names are 0.
128
129 mTexture2DZero.set(new Texture2D(0));
130 mTextureCubeMapZero.set(new TextureCubeMap(0));
131
132 mState.activeSampler = 0;
133 bindArrayBuffer(0);
134 bindElementArrayBuffer(0);
135 bindTextureCubeMap(0);
136 bindTexture2D(0);
137 bindReadFramebuffer(0);
138 bindDrawFramebuffer(0);
139 bindRenderbuffer(0);
140
141 mState.currentProgram = 0;
142
143 mState.packAlignment = 4;
144 mState.unpackAlignment = 4;
145
146 mVertexDataManager = NULL;
147 mIndexDataManager = NULL;
148
149 mInvalidEnum = false;
150 mInvalidValue = false;
151 mInvalidOperation = false;
152 mOutOfMemory = false;
153 mInvalidFramebufferOperation = false;
154
155 mHasBeenCurrent = false;
156
157 markAllStateDirty();
158}
159
160Context::~Context()
161{
162 if(mState.currentProgram != 0)
163 {
164 Program *programObject = mResourceManager->getProgram(mState.currentProgram);
165 if(programObject)
166 {
167 programObject->release();
168 }
169 mState.currentProgram = 0;
170 }
171
172 while(!mFramebufferMap.empty())
173 {
174 deleteFramebuffer(mFramebufferMap.begin()->first);
175 }
176
177 while(!mFenceMap.empty())
178 {
179 deleteFence(mFenceMap.begin()->first);
180 }
181
John Bauman19bac1e2014-05-06 15:23:49 -0400182 while(!mQueryMap.empty())
183 {
184 deleteQuery(mQueryMap.begin()->first);
185 }
186
John Bauman89401822014-05-06 15:04:28 -0400187 while(!mMultiSampleSupport.empty())
188 {
189 delete [] mMultiSampleSupport.begin()->second;
190 mMultiSampleSupport.erase(mMultiSampleSupport.begin());
191 }
192
193 for(int type = 0; type < TEXTURE_TYPE_COUNT; type++)
194 {
195 for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
196 {
197 mState.samplerTexture[type][sampler].set(NULL);
198 }
199 }
200
201 for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
202 {
203 mState.vertexAttribute[i].mBoundBuffer.set(NULL);
204 }
205
John Bauman19bac1e2014-05-06 15:23:49 -0400206 for(int i = 0; i < QUERY_TYPE_COUNT; i++)
207 {
208 mState.activeQuery[i].set(NULL);
209 }
210
John Bauman89401822014-05-06 15:04:28 -0400211 mState.arrayBuffer.set(NULL);
212 mState.elementArrayBuffer.set(NULL);
213 mState.renderbuffer.set(NULL);
214
215 mTexture2DZero.set(NULL);
216 mTextureCubeMapZero.set(NULL);
217
218 delete mVertexDataManager;
219 delete mIndexDataManager;
220
221 mResourceManager->release();
222}
223
224void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
225{
226 Device *device = display->getDevice();
227
228 if(!mHasBeenCurrent)
229 {
John Bauman19bac1e2014-05-06 15:23:49 -0400230 mVertexDataManager = new VertexDataManager(this);
231 mIndexDataManager = new IndexDataManager();
John Bauman89401822014-05-06 15:04:28 -0400232
233 const sw::Format renderBufferFormats[] =
234 {
235 sw::FORMAT_A8R8G8B8,
236 sw::FORMAT_X8R8G8B8,
237 sw::FORMAT_R5G6B5,
238 sw::FORMAT_D24S8
239 };
240
241 initExtensionString();
242
243 mState.viewportX = 0;
244 mState.viewportY = 0;
245 mState.viewportWidth = surface->getWidth();
246 mState.viewportHeight = surface->getHeight();
247
248 mState.scissorX = 0;
249 mState.scissorY = 0;
250 mState.scissorWidth = surface->getWidth();
251 mState.scissorHeight = surface->getHeight();
252
253 mHasBeenCurrent = true;
254 }
255
256 // Wrap the existing resources into GL objects and assign them to the '0' names
257 Image *defaultRenderTarget = surface->getRenderTarget();
258 Image *depthStencil = surface->getDepthStencil();
259
260 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
261 DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
262 Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);
263
264 setFramebufferZero(framebufferZero);
265
266 if(defaultRenderTarget)
267 {
268 defaultRenderTarget->release();
269 }
270
271 if(depthStencil)
272 {
273 depthStencil->release();
274 }
275
276 markAllStateDirty();
277}
278
279// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
280void Context::markAllStateDirty()
281{
282 mAppliedProgramSerial = 0;
John Bauman89401822014-05-06 15:04:28 -0400283
John Bauman89401822014-05-06 15:04:28 -0400284 mDepthStateDirty = true;
285 mMaskStateDirty = true;
286 mBlendStateDirty = true;
287 mStencilStateDirty = true;
288 mPolygonOffsetStateDirty = true;
John Bauman89401822014-05-06 15:04:28 -0400289 mSampleStateDirty = true;
290 mDitherStateDirty = true;
291 mFrontFaceDirty = true;
292}
293
294void Context::setClearColor(float red, float green, float blue, float alpha)
295{
296 mState.colorClearValue.red = red;
297 mState.colorClearValue.green = green;
298 mState.colorClearValue.blue = blue;
299 mState.colorClearValue.alpha = alpha;
300}
301
302void Context::setClearDepth(float depth)
303{
304 mState.depthClearValue = depth;
305}
306
307void Context::setClearStencil(int stencil)
308{
309 mState.stencilClearValue = stencil;
310}
311
312void Context::setCullFace(bool enabled)
313{
John Bauman19bac1e2014-05-06 15:23:49 -0400314 mState.cullFace = enabled;
John Bauman89401822014-05-06 15:04:28 -0400315}
316
317bool Context::isCullFaceEnabled() const
318{
319 return mState.cullFace;
320}
321
322void Context::setCullMode(GLenum mode)
323{
John Bauman19bac1e2014-05-06 15:23:49 -0400324 mState.cullMode = mode;
John Bauman89401822014-05-06 15:04:28 -0400325}
326
327void Context::setFrontFace(GLenum front)
328{
329 if(mState.frontFace != front)
330 {
331 mState.frontFace = front;
332 mFrontFaceDirty = true;
333 }
334}
335
336void Context::setDepthTest(bool enabled)
337{
338 if(mState.depthTest != enabled)
339 {
340 mState.depthTest = enabled;
341 mDepthStateDirty = true;
342 }
343}
344
345bool Context::isDepthTestEnabled() const
346{
347 return mState.depthTest;
348}
349
350void Context::setDepthFunc(GLenum depthFunc)
351{
352 if(mState.depthFunc != depthFunc)
353 {
354 mState.depthFunc = depthFunc;
355 mDepthStateDirty = true;
356 }
357}
358
359void Context::setDepthRange(float zNear, float zFar)
360{
361 mState.zNear = zNear;
362 mState.zFar = zFar;
363}
364
365void Context::setBlend(bool enabled)
366{
367 if(mState.blend != enabled)
368 {
369 mState.blend = enabled;
370 mBlendStateDirty = true;
371 }
372}
373
374bool Context::isBlendEnabled() const
375{
376 return mState.blend;
377}
378
379void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
380{
381 if(mState.sourceBlendRGB != sourceRGB ||
382 mState.sourceBlendAlpha != sourceAlpha ||
383 mState.destBlendRGB != destRGB ||
384 mState.destBlendAlpha != destAlpha)
385 {
386 mState.sourceBlendRGB = sourceRGB;
387 mState.destBlendRGB = destRGB;
388 mState.sourceBlendAlpha = sourceAlpha;
389 mState.destBlendAlpha = destAlpha;
390 mBlendStateDirty = true;
391 }
392}
393
394void Context::setBlendColor(float red, float green, float blue, float alpha)
395{
396 if(mState.blendColor.red != red ||
397 mState.blendColor.green != green ||
398 mState.blendColor.blue != blue ||
399 mState.blendColor.alpha != alpha)
400 {
401 mState.blendColor.red = red;
402 mState.blendColor.green = green;
403 mState.blendColor.blue = blue;
404 mState.blendColor.alpha = alpha;
405 mBlendStateDirty = true;
406 }
407}
408
409void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
410{
411 if(mState.blendEquationRGB != rgbEquation ||
412 mState.blendEquationAlpha != alphaEquation)
413 {
414 mState.blendEquationRGB = rgbEquation;
415 mState.blendEquationAlpha = alphaEquation;
416 mBlendStateDirty = true;
417 }
418}
419
420void Context::setStencilTest(bool enabled)
421{
422 if(mState.stencilTest != enabled)
423 {
424 mState.stencilTest = enabled;
425 mStencilStateDirty = true;
426 }
427}
428
429bool Context::isStencilTestEnabled() const
430{
431 return mState.stencilTest;
432}
433
434void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
435{
436 if(mState.stencilFunc != stencilFunc ||
437 mState.stencilRef != stencilRef ||
438 mState.stencilMask != stencilMask)
439 {
440 mState.stencilFunc = stencilFunc;
441 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
442 mState.stencilMask = stencilMask;
443 mStencilStateDirty = true;
444 }
445}
446
447void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
448{
449 if(mState.stencilBackFunc != stencilBackFunc ||
450 mState.stencilBackRef != stencilBackRef ||
451 mState.stencilBackMask != stencilBackMask)
452 {
453 mState.stencilBackFunc = stencilBackFunc;
454 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
455 mState.stencilBackMask = stencilBackMask;
456 mStencilStateDirty = true;
457 }
458}
459
460void Context::setStencilWritemask(GLuint stencilWritemask)
461{
462 if(mState.stencilWritemask != stencilWritemask)
463 {
464 mState.stencilWritemask = stencilWritemask;
465 mStencilStateDirty = true;
466 }
467}
468
469void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
470{
471 if(mState.stencilBackWritemask != stencilBackWritemask)
472 {
473 mState.stencilBackWritemask = stencilBackWritemask;
474 mStencilStateDirty = true;
475 }
476}
477
478void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
479{
480 if(mState.stencilFail != stencilFail ||
481 mState.stencilPassDepthFail != stencilPassDepthFail ||
482 mState.stencilPassDepthPass != stencilPassDepthPass)
483 {
484 mState.stencilFail = stencilFail;
485 mState.stencilPassDepthFail = stencilPassDepthFail;
486 mState.stencilPassDepthPass = stencilPassDepthPass;
487 mStencilStateDirty = true;
488 }
489}
490
491void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
492{
493 if(mState.stencilBackFail != stencilBackFail ||
494 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
495 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
496 {
497 mState.stencilBackFail = stencilBackFail;
498 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
499 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
500 mStencilStateDirty = true;
501 }
502}
503
504void Context::setPolygonOffsetFill(bool enabled)
505{
506 if(mState.polygonOffsetFill != enabled)
507 {
508 mState.polygonOffsetFill = enabled;
509 mPolygonOffsetStateDirty = true;
510 }
511}
512
513bool Context::isPolygonOffsetFillEnabled() const
514{
515 return mState.polygonOffsetFill;
516
517}
518
519void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
520{
521 if(mState.polygonOffsetFactor != factor ||
522 mState.polygonOffsetUnits != units)
523 {
524 mState.polygonOffsetFactor = factor;
525 mState.polygonOffsetUnits = units;
526 mPolygonOffsetStateDirty = true;
527 }
528}
529
530void Context::setSampleAlphaToCoverage(bool enabled)
531{
532 if(mState.sampleAlphaToCoverage != enabled)
533 {
534 mState.sampleAlphaToCoverage = enabled;
535 mSampleStateDirty = true;
536 }
537}
538
539bool Context::isSampleAlphaToCoverageEnabled() const
540{
541 return mState.sampleAlphaToCoverage;
542}
543
544void Context::setSampleCoverage(bool enabled)
545{
546 if(mState.sampleCoverage != enabled)
547 {
548 mState.sampleCoverage = enabled;
549 mSampleStateDirty = true;
550 }
551}
552
553bool Context::isSampleCoverageEnabled() const
554{
555 return mState.sampleCoverage;
556}
557
558void Context::setSampleCoverageParams(GLclampf value, bool invert)
559{
560 if(mState.sampleCoverageValue != value ||
561 mState.sampleCoverageInvert != invert)
562 {
563 mState.sampleCoverageValue = value;
564 mState.sampleCoverageInvert = invert;
565 mSampleStateDirty = true;
566 }
567}
568
569void Context::setScissorTest(bool enabled)
570{
John Bauman19bac1e2014-05-06 15:23:49 -0400571 mState.scissorTest = enabled;
John Bauman89401822014-05-06 15:04:28 -0400572}
573
574bool Context::isScissorTestEnabled() const
575{
576 return mState.scissorTest;
577}
578
579void Context::setDither(bool enabled)
580{
581 if(mState.dither != enabled)
582 {
583 mState.dither = enabled;
584 mDitherStateDirty = true;
585 }
586}
587
588bool Context::isDitherEnabled() const
589{
590 return mState.dither;
591}
592
593void Context::setLineWidth(GLfloat width)
594{
595 mState.lineWidth = width;
596}
597
598void Context::setGenerateMipmapHint(GLenum hint)
599{
600 mState.generateMipmapHint = hint;
601}
602
603void Context::setFragmentShaderDerivativeHint(GLenum hint)
604{
605 mState.fragmentShaderDerivativeHint = hint;
606 // TODO: Propagate the hint to shader translator so we can write
607 // ddx, ddx_coarse, or ddx_fine depending on the hint.
608 // Ignore for now. It is valid for implementations to ignore hint.
609}
610
611void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
612{
613 mState.viewportX = x;
614 mState.viewportY = y;
615 mState.viewportWidth = width;
616 mState.viewportHeight = height;
617}
618
619void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
620{
John Bauman19bac1e2014-05-06 15:23:49 -0400621 mState.scissorX = x;
622 mState.scissorY = y;
623 mState.scissorWidth = width;
624 mState.scissorHeight = height;
John Bauman89401822014-05-06 15:04:28 -0400625}
626
627void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
628{
629 if(mState.colorMaskRed != red || mState.colorMaskGreen != green ||
John Bauman19bac1e2014-05-06 15:23:49 -0400630 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
John Bauman89401822014-05-06 15:04:28 -0400631 {
632 mState.colorMaskRed = red;
633 mState.colorMaskGreen = green;
634 mState.colorMaskBlue = blue;
635 mState.colorMaskAlpha = alpha;
636 mMaskStateDirty = true;
637 }
638}
639
640void Context::setDepthMask(bool mask)
641{
642 if(mState.depthMask != mask)
643 {
644 mState.depthMask = mask;
645 mMaskStateDirty = true;
646 }
647}
648
649void Context::setActiveSampler(unsigned int active)
650{
651 mState.activeSampler = active;
652}
653
654GLuint Context::getReadFramebufferHandle() const
655{
656 return mState.readFramebuffer;
657}
658
659GLuint Context::getDrawFramebufferHandle() const
660{
661 return mState.drawFramebuffer;
662}
663
664GLuint Context::getRenderbufferHandle() const
665{
666 return mState.renderbuffer.id();
667}
668
669GLuint Context::getArrayBufferHandle() const
670{
671 return mState.arrayBuffer.id();
672}
673
John Bauman19bac1e2014-05-06 15:23:49 -0400674GLuint Context::getActiveQuery(GLenum target) const
675{
676 Query *queryObject = NULL;
677
678 switch(target)
679 {
680 case GL_ANY_SAMPLES_PASSED_EXT:
681 queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();
682 break;
683 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
684 queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();
685 break;
686 default:
687 ASSERT(false);
688 }
689
690 if(queryObject)
691 {
692 return queryObject->id();
693 }
694
695 return 0;
696}
697
John Bauman89401822014-05-06 15:04:28 -0400698void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
699{
700 mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
701}
702
703const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
704{
705 return mState.vertexAttribute[attribNum];
706}
707
708void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
709 GLsizei stride, const void *pointer)
710{
711 mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
712 mState.vertexAttribute[attribNum].mSize = size;
713 mState.vertexAttribute[attribNum].mType = type;
714 mState.vertexAttribute[attribNum].mNormalized = normalized;
715 mState.vertexAttribute[attribNum].mStride = stride;
716 mState.vertexAttribute[attribNum].mPointer = pointer;
717}
718
719const void *Context::getVertexAttribPointer(unsigned int attribNum) const
720{
721 return mState.vertexAttribute[attribNum].mPointer;
722}
723
724const VertexAttributeArray &Context::getVertexAttributes()
725{
726 return mState.vertexAttribute;
727}
728
729void Context::setPackAlignment(GLint alignment)
730{
731 mState.packAlignment = alignment;
732}
733
734GLint Context::getPackAlignment() const
735{
736 return mState.packAlignment;
737}
738
739void Context::setUnpackAlignment(GLint alignment)
740{
741 mState.unpackAlignment = alignment;
742}
743
744GLint Context::getUnpackAlignment() const
745{
746 return mState.unpackAlignment;
747}
748
749GLuint Context::createBuffer()
750{
751 return mResourceManager->createBuffer();
752}
753
754GLuint Context::createProgram()
755{
756 return mResourceManager->createProgram();
757}
758
759GLuint Context::createShader(GLenum type)
760{
761 return mResourceManager->createShader(type);
762}
763
764GLuint Context::createTexture()
765{
766 return mResourceManager->createTexture();
767}
768
769GLuint Context::createRenderbuffer()
770{
771 return mResourceManager->createRenderbuffer();
772}
773
774// Returns an unused framebuffer name
775GLuint Context::createFramebuffer()
776{
777 GLuint handle = mFramebufferHandleAllocator.allocate();
778
779 mFramebufferMap[handle] = NULL;
780
781 return handle;
782}
783
784GLuint Context::createFence()
785{
786 GLuint handle = mFenceHandleAllocator.allocate();
787
788 mFenceMap[handle] = new Fence;
789
790 return handle;
791}
792
John Bauman19bac1e2014-05-06 15:23:49 -0400793// Returns an unused query name
794GLuint Context::createQuery()
795{
796 GLuint handle = mQueryHandleAllocator.allocate();
797
798 mQueryMap[handle] = NULL;
799
800 return handle;
801}
802
John Bauman89401822014-05-06 15:04:28 -0400803void Context::deleteBuffer(GLuint buffer)
804{
805 if(mResourceManager->getBuffer(buffer))
806 {
807 detachBuffer(buffer);
808 }
809
810 mResourceManager->deleteBuffer(buffer);
811}
812
813void Context::deleteShader(GLuint shader)
814{
815 mResourceManager->deleteShader(shader);
816}
817
818void Context::deleteProgram(GLuint program)
819{
820 mResourceManager->deleteProgram(program);
821}
822
823void Context::deleteTexture(GLuint texture)
824{
825 if(mResourceManager->getTexture(texture))
826 {
827 detachTexture(texture);
828 }
829
830 mResourceManager->deleteTexture(texture);
831}
832
833void Context::deleteRenderbuffer(GLuint renderbuffer)
834{
835 if(mResourceManager->getRenderbuffer(renderbuffer))
836 {
837 detachRenderbuffer(renderbuffer);
838 }
839
840 mResourceManager->deleteRenderbuffer(renderbuffer);
841}
842
843void Context::deleteFramebuffer(GLuint framebuffer)
844{
845 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
846
847 if(framebufferObject != mFramebufferMap.end())
848 {
849 detachFramebuffer(framebuffer);
850
851 mFramebufferHandleAllocator.release(framebufferObject->first);
852 delete framebufferObject->second;
853 mFramebufferMap.erase(framebufferObject);
854 }
855}
856
857void Context::deleteFence(GLuint fence)
858{
859 FenceMap::iterator fenceObject = mFenceMap.find(fence);
860
861 if(fenceObject != mFenceMap.end())
862 {
863 mFenceHandleAllocator.release(fenceObject->first);
864 delete fenceObject->second;
865 mFenceMap.erase(fenceObject);
866 }
867}
868
John Bauman19bac1e2014-05-06 15:23:49 -0400869void Context::deleteQuery(GLuint query)
870{
871 QueryMap::iterator queryObject = mQueryMap.find(query);
872
873 if(queryObject != mQueryMap.end())
874 {
875 mQueryHandleAllocator.release(queryObject->first);
876
877 if(queryObject->second)
878 {
879 queryObject->second->release();
880 }
881
882 mQueryMap.erase(queryObject);
883 }
884}
885
John Bauman89401822014-05-06 15:04:28 -0400886Buffer *Context::getBuffer(GLuint handle)
887{
888 return mResourceManager->getBuffer(handle);
889}
890
891Shader *Context::getShader(GLuint handle)
892{
893 return mResourceManager->getShader(handle);
894}
895
896Program *Context::getProgram(GLuint handle)
897{
898 return mResourceManager->getProgram(handle);
899}
900
901Texture *Context::getTexture(GLuint handle)
902{
903 return mResourceManager->getTexture(handle);
904}
905
906Renderbuffer *Context::getRenderbuffer(GLuint handle)
907{
908 return mResourceManager->getRenderbuffer(handle);
909}
910
911Framebuffer *Context::getReadFramebuffer()
912{
913 return getFramebuffer(mState.readFramebuffer);
914}
915
916Framebuffer *Context::getDrawFramebuffer()
917{
918 return getFramebuffer(mState.drawFramebuffer);
919}
920
921void Context::bindArrayBuffer(unsigned int buffer)
922{
923 mResourceManager->checkBufferAllocation(buffer);
924
925 mState.arrayBuffer.set(getBuffer(buffer));
926}
927
928void Context::bindElementArrayBuffer(unsigned int buffer)
929{
930 mResourceManager->checkBufferAllocation(buffer);
931
932 mState.elementArrayBuffer.set(getBuffer(buffer));
933}
934
935void Context::bindTexture2D(GLuint texture)
936{
937 mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
938
939 mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
940}
941
942void Context::bindTextureCubeMap(GLuint texture)
943{
944 mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
945
946 mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
947}
948
949void Context::bindReadFramebuffer(GLuint framebuffer)
950{
951 if(!getFramebuffer(framebuffer))
952 {
953 mFramebufferMap[framebuffer] = new Framebuffer();
954 }
955
956 mState.readFramebuffer = framebuffer;
957}
958
959void Context::bindDrawFramebuffer(GLuint framebuffer)
960{
961 if(!getFramebuffer(framebuffer))
962 {
963 mFramebufferMap[framebuffer] = new Framebuffer();
964 }
965
966 mState.drawFramebuffer = framebuffer;
967}
968
969void Context::bindRenderbuffer(GLuint renderbuffer)
970{
971 mResourceManager->checkRenderbufferAllocation(renderbuffer);
972
973 mState.renderbuffer.set(getRenderbuffer(renderbuffer));
974}
975
976void Context::useProgram(GLuint program)
977{
978 GLuint priorProgram = mState.currentProgram;
979 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
980
981 if(priorProgram != program)
982 {
983 Program *newProgram = mResourceManager->getProgram(program);
984 Program *oldProgram = mResourceManager->getProgram(priorProgram);
985
986 if(newProgram)
987 {
988 newProgram->addRef();
989 }
990
991 if(oldProgram)
992 {
993 oldProgram->release();
994 }
995 }
996}
997
John Bauman19bac1e2014-05-06 15:23:49 -0400998void Context::beginQuery(GLenum target, GLuint query)
999{
1000 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1001 // of zero, if the active query object name for <target> is non-zero (for the
1002 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1003 // the active query for either target is non-zero), if <id> is the name of an
1004 // existing query object whose type does not match <target>, or if <id> is the
1005 // active query object name for any query type, the error INVALID_OPERATION is
1006 // generated.
1007
1008 // Ensure no other queries are active
1009 // NOTE: If other queries than occlusion are supported, we will need to check
1010 // separately that:
1011 // a) The query ID passed is not the current active query for any target/type
1012 // b) There are no active queries for the requested target (and in the case
1013 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1014 // no query may be active for either if glBeginQuery targets either.
1015 for(int i = 0; i < QUERY_TYPE_COUNT; i++)
1016 {
1017 if(mState.activeQuery[i].get() != NULL)
1018 {
1019 return error(GL_INVALID_OPERATION);
1020 }
1021 }
1022
1023 QueryType qType;
1024 switch(target)
1025 {
1026 case GL_ANY_SAMPLES_PASSED_EXT:
1027 qType = QUERY_ANY_SAMPLES_PASSED;
1028 break;
1029 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1030 qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
1031 break;
1032 default:
1033 ASSERT(false);
1034 }
1035
1036 Query *queryObject = getQuery(query, true, target);
1037
1038 // Check that name was obtained with glGenQueries
1039 if(!queryObject)
1040 {
1041 return error(GL_INVALID_OPERATION);
1042 }
1043
1044 // Check for type mismatch
1045 if(queryObject->getType() != target)
1046 {
1047 return error(GL_INVALID_OPERATION);
1048 }
1049
1050 // Set query as active for specified target
1051 mState.activeQuery[qType].set(queryObject);
1052
1053 // Begin query
1054 queryObject->begin();
1055}
1056
1057void Context::endQuery(GLenum target)
1058{
1059 QueryType qType;
1060
1061 switch(target)
1062 {
1063 case GL_ANY_SAMPLES_PASSED_EXT:
1064 qType = QUERY_ANY_SAMPLES_PASSED;
1065 break;
1066 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1067 qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
1068 break;
1069 default:
1070 ASSERT(false);
1071 }
1072
1073 Query *queryObject = mState.activeQuery[qType].get();
1074
1075 if(queryObject == NULL)
1076 {
1077 return error(GL_INVALID_OPERATION);
1078 }
1079
1080 queryObject->end();
1081
1082 mState.activeQuery[qType].set(NULL);
1083}
1084
John Bauman89401822014-05-06 15:04:28 -04001085void Context::setFramebufferZero(Framebuffer *buffer)
1086{
1087 delete mFramebufferMap[0];
1088 mFramebufferMap[0] = buffer;
1089}
1090
1091void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
1092{
1093 Renderbuffer *renderbufferObject = mState.renderbuffer.get();
1094 renderbufferObject->setStorage(renderbuffer);
1095}
1096
1097Framebuffer *Context::getFramebuffer(unsigned int handle)
1098{
1099 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
1100
1101 if(framebuffer == mFramebufferMap.end())
1102 {
1103 return NULL;
1104 }
1105 else
1106 {
1107 return framebuffer->second;
1108 }
1109}
1110
1111Fence *Context::getFence(unsigned int handle)
1112{
1113 FenceMap::iterator fence = mFenceMap.find(handle);
1114
1115 if(fence == mFenceMap.end())
1116 {
1117 return NULL;
1118 }
1119 else
1120 {
1121 return fence->second;
1122 }
1123}
1124
John Bauman19bac1e2014-05-06 15:23:49 -04001125Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
1126{
1127 QueryMap::iterator query = mQueryMap.find(handle);
1128
1129 if(query == mQueryMap.end())
1130 {
1131 return NULL;
1132 }
1133 else
1134 {
1135 if(!query->second && create)
1136 {
1137 query->second = new Query(handle, type);
1138 query->second->addRef();
1139 }
1140
1141 return query->second;
1142 }
1143}
1144
John Bauman89401822014-05-06 15:04:28 -04001145Buffer *Context::getArrayBuffer()
1146{
1147 return mState.arrayBuffer.get();
1148}
1149
1150Buffer *Context::getElementArrayBuffer()
1151{
1152 return mState.elementArrayBuffer.get();
1153}
1154
1155Program *Context::getCurrentProgram()
1156{
1157 return mResourceManager->getProgram(mState.currentProgram);
1158}
1159
1160Texture2D *Context::getTexture2D()
1161{
1162 return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
1163}
1164
1165TextureCubeMap *Context::getTextureCubeMap()
1166{
1167 return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
1168}
1169
1170Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
1171{
1172 GLuint texid = mState.samplerTexture[type][sampler].id();
1173
1174 if(texid == 0) // Special case: 0 refers to different initial textures based on the target
1175 {
1176 switch (type)
1177 {
1178 default: UNREACHABLE();
1179 case TEXTURE_2D: return mTexture2DZero.get();
1180 case TEXTURE_CUBE: return mTextureCubeMapZero.get();
1181 }
1182 }
1183
1184 return mState.samplerTexture[type][sampler].get();
1185}
1186
1187bool Context::getBooleanv(GLenum pname, GLboolean *params)
1188{
1189 switch (pname)
1190 {
1191 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1192 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1193 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
1194 case GL_COLOR_WRITEMASK:
1195 params[0] = mState.colorMaskRed;
1196 params[1] = mState.colorMaskGreen;
1197 params[2] = mState.colorMaskBlue;
1198 params[3] = mState.colorMaskAlpha;
1199 break;
1200 case GL_CULL_FACE: *params = mState.cullFace; break;
1201 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break;
1202 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break;
1203 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break;
1204 case GL_SCISSOR_TEST: *params = mState.scissorTest; break;
1205 case GL_STENCIL_TEST: *params = mState.stencilTest; break;
1206 case GL_DEPTH_TEST: *params = mState.depthTest; break;
1207 case GL_BLEND: *params = mState.blend; break;
1208 case GL_DITHER: *params = mState.dither; break;
1209 default:
1210 return false;
1211 }
1212
1213 return true;
1214}
1215
1216bool Context::getFloatv(GLenum pname, GLfloat *params)
1217{
1218 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1219 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1220 // GetIntegerv as its native query function. As it would require conversion in any
1221 // case, this should make no difference to the calling application.
1222 switch (pname)
1223 {
1224 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1225 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1226 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1227 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1228 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
1229 case GL_ALIASED_LINE_WIDTH_RANGE:
1230 params[0] = ALIASED_LINE_WIDTH_RANGE_MIN;
1231 params[1] = ALIASED_LINE_WIDTH_RANGE_MAX;
1232 break;
1233 case GL_ALIASED_POINT_SIZE_RANGE:
1234 params[0] = ALIASED_POINT_SIZE_RANGE_MIN;
1235 params[1] = ALIASED_POINT_SIZE_RANGE_MAX;
1236 break;
1237 case GL_DEPTH_RANGE:
1238 params[0] = mState.zNear;
1239 params[1] = mState.zFar;
1240 break;
1241 case GL_COLOR_CLEAR_VALUE:
1242 params[0] = mState.colorClearValue.red;
1243 params[1] = mState.colorClearValue.green;
1244 params[2] = mState.colorClearValue.blue;
1245 params[3] = mState.colorClearValue.alpha;
1246 break;
1247 case GL_BLEND_COLOR:
1248 params[0] = mState.blendColor.red;
1249 params[1] = mState.blendColor.green;
1250 params[2] = mState.blendColor.blue;
1251 params[3] = mState.blendColor.alpha;
1252 break;
1253 default:
1254 return false;
1255 }
1256
1257 return true;
1258}
1259
1260bool Context::getIntegerv(GLenum pname, GLint *params)
1261{
1262 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1263 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1264 // GetIntegerv as its native query function. As it would require conversion in any
1265 // case, this should make no difference to the calling application. You may find it in
1266 // Context::getFloatv.
1267 switch (pname)
1268 {
1269 case GL_MAX_VERTEX_ATTRIBS: *params = MAX_VERTEX_ATTRIBS; break;
1270 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = MAX_VERTEX_UNIFORM_VECTORS; break;
1271 case GL_MAX_VARYING_VECTORS: *params = MAX_VARYING_VECTORS; break;
1272 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1273 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1274 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = MAX_TEXTURE_IMAGE_UNITS; break;
1275 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = MAX_FRAGMENT_UNIFORM_VECTORS; break;
1276 case GL_MAX_RENDERBUFFER_SIZE: *params = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE; break;
1277 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1278 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
1279 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break;
1280 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break;
1281// case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
1282 case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break;
1283 case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break;
1284 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break;
1285 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1286 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1287 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1288 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1289 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
1290 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
1291 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1292 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1293 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1294 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1295 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1296 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1297 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1298 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1299 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1300 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1301 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1302 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1303 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1304 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1305 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1306 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1307 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1308 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1309 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1310 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1311 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1312 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
1313 case GL_SUBPIXEL_BITS: *params = 4; break;
1314 case GL_MAX_TEXTURE_SIZE: *params = IMPLEMENTATION_MAX_TEXTURE_SIZE; break;
1315 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE; break;
1316 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1317 {
1318 if(S3TC_SUPPORT)
1319 {
John Bauman19bac1e2014-05-06 15:23:49 -04001320 // GL_COMPRESSED_RGB_S3TC_DXT1_EXT
1321 // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
1322 // GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE
1323 // GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE
1324 *params = 4;
John Bauman89401822014-05-06 15:04:28 -04001325 }
1326 else
1327 {
1328 *params = 0;
1329 }
1330 }
1331 break;
1332 case GL_MAX_SAMPLES_ANGLE: *params = IMPLEMENTATION_MAX_SAMPLES; break;
1333 case GL_SAMPLE_BUFFERS:
1334 case GL_SAMPLES:
1335 {
1336 Framebuffer *framebuffer = getDrawFramebuffer();
1337 if(framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
1338 {
1339 switch (pname)
1340 {
1341 case GL_SAMPLE_BUFFERS:
1342 if(framebuffer->getSamples() != 0)
1343 {
1344 *params = 1;
1345 }
1346 else
1347 {
1348 *params = 0;
1349 }
1350 break;
1351 case GL_SAMPLES:
1352 *params = framebuffer->getSamples();
1353 break;
1354 }
1355 }
1356 else
1357 {
1358 *params = 0;
1359 }
1360 }
1361 break;
1362 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = IMPLEMENTATION_COLOR_READ_TYPE; break;
1363 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = IMPLEMENTATION_COLOR_READ_FORMAT; break;
1364 case GL_MAX_VIEWPORT_DIMS:
1365 {
1366 int maxDimension = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE;
1367 params[0] = maxDimension;
1368 params[1] = maxDimension;
1369 }
1370 break;
1371 case GL_COMPRESSED_TEXTURE_FORMATS:
1372 {
1373 if(S3TC_SUPPORT)
1374 {
1375 params[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
1376 params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
John Bauman19bac1e2014-05-06 15:23:49 -04001377 params[2] = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
1378 params[3] = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
John Bauman89401822014-05-06 15:04:28 -04001379 }
1380 }
1381 break;
1382 case GL_VIEWPORT:
1383 params[0] = mState.viewportX;
1384 params[1] = mState.viewportY;
1385 params[2] = mState.viewportWidth;
1386 params[3] = mState.viewportHeight;
1387 break;
1388 case GL_SCISSOR_BOX:
1389 params[0] = mState.scissorX;
1390 params[1] = mState.scissorY;
1391 params[2] = mState.scissorWidth;
1392 params[3] = mState.scissorHeight;
1393 break;
1394 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1395 case GL_FRONT_FACE: *params = mState.frontFace; break;
1396 case GL_RED_BITS:
1397 case GL_GREEN_BITS:
1398 case GL_BLUE_BITS:
1399 case GL_ALPHA_BITS:
1400 {
1401 Framebuffer *framebuffer = getDrawFramebuffer();
1402 Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1403
1404 if(colorbuffer)
1405 {
1406 switch (pname)
1407 {
1408 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1409 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1410 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1411 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1412 }
1413 }
1414 else
1415 {
1416 *params = 0;
1417 }
1418 }
1419 break;
1420 case GL_DEPTH_BITS:
1421 {
1422 Framebuffer *framebuffer = getDrawFramebuffer();
1423 DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
1424
1425 if(depthbuffer)
1426 {
1427 *params = depthbuffer->getDepthSize();
1428 }
1429 else
1430 {
1431 *params = 0;
1432 }
1433 }
1434 break;
1435 case GL_STENCIL_BITS:
1436 {
1437 Framebuffer *framebuffer = getDrawFramebuffer();
1438 DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1439
1440 if(stencilbuffer)
1441 {
1442 *params = stencilbuffer->getStencilSize();
1443 }
1444 else
1445 {
1446 *params = 0;
1447 }
1448 }
1449 break;
1450 case GL_TEXTURE_BINDING_2D:
1451 {
1452 if(mState.activeSampler < 0 || mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
1453 {
1454 error(GL_INVALID_OPERATION);
1455 return false;
1456 }
1457
1458 *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();
1459 }
1460 break;
1461 case GL_TEXTURE_BINDING_CUBE_MAP:
1462 {
1463 if(mState.activeSampler < 0 || mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
1464 {
1465 error(GL_INVALID_OPERATION);
1466 return false;
1467 }
1468
1469 *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
1470 }
1471 break;
1472 default:
1473 return false;
1474 }
1475
1476 return true;
1477}
1478
1479bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1480{
1481 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1482 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1483 // to the fact that it is stored internally as a float, and so would require conversion
1484 // if returned from Context::getIntegerv. Since this conversion is already implemented
1485 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1486 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1487 // application.
1488 switch (pname)
1489 {
John Bauman19bac1e2014-05-06 15:23:49 -04001490 case GL_COMPRESSED_TEXTURE_FORMATS:
1491 {
1492 *type = GL_INT;
1493 *numParams = S3TC_SUPPORT ? 4 : 0;
1494 }
1495 break;
John Bauman89401822014-05-06 15:04:28 -04001496 case GL_SHADER_BINARY_FORMATS:
1497 {
1498 *type = GL_INT;
1499 *numParams = 0;
1500 }
1501 break;
1502 case GL_MAX_VERTEX_ATTRIBS:
1503 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1504 case GL_MAX_VARYING_VECTORS:
1505 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1506 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1507 case GL_MAX_TEXTURE_IMAGE_UNITS:
1508 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1509 case GL_MAX_RENDERBUFFER_SIZE:
1510 case GL_NUM_SHADER_BINARY_FORMATS:
1511 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1512 case GL_ARRAY_BUFFER_BINDING:
1513 case GL_FRAMEBUFFER_BINDING:
1514 case GL_RENDERBUFFER_BINDING:
1515 case GL_CURRENT_PROGRAM:
1516 case GL_PACK_ALIGNMENT:
1517 case GL_UNPACK_ALIGNMENT:
1518 case GL_GENERATE_MIPMAP_HINT:
1519 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
1520 case GL_RED_BITS:
1521 case GL_GREEN_BITS:
1522 case GL_BLUE_BITS:
1523 case GL_ALPHA_BITS:
1524 case GL_DEPTH_BITS:
1525 case GL_STENCIL_BITS:
1526 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1527 case GL_CULL_FACE_MODE:
1528 case GL_FRONT_FACE:
1529 case GL_ACTIVE_TEXTURE:
1530 case GL_STENCIL_FUNC:
1531 case GL_STENCIL_VALUE_MASK:
1532 case GL_STENCIL_REF:
1533 case GL_STENCIL_FAIL:
1534 case GL_STENCIL_PASS_DEPTH_FAIL:
1535 case GL_STENCIL_PASS_DEPTH_PASS:
1536 case GL_STENCIL_BACK_FUNC:
1537 case GL_STENCIL_BACK_VALUE_MASK:
1538 case GL_STENCIL_BACK_REF:
1539 case GL_STENCIL_BACK_FAIL:
1540 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1541 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1542 case GL_DEPTH_FUNC:
1543 case GL_BLEND_SRC_RGB:
1544 case GL_BLEND_SRC_ALPHA:
1545 case GL_BLEND_DST_RGB:
1546 case GL_BLEND_DST_ALPHA:
1547 case GL_BLEND_EQUATION_RGB:
1548 case GL_BLEND_EQUATION_ALPHA:
1549 case GL_STENCIL_WRITEMASK:
1550 case GL_STENCIL_BACK_WRITEMASK:
1551 case GL_STENCIL_CLEAR_VALUE:
1552 case GL_SUBPIXEL_BITS:
1553 case GL_MAX_TEXTURE_SIZE:
1554 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1555 case GL_SAMPLE_BUFFERS:
1556 case GL_SAMPLES:
1557 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1558 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1559 case GL_TEXTURE_BINDING_2D:
1560 case GL_TEXTURE_BINDING_CUBE_MAP:
1561 {
1562 *type = GL_INT;
1563 *numParams = 1;
1564 }
1565 break;
1566 case GL_MAX_SAMPLES_ANGLE:
1567 {
1568 *type = GL_INT;
1569 *numParams = 1;
1570 }
1571 break;
1572 case GL_MAX_VIEWPORT_DIMS:
1573 {
1574 *type = GL_INT;
1575 *numParams = 2;
1576 }
1577 break;
1578 case GL_VIEWPORT:
1579 case GL_SCISSOR_BOX:
1580 {
1581 *type = GL_INT;
1582 *numParams = 4;
1583 }
1584 break;
1585 case GL_SHADER_COMPILER:
1586 case GL_SAMPLE_COVERAGE_INVERT:
1587 case GL_DEPTH_WRITEMASK:
1588 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1589 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1590 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1591 case GL_SAMPLE_COVERAGE:
1592 case GL_SCISSOR_TEST:
1593 case GL_STENCIL_TEST:
1594 case GL_DEPTH_TEST:
1595 case GL_BLEND:
1596 case GL_DITHER:
1597 {
1598 *type = GL_BOOL;
1599 *numParams = 1;
1600 }
1601 break;
1602 case GL_COLOR_WRITEMASK:
1603 {
1604 *type = GL_BOOL;
1605 *numParams = 4;
1606 }
1607 break;
1608 case GL_POLYGON_OFFSET_FACTOR:
1609 case GL_POLYGON_OFFSET_UNITS:
1610 case GL_SAMPLE_COVERAGE_VALUE:
1611 case GL_DEPTH_CLEAR_VALUE:
1612 case GL_LINE_WIDTH:
1613 {
1614 *type = GL_FLOAT;
1615 *numParams = 1;
1616 }
1617 break;
1618 case GL_ALIASED_LINE_WIDTH_RANGE:
1619 case GL_ALIASED_POINT_SIZE_RANGE:
1620 case GL_DEPTH_RANGE:
1621 {
1622 *type = GL_FLOAT;
1623 *numParams = 2;
1624 }
1625 break;
1626 case GL_COLOR_CLEAR_VALUE:
1627 case GL_BLEND_COLOR:
1628 {
1629 *type = GL_FLOAT;
1630 *numParams = 4;
1631 }
1632 break;
1633 default:
1634 return false;
1635 }
1636
1637 return true;
1638}
1639
1640// Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle
John Bauman19bac1e2014-05-06 15:23:49 -04001641bool Context::applyRenderTarget()
John Bauman89401822014-05-06 15:04:28 -04001642{
1643 Device *device = getDevice();
1644
1645 Framebuffer *framebufferObject = getDrawFramebuffer();
1646
1647 if(!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1648 {
1649 return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
1650 }
1651
1652 Image *renderTarget = framebufferObject->getRenderTarget();
1653
1654 if(!renderTarget)
1655 {
John Bauman19bac1e2014-05-06 15:23:49 -04001656 return false;
John Bauman89401822014-05-06 15:04:28 -04001657 }
1658
John Bauman19bac1e2014-05-06 15:23:49 -04001659 device->setRenderTarget(renderTarget);
1660 renderTarget->release();
1661
John Bauman89401822014-05-06 15:04:28 -04001662 Image *depthStencil = NULL;
1663
John Bauman89401822014-05-06 15:04:28 -04001664 if(framebufferObject->getDepthbufferType() != GL_NONE)
1665 {
1666 depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil();
1667 if(!depthStencil)
1668 {
1669 ERR("Depth stencil pointer unexpectedly null.");
1670 return false;
1671 }
John Bauman89401822014-05-06 15:04:28 -04001672 }
1673 else if(framebufferObject->getStencilbufferType() != GL_NONE)
1674 {
1675 depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
1676 if(!depthStencil)
1677 {
1678 ERR("Depth stencil pointer unexpectedly null.");
1679 return false;
1680 }
John Bauman89401822014-05-06 15:04:28 -04001681 }
1682
John Bauman19bac1e2014-05-06 15:23:49 -04001683 device->setDepthStencilSurface(depthStencil);
John Bauman89401822014-05-06 15:04:28 -04001684
1685 Viewport viewport;
John Bauman89401822014-05-06 15:04:28 -04001686 float zNear = clamp01(mState.zNear);
1687 float zFar = clamp01(mState.zFar);
1688
John Bauman19bac1e2014-05-06 15:23:49 -04001689 viewport.x0 = mState.viewportX;
1690 viewport.y0 = mState.viewportY;
1691 viewport.width = mState.viewportWidth;
1692 viewport.height = mState.viewportHeight;
1693 viewport.minZ = zNear;
1694 viewport.maxZ = zFar;
John Bauman89401822014-05-06 15:04:28 -04001695
1696 device->setViewport(viewport);
1697
John Bauman19bac1e2014-05-06 15:23:49 -04001698 if(mState.scissorTest)
John Bauman89401822014-05-06 15:04:28 -04001699 {
John Bauman19bac1e2014-05-06 15:23:49 -04001700 sw::Rect scissor = {mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight};
1701 scissor.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight());
1702
1703 device->setScissorRect(scissor);
1704 device->setScissorEnable(true);
1705 }
1706 else
1707 {
1708 device->setScissorEnable(false);
John Bauman89401822014-05-06 15:04:28 -04001709 }
1710
John Bauman19bac1e2014-05-06 15:23:49 -04001711 Program *program = getCurrentProgram();
John Bauman89401822014-05-06 15:04:28 -04001712
John Bauman19bac1e2014-05-06 15:23:49 -04001713 if(program)
1714 {
1715 GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};
1716 program->setUniform1fv(program->getUniformLocation("gl_DepthRange.near"), 1, &nearFarDiff[0]);
1717 program->setUniform1fv(program->getUniformLocation("gl_DepthRange.far"), 1, &nearFarDiff[1]);
1718 program->setUniform1fv(program->getUniformLocation("gl_DepthRange.diff"), 1, &nearFarDiff[2]);
John Bauman89401822014-05-06 15:04:28 -04001719 }
1720
1721 return true;
1722}
1723
1724// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc)
1725void Context::applyState(GLenum drawMode)
1726{
1727 Device *device = getDevice();
1728 Program *programObject = getCurrentProgram();
1729
1730 Framebuffer *framebufferObject = getDrawFramebuffer();
1731
John Bauman19bac1e2014-05-06 15:23:49 -04001732 if(mState.cullFace)
John Bauman89401822014-05-06 15:04:28 -04001733 {
John Bauman19bac1e2014-05-06 15:23:49 -04001734 device->setCullMode(es2sw::ConvertCullMode(mState.cullMode, mState.frontFace));
1735 }
1736 else
1737 {
1738 device->setCullMode(sw::Context::CULL_NONE);
John Bauman89401822014-05-06 15:04:28 -04001739 }
1740
1741 if(mDepthStateDirty)
1742 {
1743 if(mState.depthTest)
1744 {
1745 device->setDepthBufferEnable(true);
1746 device->setDepthCompare(es2sw::ConvertDepthComparison(mState.depthFunc));
1747 }
1748 else
1749 {
1750 device->setDepthBufferEnable(false);
1751 }
1752
1753 mDepthStateDirty = false;
1754 }
1755
1756 if(mBlendStateDirty)
1757 {
1758 if(mState.blend)
1759 {
1760 device->setAlphaBlendEnable(true);
1761 device->setSeparateAlphaBlendEnable(true);
1762
1763 device->setBlendConstant(es2sw::ConvertColor(mState.blendColor));
1764
1765 device->setSourceBlendFactor(es2sw::ConvertBlendFunc(mState.sourceBlendRGB));
1766 device->setDestBlendFactor(es2sw::ConvertBlendFunc(mState.destBlendRGB));
1767 device->setBlendOperation(es2sw::ConvertBlendOp(mState.blendEquationRGB));
1768
1769 device->setSourceBlendFactorAlpha(es2sw::ConvertBlendFunc(mState.sourceBlendAlpha));
1770 device->setDestBlendFactorAlpha(es2sw::ConvertBlendFunc(mState.destBlendAlpha));
1771 device->setBlendOperationAlpha(es2sw::ConvertBlendOp(mState.blendEquationAlpha));
1772 }
1773 else
1774 {
1775 device->setAlphaBlendEnable(false);
1776 }
1777
1778 mBlendStateDirty = false;
1779 }
1780
1781 if(mStencilStateDirty || mFrontFaceDirty)
1782 {
1783 if(mState.stencilTest && framebufferObject->hasStencil())
1784 {
1785 device->setStencilEnable(true);
1786 device->setTwoSidedStencil(true);
1787
1788 if(mState.stencilWritemask != mState.stencilBackWritemask ||
1789 mState.stencilRef != mState.stencilBackRef ||
1790 mState.stencilMask != mState.stencilBackMask)
1791 {
1792 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1793 return error(GL_INVALID_OPERATION);
1794 }
1795
1796 // get the maximum size of the stencil ref
1797 DepthStencilbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
1798 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
1799
John Bauman19bac1e2014-05-06 15:23:49 -04001800 if(mState.frontFace == GL_CCW)
John Bauman89401822014-05-06 15:04:28 -04001801 {
1802 device->setStencilWriteMask(mState.stencilWritemask);
1803 device->setStencilCompare(es2sw::ConvertStencilComparison(mState.stencilFunc));
1804
1805 device->setStencilReference((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
1806 device->setStencilMask(mState.stencilMask);
1807
1808 device->setStencilFailOperation(es2sw::ConvertStencilOp(mState.stencilFail));
1809 device->setStencilZFailOperation(es2sw::ConvertStencilOp(mState.stencilPassDepthFail));
1810 device->setStencilPassOperation(es2sw::ConvertStencilOp(mState.stencilPassDepthPass));
1811
1812 device->setStencilWriteMaskCCW(mState.stencilBackWritemask);
1813 device->setStencilCompareCCW(es2sw::ConvertStencilComparison(mState.stencilBackFunc));
1814
1815 device->setStencilReferenceCCW((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
1816 device->setStencilMaskCCW(mState.stencilBackMask);
1817
1818 device->setStencilFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilBackFail));
1819 device->setStencilZFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilBackPassDepthFail));
1820 device->setStencilPassOperationCCW(es2sw::ConvertStencilOp(mState.stencilBackPassDepthPass));
1821 }
1822 else
1823 {
1824 device->setStencilWriteMaskCCW(mState.stencilWritemask);
1825 device->setStencilCompareCCW(es2sw::ConvertStencilComparison(mState.stencilFunc));
1826
1827 device->setStencilReferenceCCW((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
1828 device->setStencilMaskCCW(mState.stencilMask);
1829
1830 device->setStencilFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilFail));
1831 device->setStencilZFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilPassDepthFail));
1832 device->setStencilPassOperationCCW(es2sw::ConvertStencilOp(mState.stencilPassDepthPass));
1833
1834 device->setStencilWriteMask(mState.stencilBackWritemask);
1835 device->setStencilCompare(es2sw::ConvertStencilComparison(mState.stencilBackFunc));
1836
1837 device->setStencilReference((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
1838 device->setStencilMask(mState.stencilBackMask);
1839
1840 device->setStencilFailOperation(es2sw::ConvertStencilOp(mState.stencilBackFail));
1841 device->setStencilZFailOperation(es2sw::ConvertStencilOp(mState.stencilBackPassDepthFail));
1842 device->setStencilPassOperation(es2sw::ConvertStencilOp(mState.stencilBackPassDepthPass));
1843 }
1844 }
1845 else
1846 {
1847 device->setStencilEnable(false);
1848 }
1849
1850 mStencilStateDirty = false;
1851 mFrontFaceDirty = false;
1852 }
1853
1854 if(mMaskStateDirty)
1855 {
1856 device->setColorWriteMask(0, es2sw::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha));
1857 device->setDepthWriteEnable(mState.depthMask);
1858
1859 mMaskStateDirty = false;
1860 }
1861
1862 if(mPolygonOffsetStateDirty)
1863 {
1864 if(mState.polygonOffsetFill)
1865 {
1866 DepthStencilbuffer *depthbuffer = framebufferObject->getDepthbuffer();
1867 if(depthbuffer)
1868 {
1869 device->setSlopeDepthBias(mState.polygonOffsetFactor);
1870 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1871 device->setDepthBias(depthBias);
1872 }
1873 }
1874 else
1875 {
1876 device->setSlopeDepthBias(0);
1877 device->setDepthBias(0);
1878 }
1879
1880 mPolygonOffsetStateDirty = false;
1881 }
1882
1883 if(mSampleStateDirty)
1884 {
1885 if(mState.sampleAlphaToCoverage)
1886 {
1887 FIXME("Sample alpha to coverage is unimplemented.");
1888 }
1889
1890 if(mState.sampleCoverage)
1891 {
1892 unsigned int mask = 0;
1893 if(mState.sampleCoverageValue != 0)
1894 {
1895 float threshold = 0.5f;
1896
1897 for(int i = 0; i < framebufferObject->getSamples(); ++i)
1898 {
1899 mask <<= 1;
1900
1901 if((i + 1) * mState.sampleCoverageValue >= threshold)
1902 {
1903 threshold += 1.0f;
1904 mask |= 1;
1905 }
1906 }
1907 }
1908
1909 if(mState.sampleCoverageInvert)
1910 {
1911 mask = ~mask;
1912 }
1913
1914 device->setMultiSampleMask(mask);
1915 }
1916 else
1917 {
1918 device->setMultiSampleMask(0xFFFFFFFF);
1919 }
1920
1921 mSampleStateDirty = false;
1922 }
1923
1924 if(mDitherStateDirty)
1925 {
1926 // UNIMPLEMENTED(); // FIXME
1927
1928 mDitherStateDirty = false;
1929 }
1930}
1931
1932GLenum Context::applyVertexBuffer(GLint base, GLint first, GLsizei count)
1933{
1934 TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];
1935
1936 GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes);
1937 if(err != GL_NO_ERROR)
1938 {
1939 return err;
1940 }
1941
1942 Device *device = getDevice();
1943 Program *program = getCurrentProgram();
1944
1945 device->resetInputStreams(false);
1946
1947 for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
John Bauman19bac1e2014-05-06 15:23:49 -04001948 {
1949 if(program->getAttributeStream(i) == -1)
John Bauman89401822014-05-06 15:04:28 -04001950 {
1951 continue;
1952 }
1953
1954 sw::Resource *resource = attributes[i].vertexBuffer;
1955 const void *buffer = (char*)resource->getBuffer() + attributes[i].offset;
1956
1957 int stride = attributes[i].stride;
1958
1959 buffer = (char*)buffer + stride * base;
1960
1961 sw::Stream attribute(resource, buffer, stride);
1962
1963 attribute.type = attributes[i].type;
1964 attribute.count = attributes[i].count;
1965 attribute.normalized = attributes[i].normalized;
1966
John Bauman19bac1e2014-05-06 15:23:49 -04001967 int stream = program->getAttributeStream(i);
1968 device->setInputStream(stream, attribute);
John Bauman89401822014-05-06 15:04:28 -04001969 }
1970
1971 return GL_NO_ERROR;
1972}
1973
1974// Applies the indices and element array bindings
1975GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
1976{
1977 Device *device = getDevice();
1978 GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
1979
1980 if(err == GL_NO_ERROR)
1981 {
1982 device->setIndexBuffer(indexInfo->indexBuffer);
1983 }
1984
1985 return err;
1986}
1987
1988// Applies the shaders and shader constants
1989void Context::applyShaders()
1990{
1991 Device *device = getDevice();
1992 Program *programObject = getCurrentProgram();
1993 sw::VertexShader *vertexShader = programObject->getVertexShader();
John Bauman19bac1e2014-05-06 15:23:49 -04001994 sw::PixelShader *pixelShader = programObject->getPixelShader();
John Bauman89401822014-05-06 15:04:28 -04001995
1996 device->setVertexShader(vertexShader);
1997 device->setPixelShader(pixelShader);
1998
1999 if(programObject->getSerial() != mAppliedProgramSerial)
2000 {
2001 programObject->dirtyAllUniforms();
2002 mAppliedProgramSerial = programObject->getSerial();
2003 }
2004
2005 programObject->applyUniforms();
2006}
2007
John Bauman89401822014-05-06 15:04:28 -04002008void Context::applyTextures()
2009{
2010 applyTextures(sw::SAMPLER_PIXEL);
2011 applyTextures(sw::SAMPLER_VERTEX);
2012}
2013
John Bauman89401822014-05-06 15:04:28 -04002014void Context::applyTextures(sw::SamplerType samplerType)
2015{
2016 Device *device = getDevice();
2017 Program *programObject = getCurrentProgram();
2018
2019 int samplerCount = (samplerType == sw::SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS; // Range of samplers of given sampler type
2020
2021 for(int samplerIndex = 0; samplerIndex < samplerCount; samplerIndex++)
2022 {
2023 int textureUnit = programObject->getSamplerMapping(samplerType, samplerIndex); // OpenGL texture image unit index
2024
2025 if(textureUnit != -1)
2026 {
2027 TextureType textureType = programObject->getSamplerTextureType(samplerType, samplerIndex);
2028
2029 Texture *texture = getSamplerTexture(textureUnit, textureType);
2030
John Bauman19bac1e2014-05-06 15:23:49 -04002031 if(texture->isSamplerComplete())
John Bauman89401822014-05-06 15:04:28 -04002032 {
2033 GLenum wrapS = texture->getWrapS();
2034 GLenum wrapT = texture->getWrapT();
2035 GLenum texFilter = texture->getMinFilter();
2036 GLenum magFilter = texture->getMagFilter();
2037
2038 device->setAddressingModeU(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapS));
2039 device->setAddressingModeV(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapT));
2040
2041 sw::FilterType minFilter;
2042 sw::MipmapType mipFilter;
2043 es2sw::ConvertMinFilter(texFilter, &minFilter, &mipFilter);
2044 // ASSERT(minFilter == es2sw::ConvertMagFilter(magFilter));
2045
2046 device->setTextureFilter(samplerType, samplerIndex, minFilter);
2047 // device->setTextureFilter(samplerType, samplerIndex, es2sw::ConvertMagFilter(magFilter));
2048 device->setMipmapFilter(samplerType, samplerIndex, mipFilter);
2049
2050 applyTexture(samplerType, samplerIndex, texture);
2051 }
2052 else
2053 {
2054 applyTexture(samplerType, samplerIndex, 0);
2055 }
2056 }
2057 else
2058 {
2059 applyTexture(samplerType, samplerIndex, NULL);
2060 }
2061 }
2062}
2063
2064void Context::applyTexture(sw::SamplerType type, int index, Texture *baseTexture)
2065{
2066 Device *device = getDevice();
2067 Program *program = getCurrentProgram();
2068 int sampler = (type == sw::SAMPLER_PIXEL) ? index : 16 + index;
2069 bool textureUsed = false;
2070
2071 if(type == sw::SAMPLER_PIXEL)
2072 {
2073 textureUsed = program->getPixelShader()->usesSampler(index);
2074 }
2075 else if(type == sw::SAMPLER_VERTEX)
2076 {
John Bauman19bac1e2014-05-06 15:23:49 -04002077 textureUsed = program->getVertexShader()->usesSampler(index);
John Bauman89401822014-05-06 15:04:28 -04002078 }
2079 else
2080 {
2081 textureUsed = true; // FIXME: Check fixed-function use?
2082 }
2083
2084 sw::Resource *resource = 0;
2085
2086 if(baseTexture && textureUsed)
2087 {
2088 resource = baseTexture->getResource();
2089 }
2090
2091 device->setTextureResource(sampler, resource);
2092
2093 if(baseTexture && textureUsed)
2094 {
2095 int levelCount = baseTexture->getLevelCount();
2096
2097 if(baseTexture->isTexture2D())
2098 {
2099 Texture2D *texture = static_cast<Texture2D*>(baseTexture);
2100
2101 for(int mipmapLevel = 0; mipmapLevel < MIPMAP_LEVELS; mipmapLevel++)
2102 {
2103 int surfaceLevel = mipmapLevel;
2104
2105 if(surfaceLevel < 0)
2106 {
2107 surfaceLevel = 0;
2108 }
2109 else if(surfaceLevel >= levelCount)
2110 {
2111 surfaceLevel = levelCount - 1;
2112 }
2113
2114 Image *surface = texture->getImage(surfaceLevel);
2115 device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D);
2116 }
2117 }
2118 else if(baseTexture->isTextureCubeMap())
2119 {
2120 for(int face = 0; face < 6; face++)
2121 {
2122 TextureCubeMap *cubeTexture = static_cast<TextureCubeMap*>(baseTexture);
2123
2124 for(int mipmapLevel = 0; mipmapLevel < MIPMAP_LEVELS; mipmapLevel++)
2125 {
2126 int surfaceLevel = mipmapLevel;
2127
2128 if(surfaceLevel < 0)
2129 {
2130 surfaceLevel = 0;
2131 }
2132 else if(surfaceLevel >= levelCount)
2133 {
2134 surfaceLevel = levelCount - 1;
2135 }
2136
2137 Image *surface = cubeTexture->getImage((CubeFace)face, surfaceLevel);
2138 device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
2139 }
2140 }
2141 }
2142 else UNIMPLEMENTED();
2143 }
2144 else
2145 {
2146 device->setTextureLevel(sampler, 0, 0, 0, sw::TEXTURE_NULL);
2147 }
2148}
2149
John Bauman19bac1e2014-05-06 15:23:49 -04002150void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2151 GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
John Bauman89401822014-05-06 15:04:28 -04002152{
2153 Framebuffer *framebuffer = getReadFramebuffer();
2154
2155 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
2156 {
2157 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
2158 }
2159
2160 if(getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
2161 {
2162 return error(GL_INVALID_OPERATION);
2163 }
2164
John Bauman19bac1e2014-05-06 15:23:49 -04002165 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
2166
2167 // Sized query sanity check
2168 if(bufSize)
2169 {
2170 int requiredSize = outputPitch * height;
2171 if(requiredSize > *bufSize)
2172 {
2173 return error(GL_INVALID_OPERATION);
2174 }
2175 }
2176
John Bauman89401822014-05-06 15:04:28 -04002177 Image *renderTarget = framebuffer->getRenderTarget();
2178
2179 if(!renderTarget)
2180 {
John Bauman89401822014-05-06 15:04:28 -04002181 return error(GL_OUT_OF_MEMORY);
2182 }
2183
John Bauman19bac1e2014-05-06 15:23:49 -04002184 sw::Rect rect = {x, y, x + width, y + height};
2185 rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight());
John Bauman89401822014-05-06 15:04:28 -04002186
John Bauman19bac1e2014-05-06 15:23:49 -04002187 unsigned char *source = (unsigned char*)renderTarget->lock(rect.x0, rect.y0, sw::LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002188 unsigned char *dest = (unsigned char*)pixels;
2189 unsigned short *dest16 = (unsigned short*)pixels;
John Bauman19bac1e2014-05-06 15:23:49 -04002190 int inputPitch = (int)renderTarget->getPitch();
John Bauman89401822014-05-06 15:04:28 -04002191
John Bauman19bac1e2014-05-06 15:23:49 -04002192 for(int j = 0; j < rect.y1 - rect.y0; j++)
John Bauman89401822014-05-06 15:04:28 -04002193 {
2194 if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 &&
John Bauman19bac1e2014-05-06 15:23:49 -04002195 format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE)
John Bauman89401822014-05-06 15:04:28 -04002196 {
John Bauman19bac1e2014-05-06 15:23:49 -04002197 // Fast path for EXT_read_format_bgra, given an RGBA source buffer
2198 // Note that buffers with no alpha go through the slow path below
2199 memcpy(dest + j * outputPitch, source + j * inputPitch, (rect.x1 - rect.x0) * 4);
John Bauman89401822014-05-06 15:04:28 -04002200 }
2201 else
2202 {
John Bauman19bac1e2014-05-06 15:23:49 -04002203 for(int i = 0; i < rect.x1 - rect.x0; i++)
John Bauman89401822014-05-06 15:04:28 -04002204 {
2205 float r;
2206 float g;
2207 float b;
2208 float a;
2209
2210 switch(renderTarget->getInternalFormat())
2211 {
2212 case sw::FORMAT_R5G6B5:
2213 {
2214 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
2215
2216 a = 1.0f;
2217 b = (rgb & 0x001F) * (1.0f / 0x001F);
2218 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2219 r = (rgb & 0xF800) * (1.0f / 0xF800);
2220 }
2221 break;
2222 case sw::FORMAT_A1R5G5B5:
2223 {
2224 unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
2225
2226 a = (argb & 0x8000) ? 1.0f : 0.0f;
2227 b = (argb & 0x001F) * (1.0f / 0x001F);
2228 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2229 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2230 }
2231 break;
2232 case sw::FORMAT_A8R8G8B8:
2233 {
2234 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
2235
2236 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2237 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2238 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2239 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2240 }
2241 break;
2242 case sw::FORMAT_X8R8G8B8:
2243 {
2244 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
2245
2246 a = 1.0f;
2247 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2248 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2249 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2250 }
2251 break;
2252 case sw::FORMAT_A2R10G10B10:
2253 {
2254 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
2255
2256 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2257 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2258 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2259 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2260 }
2261 break;
2262 case sw::FORMAT_A32B32G32R32F:
2263 {
2264 r = *((float*)(source + 16 * i + j * inputPitch) + 0);
2265 g = *((float*)(source + 16 * i + j * inputPitch) + 1);
2266 b = *((float*)(source + 16 * i + j * inputPitch) + 2);
2267 a = *((float*)(source + 16 * i + j * inputPitch) + 3);
2268 }
2269 break;
2270 case sw::FORMAT_A16B16G16R16F:
2271 {
2272 r = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 0);
2273 g = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 1);
2274 b = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 2);
2275 a = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 3);
2276 }
2277 break;
2278 default:
2279 UNIMPLEMENTED(); // FIXME
2280 UNREACHABLE();
2281 }
2282
John Bauman19bac1e2014-05-06 15:23:49 -04002283 switch(format)
John Bauman89401822014-05-06 15:04:28 -04002284 {
2285 case GL_RGBA:
John Bauman19bac1e2014-05-06 15:23:49 -04002286 switch(type)
John Bauman89401822014-05-06 15:04:28 -04002287 {
2288 case GL_UNSIGNED_BYTE:
2289 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2290 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2291 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2292 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
2293 break;
2294 default: UNREACHABLE();
2295 }
2296 break;
2297 case GL_BGRA_EXT:
John Bauman19bac1e2014-05-06 15:23:49 -04002298 switch(type)
John Bauman89401822014-05-06 15:04:28 -04002299 {
2300 case GL_UNSIGNED_BYTE:
2301 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
2302 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2303 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
2304 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
2305 break;
2306 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
2307 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
2308 // this type is packed as follows:
2309 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
2310 // --------------------------------------------------------------------------------
2311 // | 4th | 3rd | 2nd | 1st component |
2312 // --------------------------------------------------------------------------------
2313 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
2314 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2315 ((unsigned short)(15 * a + 0.5f) << 12)|
2316 ((unsigned short)(15 * r + 0.5f) << 8) |
2317 ((unsigned short)(15 * g + 0.5f) << 4) |
2318 ((unsigned short)(15 * b + 0.5f) << 0);
2319 break;
2320 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
2321 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
2322 // this type is packed as follows:
2323 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
2324 // --------------------------------------------------------------------------------
2325 // | 4th | 3rd | 2nd | 1st component |
2326 // --------------------------------------------------------------------------------
2327 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
2328 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2329 ((unsigned short)( a + 0.5f) << 15) |
2330 ((unsigned short)(31 * r + 0.5f) << 10) |
2331 ((unsigned short)(31 * g + 0.5f) << 5) |
2332 ((unsigned short)(31 * b + 0.5f) << 0);
2333 break;
2334 default: UNREACHABLE();
2335 }
2336 break;
2337 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
John Bauman19bac1e2014-05-06 15:23:49 -04002338 switch(type)
John Bauman89401822014-05-06 15:04:28 -04002339 {
2340 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
2341 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2342 ((unsigned short)(31 * b + 0.5f) << 0) |
2343 ((unsigned short)(63 * g + 0.5f) << 5) |
2344 ((unsigned short)(31 * r + 0.5f) << 11);
2345 break;
2346 default: UNREACHABLE();
2347 }
2348 break;
2349 default: UNREACHABLE();
2350 }
2351 }
2352 }
2353 }
2354
John Bauman19bac1e2014-05-06 15:23:49 -04002355 renderTarget->unlock();
2356 renderTarget->release();
John Bauman89401822014-05-06 15:04:28 -04002357}
2358
2359void Context::clear(GLbitfield mask)
2360{
2361 Framebuffer *framebufferObject = getDrawFramebuffer();
2362
2363 if(!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2364 {
2365 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
2366 }
2367
John Bauman19bac1e2014-05-06 15:23:49 -04002368 if(!applyRenderTarget())
John Bauman89401822014-05-06 15:04:28 -04002369 {
2370 return;
2371 }
2372
John Bauman19bac1e2014-05-06 15:23:49 -04002373 Device *device = getDevice();
2374
John Bauman89401822014-05-06 15:04:28 -04002375 unsigned int color = (unorm<8>(mState.colorClearValue.alpha) << 24) |
2376 (unorm<8>(mState.colorClearValue.red) << 16) |
2377 (unorm<8>(mState.colorClearValue.green) << 8) |
2378 (unorm<8>(mState.colorClearValue.blue) << 0);
2379 float depth = clamp01(mState.depthClearValue);
2380 int stencil = mState.stencilClearValue & 0x000000FF;
2381
2382 if(mask & GL_COLOR_BUFFER_BIT)
2383 {
2384 unsigned int rgbaMask = (mState.colorMaskRed ? 0x1 : 0) |
2385 (mState.colorMaskGreen ? 0x2 : 0) |
2386 (mState.colorMaskBlue ? 0x4 : 0) |
2387 (mState.colorMaskAlpha ? 0x8 : 0);
2388 device->clearColor(color, rgbaMask);
2389 }
2390
2391 if(mask & GL_DEPTH_BUFFER_BIT)
2392 {
2393 if(mState.depthMask)
2394 {
2395 device->clearDepth(depth);
2396 }
2397 }
2398
2399 if(mask & GL_STENCIL_BUFFER_BIT)
2400 {
2401 device->clearStencil(stencil, mState.stencilWritemask);
2402 }
2403}
2404
2405void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2406{
2407 if(!mState.currentProgram)
2408 {
2409 return error(GL_INVALID_OPERATION);
2410 }
2411
John Bauman89401822014-05-06 15:04:28 -04002412 Device *device = getDevice();
2413 PrimitiveType primitiveType;
2414 int primitiveCount;
2415
2416 if(!es2sw::ConvertPrimitiveType(mode, count, primitiveType, primitiveCount))
2417 return error(GL_INVALID_ENUM);
2418
2419 if(primitiveCount <= 0)
2420 {
2421 return;
2422 }
2423
John Bauman19bac1e2014-05-06 15:23:49 -04002424 if(!applyRenderTarget())
John Bauman89401822014-05-06 15:04:28 -04002425 {
2426 return;
2427 }
2428
2429 applyState(mode);
2430
2431 GLenum err = applyVertexBuffer(0, first, count);
2432 if(err != GL_NO_ERROR)
2433 {
2434 return error(err);
2435 }
2436
2437 applyShaders();
2438 applyTextures();
2439
2440 if(!getCurrentProgram()->validateSamplers(false))
2441 {
2442 return error(GL_INVALID_OPERATION);
2443 }
2444
2445 if(!cullSkipsDraw(mode))
2446 {
2447 device->drawPrimitive(primitiveType, primitiveCount);
2448 }
2449}
2450
2451void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
2452{
2453 if(!mState.currentProgram)
2454 {
2455 return error(GL_INVALID_OPERATION);
2456 }
2457
2458 if(!indices && !mState.elementArrayBuffer)
2459 {
2460 return error(GL_INVALID_OPERATION);
2461 }
2462
John Bauman89401822014-05-06 15:04:28 -04002463 Device *device = getDevice();
2464 PrimitiveType primitiveType;
2465 int primitiveCount;
2466
2467 if(!es2sw::ConvertPrimitiveType(mode, count, primitiveType, primitiveCount))
2468 return error(GL_INVALID_ENUM);
2469
2470 if(primitiveCount <= 0)
2471 {
2472 return;
2473 }
2474
John Bauman19bac1e2014-05-06 15:23:49 -04002475 if(!applyRenderTarget())
John Bauman89401822014-05-06 15:04:28 -04002476 {
2477 return;
2478 }
2479
2480 applyState(mode);
2481
2482 TranslatedIndexData indexInfo;
2483 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2484 if(err != GL_NO_ERROR)
2485 {
2486 return error(err);
2487 }
2488
2489 GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
2490 err = applyVertexBuffer(-(int)indexInfo.minIndex, indexInfo.minIndex, vertexCount);
2491 if(err != GL_NO_ERROR)
2492 {
2493 return error(err);
2494 }
2495
2496 applyShaders();
2497 applyTextures();
2498
2499 if(!getCurrentProgram()->validateSamplers(false))
2500 {
2501 return error(GL_INVALID_OPERATION);
2502 }
2503
2504 if(!cullSkipsDraw(mode))
2505 {
2506 device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, primitiveCount, IndexDataManager::typeSize(type));
2507 }
2508}
2509
2510void Context::finish()
2511{
2512 Device *device = getDevice();
2513
2514 device->finish();
2515}
2516
2517void Context::flush()
2518{
2519 // We don't queue anything without processing it as fast as possible
2520}
2521
2522void Context::recordInvalidEnum()
2523{
2524 mInvalidEnum = true;
2525}
2526
2527void Context::recordInvalidValue()
2528{
2529 mInvalidValue = true;
2530}
2531
2532void Context::recordInvalidOperation()
2533{
2534 mInvalidOperation = true;
2535}
2536
2537void Context::recordOutOfMemory()
2538{
2539 mOutOfMemory = true;
2540}
2541
2542void Context::recordInvalidFramebufferOperation()
2543{
2544 mInvalidFramebufferOperation = true;
2545}
2546
2547// Get one of the recorded errors and clear its flag, if any.
2548// [OpenGL ES 2.0.24] section 2.5 page 13.
2549GLenum Context::getError()
2550{
2551 if(mInvalidEnum)
2552 {
2553 mInvalidEnum = false;
2554
2555 return GL_INVALID_ENUM;
2556 }
2557
2558 if(mInvalidValue)
2559 {
2560 mInvalidValue = false;
2561
2562 return GL_INVALID_VALUE;
2563 }
2564
2565 if(mInvalidOperation)
2566 {
2567 mInvalidOperation = false;
2568
2569 return GL_INVALID_OPERATION;
2570 }
2571
2572 if(mOutOfMemory)
2573 {
2574 mOutOfMemory = false;
2575
2576 return GL_OUT_OF_MEMORY;
2577 }
2578
2579 if(mInvalidFramebufferOperation)
2580 {
2581 mInvalidFramebufferOperation = false;
2582
2583 return GL_INVALID_FRAMEBUFFER_OPERATION;
2584 }
2585
2586 return GL_NO_ERROR;
2587}
2588
2589int Context::getNearestSupportedSamples(sw::Format format, int requested) const
2590{
2591 if(requested <= 1)
2592 {
2593 return requested;
2594 }
2595
2596 if(requested <= 2)
2597 {
2598 return 2;
2599 }
2600
2601 return 4;
2602}
2603
2604void Context::detachBuffer(GLuint buffer)
2605{
2606 // [OpenGL ES 2.0.24] section 2.9 page 22:
2607 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2608 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2609
2610 if(mState.arrayBuffer.id() == buffer)
2611 {
2612 mState.arrayBuffer.set(NULL);
2613 }
2614
2615 if(mState.elementArrayBuffer.id() == buffer)
2616 {
2617 mState.elementArrayBuffer.set(NULL);
2618 }
2619
2620 for(int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2621 {
2622 if(mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
2623 {
2624 mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
2625 }
2626 }
2627}
2628
2629void Context::detachTexture(GLuint texture)
2630{
2631 // [OpenGL ES 2.0.24] section 3.8 page 84:
2632 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2633 // rebound to texture object zero
2634
2635 for(int type = 0; type < TEXTURE_TYPE_COUNT; type++)
2636 {
2637 for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
2638 {
2639 if(mState.samplerTexture[type][sampler].id() == texture)
2640 {
2641 mState.samplerTexture[type][sampler].set(NULL);
2642 }
2643 }
2644 }
2645
2646 // [OpenGL ES 2.0.24] section 4.4 page 112:
2647 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2648 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2649 // image was attached in the currently bound framebuffer.
2650
2651 Framebuffer *readFramebuffer = getReadFramebuffer();
2652 Framebuffer *drawFramebuffer = getDrawFramebuffer();
2653
2654 if(readFramebuffer)
2655 {
2656 readFramebuffer->detachTexture(texture);
2657 }
2658
2659 if(drawFramebuffer && drawFramebuffer != readFramebuffer)
2660 {
2661 drawFramebuffer->detachTexture(texture);
2662 }
2663}
2664
2665void Context::detachFramebuffer(GLuint framebuffer)
2666{
2667 // [OpenGL ES 2.0.24] section 4.4 page 107:
2668 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2669 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2670
2671 if(mState.readFramebuffer == framebuffer)
2672 {
2673 bindReadFramebuffer(0);
2674 }
2675
2676 if(mState.drawFramebuffer == framebuffer)
2677 {
2678 bindDrawFramebuffer(0);
2679 }
2680}
2681
2682void Context::detachRenderbuffer(GLuint renderbuffer)
2683{
2684 // [OpenGL ES 2.0.24] section 4.4 page 109:
2685 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2686 // had been executed with the target RENDERBUFFER and name of zero.
2687
2688 if(mState.renderbuffer.id() == renderbuffer)
2689 {
2690 bindRenderbuffer(0);
2691 }
2692
2693 // [OpenGL ES 2.0.24] section 4.4 page 111:
2694 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2695 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2696 // point to which this image was attached in the currently bound framebuffer.
2697
2698 Framebuffer *readFramebuffer = getReadFramebuffer();
2699 Framebuffer *drawFramebuffer = getDrawFramebuffer();
2700
2701 if(readFramebuffer)
2702 {
2703 readFramebuffer->detachRenderbuffer(renderbuffer);
2704 }
2705
2706 if(drawFramebuffer && drawFramebuffer != readFramebuffer)
2707 {
2708 drawFramebuffer->detachRenderbuffer(renderbuffer);
2709 }
2710}
2711
2712bool Context::cullSkipsDraw(GLenum drawMode)
2713{
2714 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
2715}
2716
2717bool Context::isTriangleMode(GLenum drawMode)
2718{
2719 switch (drawMode)
2720 {
2721 case GL_TRIANGLES:
2722 case GL_TRIANGLE_FAN:
2723 case GL_TRIANGLE_STRIP:
2724 return true;
2725 case GL_POINTS:
2726 case GL_LINES:
2727 case GL_LINE_LOOP:
2728 case GL_LINE_STRIP:
2729 return false;
2730 default: UNREACHABLE();
2731 }
2732
2733 return false;
2734}
2735
2736void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2737{
2738 ASSERT(index < MAX_VERTEX_ATTRIBS);
2739
2740 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2741 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2742 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2743 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
2744
2745 mVertexDataManager->dirtyCurrentValue(index);
2746}
2747
2748void Context::initExtensionString()
2749{
John Bauman19bac1e2014-05-06 15:23:49 -04002750 // Keep list sorted in following order:
2751 // OES extensions
2752 // EXT extensions
2753 // Vendor extensions
John Bauman89401822014-05-06 15:04:28 -04002754
John Bauman19bac1e2014-05-06 15:23:49 -04002755 mExtensionString += "GL_OES_element_index_uint ";
2756 mExtensionString += "GL_OES_packed_depth_stencil ";
2757 mExtensionString += "GL_OES_rgb8_rgba8 ";
2758 mExtensionString += "GL_OES_standard_derivatives ";
2759 mExtensionString += "GL_OES_texture_float ";
2760 mExtensionString += "GL_OES_texture_float_linear ";
2761 mExtensionString += "GL_OES_texture_half_float ";
2762 mExtensionString += "GL_OES_texture_half_float_linear ";
2763 mExtensionString += "GL_OES_texture_npot ";
2764 mExtensionString += "GL_EXT_occlusion_query_boolean ";
2765 mExtensionString += "GL_EXT_read_format_bgra ";
2766
2767 if(S3TC_SUPPORT)
2768 {
2769 mExtensionString += "GL_EXT_texture_compression_dxt1 ";
2770 mExtensionString += "GL_ANGLE_texture_compression_dxt3 ";
2771 mExtensionString += "GL_ANGLE_texture_compression_dxt5 ";
2772 }
John Bauman89401822014-05-06 15:04:28 -04002773
John Bauman19bac1e2014-05-06 15:23:49 -04002774 mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
2775 mExtensionString += "GL_ANGLE_framebuffer_blit ";
2776 mExtensionString += "GL_ANGLE_framebuffer_multisample ";
2777 mExtensionString += "GL_NV_fence ";
John Bauman89401822014-05-06 15:04:28 -04002778
John Bauman19bac1e2014-05-06 15:23:49 -04002779 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2780 if(end != std::string::npos)
2781 {
2782 mExtensionString.resize(end + 1);
2783 }
John Bauman89401822014-05-06 15:04:28 -04002784}
2785
2786const char *Context::getExtensionString() const
2787{
2788 return mExtensionString.c_str();
2789}
2790
2791void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
2792 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
2793 GLbitfield mask)
2794{
2795 Device *device = getDevice();
2796
2797 Framebuffer *readFramebuffer = getReadFramebuffer();
2798 Framebuffer *drawFramebuffer = getDrawFramebuffer();
2799
2800 if(!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
John Bauman19bac1e2014-05-06 15:23:49 -04002801 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
John Bauman89401822014-05-06 15:04:28 -04002802 {
2803 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
2804 }
2805
2806 if(drawFramebuffer->getSamples() != 0)
2807 {
2808 return error(GL_INVALID_OPERATION);
2809 }
2810
2811 int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth();
2812 int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight();
2813 int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth();
2814 int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight();
2815
2816 sw::Rect sourceRect;
2817 sw::Rect destRect;
2818
2819 if(srcX0 < srcX1)
2820 {
John Bauman19bac1e2014-05-06 15:23:49 -04002821 sourceRect.x0 = srcX0;
2822 sourceRect.x1 = srcX1;
2823 destRect.x0 = dstX0;
2824 destRect.x1 = dstX1;
John Bauman89401822014-05-06 15:04:28 -04002825 }
2826 else
2827 {
John Bauman19bac1e2014-05-06 15:23:49 -04002828 sourceRect.x0 = srcX1;
2829 destRect.x0 = dstX1;
2830 sourceRect.x1 = srcX0;
2831 destRect.x1 = dstX0;
John Bauman89401822014-05-06 15:04:28 -04002832 }
2833
2834 if(srcY0 < srcY1)
2835 {
John Bauman19bac1e2014-05-06 15:23:49 -04002836 sourceRect.y0 = srcY0;
2837 destRect.y0 = dstY0;
2838 sourceRect.y1 = srcY1;
2839 destRect.y1 = dstY1;
John Bauman89401822014-05-06 15:04:28 -04002840 }
2841 else
2842 {
John Bauman19bac1e2014-05-06 15:23:49 -04002843 sourceRect.y0 = srcY1;
2844 destRect.y0 = dstY1;
2845 sourceRect.y1 = srcY0;
2846 destRect.y1 = dstY0;
John Bauman89401822014-05-06 15:04:28 -04002847 }
2848
2849 sw::Rect sourceScissoredRect = sourceRect;
2850 sw::Rect destScissoredRect = destRect;
2851
John Bauman19bac1e2014-05-06 15:23:49 -04002852 if(mState.scissorTest) // Only write to parts of the destination framebuffer which pass the scissor test
John Bauman89401822014-05-06 15:04:28 -04002853 {
John Bauman19bac1e2014-05-06 15:23:49 -04002854 if(destRect.x0 < mState.scissorX)
John Bauman89401822014-05-06 15:04:28 -04002855 {
John Bauman19bac1e2014-05-06 15:23:49 -04002856 int xDiff = mState.scissorX - destRect.x0;
2857 destScissoredRect.x0 = mState.scissorX;
2858 sourceScissoredRect.x0 += xDiff;
John Bauman89401822014-05-06 15:04:28 -04002859 }
2860
John Bauman19bac1e2014-05-06 15:23:49 -04002861 if(destRect.x1 > mState.scissorX + mState.scissorWidth)
John Bauman89401822014-05-06 15:04:28 -04002862 {
John Bauman19bac1e2014-05-06 15:23:49 -04002863 int xDiff = destRect.x1 - (mState.scissorX + mState.scissorWidth);
2864 destScissoredRect.x1 = mState.scissorX + mState.scissorWidth;
2865 sourceScissoredRect.x1 -= xDiff;
John Bauman89401822014-05-06 15:04:28 -04002866 }
2867
John Bauman19bac1e2014-05-06 15:23:49 -04002868 if(destRect.y0 < mState.scissorY)
John Bauman89401822014-05-06 15:04:28 -04002869 {
John Bauman19bac1e2014-05-06 15:23:49 -04002870 int yDiff = mState.scissorY - destRect.y0;
2871 destScissoredRect.y0 = mState.scissorY;
2872 sourceScissoredRect.y0 += yDiff;
John Bauman89401822014-05-06 15:04:28 -04002873 }
2874
John Bauman19bac1e2014-05-06 15:23:49 -04002875 if(destRect.y1 > mState.scissorY + mState.scissorHeight)
John Bauman89401822014-05-06 15:04:28 -04002876 {
John Bauman19bac1e2014-05-06 15:23:49 -04002877 int yDiff = destRect.y1 - (mState.scissorY + mState.scissorHeight);
2878 destScissoredRect.y1 = mState.scissorY + mState.scissorHeight;
2879 sourceScissoredRect.y1 -= yDiff;
John Bauman89401822014-05-06 15:04:28 -04002880 }
2881 }
2882
2883 bool blitRenderTarget = false;
2884 bool blitDepthStencil = false;
2885
2886 sw::Rect sourceTrimmedRect = sourceScissoredRect;
2887 sw::Rect destTrimmedRect = destScissoredRect;
2888
2889 // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of
2890 // the actual draw and read surfaces.
John Bauman19bac1e2014-05-06 15:23:49 -04002891 if(sourceTrimmedRect.x0 < 0)
John Bauman89401822014-05-06 15:04:28 -04002892 {
John Bauman19bac1e2014-05-06 15:23:49 -04002893 int xDiff = 0 - sourceTrimmedRect.x0;
2894 sourceTrimmedRect.x0 = 0;
2895 destTrimmedRect.x0 += xDiff;
John Bauman89401822014-05-06 15:04:28 -04002896 }
2897
John Bauman19bac1e2014-05-06 15:23:49 -04002898 if(sourceTrimmedRect.x1 > readBufferWidth)
John Bauman89401822014-05-06 15:04:28 -04002899 {
John Bauman19bac1e2014-05-06 15:23:49 -04002900 int xDiff = sourceTrimmedRect.x1 - readBufferWidth;
2901 sourceTrimmedRect.x1 = readBufferWidth;
2902 destTrimmedRect.x1 -= xDiff;
John Bauman89401822014-05-06 15:04:28 -04002903 }
2904
John Bauman19bac1e2014-05-06 15:23:49 -04002905 if(sourceTrimmedRect.y0 < 0)
John Bauman89401822014-05-06 15:04:28 -04002906 {
John Bauman19bac1e2014-05-06 15:23:49 -04002907 int yDiff = 0 - sourceTrimmedRect.y0;
2908 sourceTrimmedRect.y0 = 0;
2909 destTrimmedRect.y0 += yDiff;
John Bauman89401822014-05-06 15:04:28 -04002910 }
2911
John Bauman19bac1e2014-05-06 15:23:49 -04002912 if(sourceTrimmedRect.y1 > readBufferHeight)
John Bauman89401822014-05-06 15:04:28 -04002913 {
John Bauman19bac1e2014-05-06 15:23:49 -04002914 int yDiff = sourceTrimmedRect.y1 - readBufferHeight;
2915 sourceTrimmedRect.y1 = readBufferHeight;
2916 destTrimmedRect.y1 -= yDiff;
John Bauman89401822014-05-06 15:04:28 -04002917 }
2918
John Bauman19bac1e2014-05-06 15:23:49 -04002919 if(destTrimmedRect.x0 < 0)
John Bauman89401822014-05-06 15:04:28 -04002920 {
John Bauman19bac1e2014-05-06 15:23:49 -04002921 int xDiff = 0 - destTrimmedRect.x0;
2922 destTrimmedRect.x0 = 0;
2923 sourceTrimmedRect.x0 += xDiff;
John Bauman89401822014-05-06 15:04:28 -04002924 }
2925
John Bauman19bac1e2014-05-06 15:23:49 -04002926 if(destTrimmedRect.x1 > drawBufferWidth)
John Bauman89401822014-05-06 15:04:28 -04002927 {
John Bauman19bac1e2014-05-06 15:23:49 -04002928 int xDiff = destTrimmedRect.x1 - drawBufferWidth;
2929 destTrimmedRect.x1 = drawBufferWidth;
2930 sourceTrimmedRect.x1 -= xDiff;
John Bauman89401822014-05-06 15:04:28 -04002931 }
2932
John Bauman19bac1e2014-05-06 15:23:49 -04002933 if(destTrimmedRect.y0 < 0)
John Bauman89401822014-05-06 15:04:28 -04002934 {
John Bauman19bac1e2014-05-06 15:23:49 -04002935 int yDiff = 0 - destTrimmedRect.y0;
2936 destTrimmedRect.y0 = 0;
2937 sourceTrimmedRect.y0 += yDiff;
John Bauman89401822014-05-06 15:04:28 -04002938 }
2939
John Bauman19bac1e2014-05-06 15:23:49 -04002940 if(destTrimmedRect.y1 > drawBufferHeight)
John Bauman89401822014-05-06 15:04:28 -04002941 {
John Bauman19bac1e2014-05-06 15:23:49 -04002942 int yDiff = destTrimmedRect.y1 - drawBufferHeight;
2943 destTrimmedRect.y1 = drawBufferHeight;
2944 sourceTrimmedRect.y1 -= yDiff;
John Bauman89401822014-05-06 15:04:28 -04002945 }
2946
2947 bool partialBufferCopy = false;
John Bauman19bac1e2014-05-06 15:23:49 -04002948 if(sourceTrimmedRect.y1 - sourceTrimmedRect.y0 < readBufferHeight ||
2949 sourceTrimmedRect.x1 - sourceTrimmedRect.x0 < readBufferWidth ||
2950 destTrimmedRect.y1 - destTrimmedRect.y0 < drawBufferHeight ||
2951 destTrimmedRect.x1 - destTrimmedRect.x0 < drawBufferWidth ||
2952 sourceTrimmedRect.y0 != 0 || destTrimmedRect.y0 != 0 || sourceTrimmedRect.x0 != 0 || destTrimmedRect.x0 != 0)
John Bauman89401822014-05-06 15:04:28 -04002953 {
2954 partialBufferCopy = true;
2955 }
2956
2957 if(mask & GL_COLOR_BUFFER_BIT)
2958 {
2959 const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
2960 readFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
2961 const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
2962 drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
2963 if(!validReadType || !validDrawType ||
2964 readFramebuffer->getColorbuffer()->getInternalFormat() != drawFramebuffer->getColorbuffer()->getInternalFormat())
2965 {
2966 ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
2967 return error(GL_INVALID_OPERATION);
2968 }
2969
2970 if(partialBufferCopy && readFramebuffer->getSamples() != 0)
2971 {
2972 return error(GL_INVALID_OPERATION);
2973 }
2974
2975 blitRenderTarget = true;
John Bauman89401822014-05-06 15:04:28 -04002976 }
2977
2978 if(mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
2979 {
2980 DepthStencilbuffer *readDSBuffer = NULL;
2981 DepthStencilbuffer *drawDSBuffer = NULL;
2982
2983 // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
2984 // both a depth and stencil buffer, it will be the same buffer.
2985
2986 if(mask & GL_DEPTH_BUFFER_BIT)
2987 {
2988 if(readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
2989 {
2990 if(readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
2991 readFramebuffer->getDepthbuffer()->getInternalFormat() != drawFramebuffer->getDepthbuffer()->getInternalFormat())
2992 {
2993 return error(GL_INVALID_OPERATION);
2994 }
2995
2996 blitDepthStencil = true;
2997 readDSBuffer = readFramebuffer->getDepthbuffer();
2998 drawDSBuffer = drawFramebuffer->getDepthbuffer();
2999 }
3000 }
3001
3002 if(mask & GL_STENCIL_BUFFER_BIT)
3003 {
3004 if(readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
3005 {
3006 if(readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
3007 readFramebuffer->getStencilbuffer()->getInternalFormat() != drawFramebuffer->getStencilbuffer()->getInternalFormat())
3008 {
3009 return error(GL_INVALID_OPERATION);
3010 }
3011
3012 blitDepthStencil = true;
3013 readDSBuffer = readFramebuffer->getStencilbuffer();
3014 drawDSBuffer = drawFramebuffer->getStencilbuffer();
3015 }
3016 }
3017
3018 if(partialBufferCopy)
3019 {
3020 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
John Bauman19bac1e2014-05-06 15:23:49 -04003021 return error(GL_INVALID_OPERATION); // Only whole-buffer copies are permitted
John Bauman89401822014-05-06 15:04:28 -04003022 }
3023
3024 if((drawDSBuffer && drawDSBuffer->getSamples() != 0) ||
3025 (readDSBuffer && readDSBuffer->getSamples() != 0))
3026 {
3027 return error(GL_INVALID_OPERATION);
3028 }
3029 }
3030
3031 if(blitRenderTarget || blitDepthStencil)
3032 {
3033 egl::Display *display = getDisplay();
3034
3035 if(blitRenderTarget)
3036 {
John Bauman19bac1e2014-05-06 15:23:49 -04003037 Image *readRenderTarget = readFramebuffer->getRenderTarget();
3038 Image *drawRenderTarget = drawFramebuffer->getRenderTarget();
3039
3040 bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, false);
3041
3042 readRenderTarget->release();
3043 drawRenderTarget->release();
John Bauman89401822014-05-06 15:04:28 -04003044
3045 if(!success)
3046 {
3047 ERR("BlitFramebufferANGLE failed.");
3048 return;
3049 }
3050 }
3051
3052 if(blitDepthStencil)
3053 {
3054 bool success = device->stretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, false);
3055
3056 if(!success)
3057 {
3058 ERR("BlitFramebufferANGLE failed.");
3059 return;
3060 }
3061 }
3062 }
3063}
3064
3065}
3066
3067extern "C"
3068{
3069 gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
3070 {
3071 return new gl::Context(config, shareContext);
3072 }
3073
3074 void glDestroyContext(gl::Context *context)
3075 {
3076 delete context;
3077
3078 if(context == gl::getContext())
3079 {
3080 gl::makeCurrent(NULL, NULL, NULL);
3081 }
3082 }
3083
3084 void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
3085 {
3086 gl::makeCurrent(context, display, surface);
3087 }
3088
3089 gl::Context *glGetCurrentContext()
3090 {
3091 return gl::getContext();
3092 }
3093}