blob: 0d87a7ea284e8db90fa956ed118ffe016965f74c [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Context.cpp: Implements the gl::Context class, managing all GL state and performing
8// rendering operations. It is the GLES2 specific implementation of EGLContext.
9
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Context.h"
daniel@transgaming.com16973022010-03-11 19:22:19 +000011
12#include <algorithm>
13
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000014#include "libEGL/Display.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000015
16#include "libGLESv2/main.h"
17#include "libGLESv2/mathutil.h"
18#include "libGLESv2/utilities.h"
19#include "libGLESv2/Blit.h"
20#include "libGLESv2/Buffer.h"
21#include "libGLESv2/FrameBuffer.h"
22#include "libGLESv2/Program.h"
23#include "libGLESv2/RenderBuffer.h"
24#include "libGLESv2/Shader.h"
25#include "libGLESv2/Texture.h"
26#include "libGLESv2/geometry/backend.h"
27#include "libGLESv2/geometry/VertexDataManager.h"
28#include "libGLESv2/geometry/IndexDataManager.h"
29#include "libGLESv2/geometry/dx9.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030
daniel@transgaming.com86487c22010-03-11 19:41:43 +000031#undef near
32#undef far
33
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034namespace gl
35{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000036Context::Context(const egl::Config *config)
37 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038{
39 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com428d1582010-05-04 03:35:25 +000040 mState.depthClearValue = 1.0f;
41 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042
daniel@transgaming.com428d1582010-05-04 03:35:25 +000043 mState.cullFace = false;
44 mState.cullMode = GL_BACK;
45 mState.frontFace = GL_CCW;
46 mState.depthTest = false;
47 mState.depthFunc = GL_LESS;
48 mState.blend = false;
49 mState.sourceBlendRGB = GL_ONE;
50 mState.sourceBlendAlpha = GL_ONE;
51 mState.destBlendRGB = GL_ZERO;
52 mState.destBlendAlpha = GL_ZERO;
53 mState.blendEquationRGB = GL_FUNC_ADD;
54 mState.blendEquationAlpha = GL_FUNC_ADD;
55 mState.blendColor.red = 0;
56 mState.blendColor.green = 0;
57 mState.blendColor.blue = 0;
58 mState.blendColor.alpha = 0;
59 mState.stencilTest = false;
60 mState.stencilFunc = GL_ALWAYS;
61 mState.stencilRef = 0;
62 mState.stencilMask = -1;
63 mState.stencilWritemask = -1;
64 mState.stencilBackFunc = GL_ALWAYS;
65 mState.stencilBackRef = 0;
66 mState.stencilBackMask = - 1;
67 mState.stencilBackWritemask = -1;
68 mState.stencilFail = GL_KEEP;
69 mState.stencilPassDepthFail = GL_KEEP;
70 mState.stencilPassDepthPass = GL_KEEP;
71 mState.stencilBackFail = GL_KEEP;
72 mState.stencilBackPassDepthFail = GL_KEEP;
73 mState.stencilBackPassDepthPass = GL_KEEP;
74 mState.polygonOffsetFill = false;
75 mState.polygonOffsetFactor = 0.0f;
76 mState.polygonOffsetUnits = 0.0f;
77 mState.sampleAlphaToCoverage = false;
78 mState.sampleCoverage = false;
79 mState.sampleCoverageValue = 1.0f;
80 mState.sampleCoverageInvert = GL_FALSE;
81 mState.scissorTest = false;
82 mState.dither = true;
83 mState.generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084
daniel@transgaming.com428d1582010-05-04 03:35:25 +000085 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000086
daniel@transgaming.com428d1582010-05-04 03:35:25 +000087 mState.viewportX = 0;
88 mState.viewportY = 0;
89 mState.viewportWidth = config->mDisplayMode.Width;
90 mState.viewportHeight = config->mDisplayMode.Height;
91 mState.zNear = 0.0f;
92 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000093
daniel@transgaming.com428d1582010-05-04 03:35:25 +000094 mState.scissorX = 0;
95 mState.scissorY = 0;
96 mState.scissorWidth = config->mDisplayMode.Width;
97 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098
daniel@transgaming.com428d1582010-05-04 03:35:25 +000099 mState.colorMaskRed = true;
100 mState.colorMaskGreen = true;
101 mState.colorMaskBlue = true;
102 mState.colorMaskAlpha = true;
103 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104
105 // [OpenGL ES 2.0.24] section 3.7 page 83:
106 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
107 // and cube map texture state vectors respectively associated with them.
108 // In order that access to these initial textures not be lost, they are treated as texture
109 // objects all of whose names are 0.
110
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000111 mTexture2DZero = new Texture2D(this);
112 mTextureCubeMapZero = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113
114 mColorbufferZero = NULL;
115 mDepthbufferZero = NULL;
116 mStencilbufferZero = NULL;
117
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000118 mState.activeSampler = 0;
119 mState.arrayBuffer = 0;
120 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121 bindTextureCubeMap(0);
122 bindTexture2D(0);
123 bindFramebuffer(0);
124 bindRenderbuffer(0);
125
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000126 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000128 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
129 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000130 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000131 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132 }
133
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000134 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
135 {
136 mIncompleteTextures[type] = NULL;
137 }
138
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000139 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000141 mState.packAlignment = 4;
142 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000143
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000144 mBufferBackEnd = NULL;
145 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000146 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000147 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000148
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149 mInvalidEnum = false;
150 mInvalidValue = false;
151 mInvalidOperation = false;
152 mOutOfMemory = false;
153 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000154
155 mHasBeenCurrent = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156}
157
158Context::~Context()
159{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000160 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000161
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000162 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
163 {
164 delete mIncompleteTextures[type];
165 }
166
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167 delete mTexture2DZero;
168 delete mTextureCubeMapZero;
169
170 delete mColorbufferZero;
171 delete mDepthbufferZero;
172 delete mStencilbufferZero;
173
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000174 delete mBufferBackEnd;
175 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000176 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000177 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000178
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179 while (!mBufferMap.empty())
180 {
181 deleteBuffer(mBufferMap.begin()->first);
182 }
183
184 while (!mProgramMap.empty())
185 {
186 deleteProgram(mProgramMap.begin()->first);
187 }
188
189 while (!mShaderMap.empty())
190 {
191 deleteShader(mShaderMap.begin()->first);
192 }
193
194 while (!mFramebufferMap.empty())
195 {
196 deleteFramebuffer(mFramebufferMap.begin()->first);
197 }
198
199 while (!mRenderbufferMap.empty())
200 {
201 deleteRenderbuffer(mRenderbufferMap.begin()->first);
202 }
203
204 while (!mTextureMap.empty())
205 {
206 deleteTexture(mTextureMap.begin()->first);
207 }
208}
209
210void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
211{
212 IDirect3DDevice9 *device = display->getDevice();
213
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000214 if (!mBufferBackEnd)
215 {
216 mBufferBackEnd = new Dx9BackEnd(device);
217 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000218 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000219 mBlit = new Blit(this);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000220 }
221
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
223 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000224 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225
226 Framebuffer *framebufferZero = new Framebuffer();
227 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000228 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
229 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230
231 setFramebufferZero(framebufferZero);
232 setColorbufferZero(colorbufferZero);
233 setDepthbufferZero(depthbufferZero);
234 setStencilbufferZero(stencilbufferZero);
235
236 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
237 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
238 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
239
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000240 if (!mHasBeenCurrent)
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000241 {
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000242 initExtensionString();
243
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000244 mState.viewportX = 0;
245 mState.viewportY = 0;
246 mState.viewportWidth = surface->getWidth();
247 mState.viewportHeight = surface->getHeight();
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000248
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000249 mState.scissorX = 0;
250 mState.scissorY = 0;
251 mState.scissorWidth = surface->getWidth();
252 mState.scissorHeight = surface->getHeight();
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000253
254 mHasBeenCurrent = true;
255 }
256
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257 defaultRenderTarget->Release();
258
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000259 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000261 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000263
264 D3DCAPS9 capabilities;
265 device->GetDeviceCaps(&capabilities);
266
267 if (capabilities.PixelShaderVersion == D3DPS_VERSION(3, 0))
268 {
269 mPsProfile = "ps_3_0";
270 mVsProfile = "vs_3_0";
271 }
272 else // egl::Display guarantees support for at least 2.0
273 {
274 mPsProfile = "ps_2_0";
275 mVsProfile = "vs_2_0";
276 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277}
278
279void Context::setClearColor(float red, float green, float blue, float alpha)
280{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000281 mState.colorClearValue.red = red;
282 mState.colorClearValue.green = green;
283 mState.colorClearValue.blue = blue;
284 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285}
286
287void Context::setClearDepth(float depth)
288{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000289 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290}
291
292void Context::setClearStencil(int stencil)
293{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000294 mState.stencilClearValue = stencil;
295}
296
297void Context::setCullFace(bool enabled)
298{
299 mState.cullFace = enabled;
300}
301
302bool Context::isCullFaceEnabled() const
303{
304 return mState.cullFace;
305}
306
307void Context::setCullMode(GLenum mode)
308{
309 mState.cullMode = mode;
310}
311
312void Context::setFrontFace(GLenum front)
313{
314 mState.frontFace = front;
315}
316
317void Context::setDepthTest(bool enabled)
318{
319 mState.depthTest = enabled;
320}
321
322bool Context::isDepthTestEnabled() const
323{
324 return mState.depthTest;
325}
326
327void Context::setDepthFunc(GLenum depthFunc)
328{
329 mState.depthFunc = depthFunc;
330}
331
332void Context::setDepthRange(float zNear, float zFar)
333{
334 mState.zNear = zNear;
335 mState.zFar = zFar;
336}
337
338void Context::setBlend(bool enabled)
339{
340 mState.blend = enabled;
341}
342
343bool Context::isBlendEnabled() const
344{
345 return mState.blend;
346}
347
348void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
349{
350 mState.sourceBlendRGB = sourceRGB;
351 mState.destBlendRGB = destRGB;
352 mState.sourceBlendAlpha = sourceAlpha;
353 mState.destBlendAlpha = destAlpha;
354}
355
356void Context::setBlendColor(float red, float green, float blue, float alpha)
357{
358 mState.blendColor.red = red;
359 mState.blendColor.green = green;
360 mState.blendColor.blue = blue;
361 mState.blendColor.alpha = alpha;
362}
363
364void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
365{
366 mState.blendEquationRGB = rgbEquation;
367 mState.blendEquationAlpha = alphaEquation;
368}
369
370void Context::setStencilTest(bool enabled)
371{
372 mState.stencilTest = enabled;
373}
374
375bool Context::isStencilTestEnabled() const
376{
377 return mState.stencilTest;
378}
379
380void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
381{
382 mState.stencilFunc = stencilFunc;
383 mState.stencilRef = stencilRef;
384 mState.stencilMask = stencilMask;
385}
386
387void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
388{
389 mState.stencilBackFunc = stencilBackFunc;
390 mState.stencilBackRef = stencilBackRef;
391 mState.stencilBackMask = stencilBackMask;
392}
393
394void Context::setStencilWritemask(GLuint stencilWritemask)
395{
396 mState.stencilWritemask = stencilWritemask;
397}
398
399void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
400{
401 mState.stencilBackWritemask = stencilBackWritemask;
402}
403
404void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
405{
406 mState.stencilFail = stencilFail;
407 mState.stencilPassDepthFail = stencilPassDepthFail;
408 mState.stencilPassDepthPass = stencilPassDepthPass;
409}
410
411void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
412{
413 mState.stencilBackFail = stencilBackFail;
414 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
415 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
416}
417
418void Context::setPolygonOffsetFill(bool enabled)
419{
420 mState.polygonOffsetFill = enabled;
421}
422
423bool Context::isPolygonOffsetFillEnabled() const
424{
425 return mState.polygonOffsetFill;
426}
427
428void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
429{
430 mState.polygonOffsetFactor = factor;
431 mState.polygonOffsetUnits = units;
432}
433
434void Context::setSampleAlphaToCoverage(bool enabled)
435{
436 mState.sampleAlphaToCoverage = enabled;
437}
438
439bool Context::isSampleAlphaToCoverageEnabled() const
440{
441 return mState.sampleAlphaToCoverage;
442}
443
444void Context::setSampleCoverage(bool enabled)
445{
446 mState.sampleCoverage = enabled;
447}
448
449bool Context::isSampleCoverageEnabled() const
450{
451 return mState.sampleCoverage;
452}
453
454void Context::setSampleCoverageParams(GLclampf value, GLboolean invert)
455{
456 mState.sampleCoverageValue = value;
457 mState.sampleCoverageInvert = invert;
458}
459
460void Context::setScissorTest(bool enabled)
461{
462 mState.scissorTest = enabled;
463}
464
465bool Context::isScissorTestEnabled() const
466{
467 return mState.scissorTest;
468}
469
470void Context::setDither(bool enabled)
471{
472 mState.dither = enabled;
473}
474
475bool Context::isDitherEnabled() const
476{
477 return mState.dither;
478}
479
480void Context::setLineWidth(GLfloat width)
481{
482 mState.lineWidth = width;
483}
484
485void Context::setGenerateMipmapHint(GLenum hint)
486{
487 mState.generateMipmapHint = hint;
488}
489
490void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
491{
492 mState.viewportX = x;
493 mState.viewportY = y;
494 mState.viewportWidth = width;
495 mState.viewportHeight = height;
496}
497
498void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
499{
500 mState.scissorX = x;
501 mState.scissorY = y;
502 mState.scissorWidth = width;
503 mState.scissorHeight = height;
504}
505
506void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
507{
508 mState.colorMaskRed = red;
509 mState.colorMaskGreen = green;
510 mState.colorMaskBlue = blue;
511 mState.colorMaskAlpha = alpha;
512}
513
514void Context::setDepthMask(bool mask)
515{
516 mState.depthMask = mask;
517}
518
519void Context::setActiveSampler(int active)
520{
521 mState.activeSampler = active;
522}
523
524GLuint Context::getFramebufferHandle() const
525{
526 return mState.framebuffer;
527}
528
529GLuint Context::getRenderbufferHandle() const
530{
531 return mState.renderbuffer;
532}
533
534GLuint Context::getArrayBufferHandle() const
535{
536 return mState.arrayBuffer;
537}
538
539void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
540{
541 mState.vertexAttribute[attribNum].mEnabled = enabled;
542}
543
544const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
545{
546 return mState.vertexAttribute[attribNum];
547}
548
549void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
550 GLsizei stride, const void *pointer)
551{
552 mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
553 mState.vertexAttribute[attribNum].mSize = size;
554 mState.vertexAttribute[attribNum].mType = type;
555 mState.vertexAttribute[attribNum].mNormalized = normalized;
556 mState.vertexAttribute[attribNum].mStride = stride;
557 mState.vertexAttribute[attribNum].mPointer = pointer;
558}
559
560const void *Context::getVertexAttribPointer(unsigned int attribNum) const
561{
562 return mState.vertexAttribute[attribNum].mPointer;
563}
564
565// returns entire set of attributes as a block
566const AttributeState *Context::getVertexAttribBlock()
567{
568 return mState.vertexAttribute;
569}
570
571void Context::setPackAlignment(GLint alignment)
572{
573 mState.packAlignment = alignment;
574}
575
576GLint Context::getPackAlignment() const
577{
578 return mState.packAlignment;
579}
580
581void Context::setUnpackAlignment(GLint alignment)
582{
583 mState.unpackAlignment = alignment;
584}
585
586GLint Context::getUnpackAlignment() const
587{
588 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000589}
590
591// Returns an unused buffer name
592GLuint Context::createBuffer()
593{
594 unsigned int handle = 1;
595
596 while (mBufferMap.find(handle) != mBufferMap.end())
597 {
598 handle++;
599 }
600
601 mBufferMap[handle] = NULL;
602
603 return handle;
604}
605
606// Returns an unused shader/program name
607GLuint Context::createShader(GLenum type)
608{
609 unsigned int handle = 1;
610
611 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
612 {
613 handle++;
614 }
615
616 if (type == GL_VERTEX_SHADER)
617 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000618 mShaderMap[handle] = new VertexShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000619 }
620 else if (type == GL_FRAGMENT_SHADER)
621 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000622 mShaderMap[handle] = new FragmentShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000623 }
624 else UNREACHABLE();
625
626 return handle;
627}
628
629// Returns an unused program/shader name
630GLuint Context::createProgram()
631{
632 unsigned int handle = 1;
633
634 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
635 {
636 handle++;
637 }
638
639 mProgramMap[handle] = new Program();
640
641 return handle;
642}
643
644// Returns an unused texture name
645GLuint Context::createTexture()
646{
647 unsigned int handle = 1;
648
649 while (mTextureMap.find(handle) != mTextureMap.end())
650 {
651 handle++;
652 }
653
654 mTextureMap[handle] = NULL;
655
656 return handle;
657}
658
659// Returns an unused framebuffer name
660GLuint Context::createFramebuffer()
661{
662 unsigned int handle = 1;
663
664 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
665 {
666 handle++;
667 }
668
669 mFramebufferMap[handle] = NULL;
670
671 return handle;
672}
673
674// Returns an unused renderbuffer name
675GLuint Context::createRenderbuffer()
676{
677 unsigned int handle = 1;
678
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000679 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000680 {
681 handle++;
682 }
683
684 mRenderbufferMap[handle] = NULL;
685
686 return handle;
687}
688
689void Context::deleteBuffer(GLuint buffer)
690{
691 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
692
693 if (bufferObject != mBufferMap.end())
694 {
695 detachBuffer(buffer);
696
697 delete bufferObject->second;
698 mBufferMap.erase(bufferObject);
699 }
700}
701
702void Context::deleteShader(GLuint shader)
703{
704 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
705
706 if (shaderObject != mShaderMap.end())
707 {
708 if (!shaderObject->second->isAttached())
709 {
710 delete shaderObject->second;
711 mShaderMap.erase(shaderObject);
712 }
713 else
714 {
715 shaderObject->second->flagForDeletion();
716 }
717 }
718}
719
720void Context::deleteProgram(GLuint program)
721{
722 ProgramMap::iterator programObject = mProgramMap.find(program);
723
724 if (programObject != mProgramMap.end())
725 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000726 if (program != mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000727 {
728 delete programObject->second;
729 mProgramMap.erase(programObject);
730 }
731 else
732 {
733 programObject->second->flagForDeletion();
734 }
735 }
736}
737
738void Context::deleteTexture(GLuint texture)
739{
740 TextureMap::iterator textureObject = mTextureMap.find(texture);
741
742 if (textureObject != mTextureMap.end())
743 {
744 detachTexture(texture);
745
746 if (texture != 0)
747 {
748 delete textureObject->second;
749 }
750
751 mTextureMap.erase(textureObject);
752 }
753}
754
755void Context::deleteFramebuffer(GLuint framebuffer)
756{
757 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
758
759 if (framebufferObject != mFramebufferMap.end())
760 {
761 detachFramebuffer(framebuffer);
762
763 delete framebufferObject->second;
764 mFramebufferMap.erase(framebufferObject);
765 }
766}
767
768void Context::deleteRenderbuffer(GLuint renderbuffer)
769{
770 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
771
772 if (renderbufferObject != mRenderbufferMap.end())
773 {
774 detachRenderbuffer(renderbuffer);
775
776 delete renderbufferObject->second;
777 mRenderbufferMap.erase(renderbufferObject);
778 }
779}
780
781void Context::bindArrayBuffer(unsigned int buffer)
782{
783 if (buffer != 0 && !getBuffer(buffer))
784 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000785 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000786 }
787
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000788 mState.arrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000789}
790
791void Context::bindElementArrayBuffer(unsigned int buffer)
792{
793 if (buffer != 0 && !getBuffer(buffer))
794 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000795 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000796 }
797
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000798 mState.elementArrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000799}
800
801void Context::bindTexture2D(GLuint texture)
802{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000803 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000804 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000805 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000806 }
807
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000808 mState.texture2D = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000809
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000810 mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000811}
812
813void Context::bindTextureCubeMap(GLuint texture)
814{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000815 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000816 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000817 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818 }
819
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000820 mState.textureCubeMap = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000821
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000822 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000823}
824
825void Context::bindFramebuffer(GLuint framebuffer)
826{
827 if (!getFramebuffer(framebuffer))
828 {
829 mFramebufferMap[framebuffer] = new Framebuffer();
830 }
831
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000832 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000833}
834
835void Context::bindRenderbuffer(GLuint renderbuffer)
836{
837 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
838 {
839 mRenderbufferMap[renderbuffer] = new Renderbuffer();
840 }
841
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000842 mState.renderbuffer = renderbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000843}
844
845void Context::useProgram(GLuint program)
846{
847 Program *programObject = getCurrentProgram();
848
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000849 GLuint priorProgram = mState.currentProgram;
850 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000851
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000852 if (programObject && programObject->isFlaggedForDeletion())
853 {
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000854 deleteProgram(priorProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000855 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000856}
857
858void Context::setFramebufferZero(Framebuffer *buffer)
859{
860 delete mFramebufferMap[0];
861 mFramebufferMap[0] = buffer;
862}
863
864void Context::setColorbufferZero(Colorbuffer *buffer)
865{
866 delete mColorbufferZero;
867 mColorbufferZero = buffer;
868}
869
870void Context::setDepthbufferZero(Depthbuffer *buffer)
871{
872 delete mDepthbufferZero;
873 mDepthbufferZero = buffer;
874}
875
876void Context::setStencilbufferZero(Stencilbuffer *buffer)
877{
878 delete mStencilbufferZero;
879 mStencilbufferZero = buffer;
880}
881
882void Context::setRenderbuffer(Renderbuffer *buffer)
883{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000884 delete mRenderbufferMap[mState.renderbuffer];
885 mRenderbufferMap[mState.renderbuffer] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000886}
887
888Buffer *Context::getBuffer(unsigned int handle)
889{
890 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000891
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000892 if (buffer == mBufferMap.end())
893 {
894 return NULL;
895 }
896 else
897 {
898 return buffer->second;
899 }
900}
901
902Shader *Context::getShader(unsigned int handle)
903{
904 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000905
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000906 if (shader == mShaderMap.end())
907 {
908 return NULL;
909 }
910 else
911 {
912 return shader->second;
913 }
914}
915
916Program *Context::getProgram(unsigned int handle)
917{
918 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000919
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000920 if (program == mProgramMap.end())
921 {
922 return NULL;
923 }
924 else
925 {
926 return program->second;
927 }
928}
929
930Texture *Context::getTexture(unsigned int handle)
931{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000932 if (handle == 0) return NULL;
933
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000934 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000935
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000936 if (texture == mTextureMap.end())
937 {
938 return NULL;
939 }
940 else
941 {
942 return texture->second;
943 }
944}
945
946Framebuffer *Context::getFramebuffer(unsigned int handle)
947{
948 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000949
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000950 if (framebuffer == mFramebufferMap.end())
951 {
952 return NULL;
953 }
954 else
955 {
956 return framebuffer->second;
957 }
958}
959
960Renderbuffer *Context::getRenderbuffer(unsigned int handle)
961{
962 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000963
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000964 if (renderbuffer == mRenderbufferMap.end())
965 {
966 return NULL;
967 }
968 else
969 {
970 return renderbuffer->second;
971 }
972}
973
974Colorbuffer *Context::getColorbuffer(GLuint handle)
975{
976 if (handle != 0)
977 {
978 Renderbuffer *renderbuffer = getRenderbuffer(handle);
979
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000980 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000981 {
982 return static_cast<Colorbuffer*>(renderbuffer);
983 }
984 }
985 else // Special case: 0 refers to different initial render targets based on the attachment type
986 {
987 return mColorbufferZero;
988 }
989
990 return NULL;
991}
992
993Depthbuffer *Context::getDepthbuffer(GLuint handle)
994{
995 if (handle != 0)
996 {
997 Renderbuffer *renderbuffer = getRenderbuffer(handle);
998
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000999 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001000 {
1001 return static_cast<Depthbuffer*>(renderbuffer);
1002 }
1003 }
1004 else // Special case: 0 refers to different initial render targets based on the attachment type
1005 {
1006 return mDepthbufferZero;
1007 }
1008
1009 return NULL;
1010}
1011
1012Stencilbuffer *Context::getStencilbuffer(GLuint handle)
1013{
1014 if (handle != 0)
1015 {
1016 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1017
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001018 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001019 {
1020 return static_cast<Stencilbuffer*>(renderbuffer);
1021 }
1022 }
1023 else
1024 {
1025 return mStencilbufferZero;
1026 }
1027
1028 return NULL;
1029}
1030
1031Buffer *Context::getArrayBuffer()
1032{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001033 return getBuffer(mState.arrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001034}
1035
1036Buffer *Context::getElementArrayBuffer()
1037{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001038 return getBuffer(mState.elementArrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001039}
1040
1041Program *Context::getCurrentProgram()
1042{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001043 return getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001044}
1045
1046Texture2D *Context::getTexture2D()
1047{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001048 if (mState.texture2D == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001049 {
1050 return mTexture2DZero;
1051 }
1052
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001053 return (Texture2D*)getTexture(mState.texture2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001054}
1055
1056TextureCubeMap *Context::getTextureCubeMap()
1057{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001058 if (mState.textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001059 {
1060 return mTextureCubeMapZero;
1061 }
1062
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001063 return (TextureCubeMap*)getTexture(mState.textureCubeMap);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001064}
1065
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001066Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001067{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001068 GLuint texid = mState.samplerTexture[type][sampler];
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001069
1070 if (texid == 0)
1071 {
1072 switch (type)
1073 {
1074 default: UNREACHABLE();
1075 case SAMPLER_2D: return mTexture2DZero;
1076 case SAMPLER_CUBE: return mTextureCubeMapZero;
1077 }
1078 }
1079
1080 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001081}
1082
1083Framebuffer *Context::getFramebuffer()
1084{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001085 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001086}
1087
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001088bool Context::getBooleanv(GLenum pname, GLboolean *params)
1089{
1090 switch (pname)
1091 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001092 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1093 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1094 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001095 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001096 params[0] = mState.colorMaskRed;
1097 params[1] = mState.colorMaskGreen;
1098 params[2] = mState.colorMaskBlue;
1099 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001100 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001101 case GL_CULL_FACE: *params = mState.cullFace;
1102 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1103 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1104 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1105 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1106 case GL_STENCIL_TEST: *params = mState.stencilTest;
1107 case GL_DEPTH_TEST: *params = mState.depthTest;
1108 case GL_BLEND: *params = mState.blend;
1109 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001110 default:
1111 return false;
1112 }
1113
1114 return true;
1115}
1116
1117bool Context::getFloatv(GLenum pname, GLfloat *params)
1118{
1119 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1120 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1121 // GetIntegerv as its native query function. As it would require conversion in any
1122 // case, this should make no difference to the calling application.
1123 switch (pname)
1124 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001125 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1126 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1127 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1128 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1129 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001130 case GL_ALIASED_LINE_WIDTH_RANGE:
1131 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1132 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1133 break;
1134 case GL_ALIASED_POINT_SIZE_RANGE:
1135 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
1136 params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
1137 break;
1138 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001139 params[0] = mState.zNear;
1140 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001141 break;
1142 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001143 params[0] = mState.colorClearValue.red;
1144 params[1] = mState.colorClearValue.green;
1145 params[2] = mState.colorClearValue.blue;
1146 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001147 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001148 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001149 params[0] = mState.blendColor.red;
1150 params[1] = mState.blendColor.green;
1151 params[2] = mState.blendColor.blue;
1152 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001153 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001154 default:
1155 return false;
1156 }
1157
1158 return true;
1159}
1160
1161bool Context::getIntegerv(GLenum pname, GLint *params)
1162{
1163 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1164 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1165 // GetIntegerv as its native query function. As it would require conversion in any
1166 // case, this should make no difference to the calling application. You may find it in
1167 // Context::getFloatv.
1168 switch (pname)
1169 {
1170 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1171 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1172 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1173 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1174 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1175 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1176 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1177 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
1178 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1179 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1180 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1181 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001182 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer; break;
1183 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer; break;
1184 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
1185 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer; break;
1186 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1187 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1188 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1189 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1190 case GL_ACTIVE_TEXTURE: *params = mState.activeSampler; break;
1191 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1192 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1193 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1194 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1195 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1196 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1197 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1198 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1199 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1200 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1201 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1202 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1203 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1204 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1205 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1206 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1207 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1208 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1209 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1210 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1211 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1212 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001213 case GL_SUBPIXEL_BITS: *params = 4; break;
1214 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1215 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1216 case GL_SAMPLE_BUFFERS: *params = 0; break;
1217 case GL_SAMPLES: *params = 0; break;
1218 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1219 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1220 case GL_MAX_VIEWPORT_DIMS:
1221 {
1222 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1223 params[0] = maxDimension;
1224 params[1] = maxDimension;
1225 }
1226 break;
1227 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001228 params[0] = mState.viewportX;
1229 params[1] = mState.viewportY;
1230 params[2] = mState.viewportWidth;
1231 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001232 break;
1233 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001234 params[0] = mState.scissorX;
1235 params[1] = mState.scissorY;
1236 params[2] = mState.scissorWidth;
1237 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001238 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001239 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1240 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001241 case GL_RED_BITS:
1242 case GL_GREEN_BITS:
1243 case GL_BLUE_BITS:
1244 case GL_ALPHA_BITS:
1245 {
1246 gl::Framebuffer *framebuffer = getFramebuffer();
1247 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1248
1249 if (colorbuffer)
1250 {
1251 switch (pname)
1252 {
1253 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1254 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1255 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1256 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1257 }
1258 }
1259 else
1260 {
1261 *params = 0;
1262 }
1263 }
1264 break;
1265 case GL_DEPTH_BITS:
1266 {
1267 gl::Framebuffer *framebuffer = getFramebuffer();
1268 gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
1269
1270 if (depthbuffer)
1271 {
1272 *params = depthbuffer->getDepthSize();
1273 }
1274 else
1275 {
1276 *params = 0;
1277 }
1278 }
1279 break;
1280 case GL_STENCIL_BITS:
1281 {
1282 gl::Framebuffer *framebuffer = getFramebuffer();
1283 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1284
1285 if (stencilbuffer)
1286 {
1287 *params = stencilbuffer->getStencilSize();
1288 }
1289 else
1290 {
1291 *params = 0;
1292 }
1293 }
1294 break;
1295 case GL_TEXTURE_BINDING_2D:
1296 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001297 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001298 {
1299 error(GL_INVALID_OPERATION);
1300 return false;
1301 }
1302
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001303 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001304 }
1305 break;
1306 case GL_TEXTURE_BINDING_CUBE_MAP:
1307 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001308 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001309 {
1310 error(GL_INVALID_OPERATION);
1311 return false;
1312 }
1313
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001314 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001315 }
1316 break;
1317 default:
1318 return false;
1319 }
1320
1321 return true;
1322}
1323
1324bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1325{
1326 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1327 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1328 // to the fact that it is stored internally as a float, and so would require conversion
1329 // if returned from Context::getIntegerv. Since this conversion is already implemented
1330 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1331 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1332 // application.
1333 switch (pname)
1334 {
1335 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1336 case GL_SHADER_BINARY_FORMATS:
1337 {
1338 *type = GL_INT;
1339 *numParams = 0;
1340 }
1341 break;
1342 case GL_MAX_VERTEX_ATTRIBS:
1343 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1344 case GL_MAX_VARYING_VECTORS:
1345 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1346 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1347 case GL_MAX_TEXTURE_IMAGE_UNITS:
1348 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1349 case GL_MAX_RENDERBUFFER_SIZE:
1350 case GL_NUM_SHADER_BINARY_FORMATS:
1351 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1352 case GL_ARRAY_BUFFER_BINDING:
1353 case GL_FRAMEBUFFER_BINDING:
1354 case GL_RENDERBUFFER_BINDING:
1355 case GL_CURRENT_PROGRAM:
1356 case GL_PACK_ALIGNMENT:
1357 case GL_UNPACK_ALIGNMENT:
1358 case GL_GENERATE_MIPMAP_HINT:
1359 case GL_RED_BITS:
1360 case GL_GREEN_BITS:
1361 case GL_BLUE_BITS:
1362 case GL_ALPHA_BITS:
1363 case GL_DEPTH_BITS:
1364 case GL_STENCIL_BITS:
1365 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1366 case GL_CULL_FACE_MODE:
1367 case GL_FRONT_FACE:
1368 case GL_ACTIVE_TEXTURE:
1369 case GL_STENCIL_FUNC:
1370 case GL_STENCIL_VALUE_MASK:
1371 case GL_STENCIL_REF:
1372 case GL_STENCIL_FAIL:
1373 case GL_STENCIL_PASS_DEPTH_FAIL:
1374 case GL_STENCIL_PASS_DEPTH_PASS:
1375 case GL_STENCIL_BACK_FUNC:
1376 case GL_STENCIL_BACK_VALUE_MASK:
1377 case GL_STENCIL_BACK_REF:
1378 case GL_STENCIL_BACK_FAIL:
1379 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1380 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1381 case GL_DEPTH_FUNC:
1382 case GL_BLEND_SRC_RGB:
1383 case GL_BLEND_SRC_ALPHA:
1384 case GL_BLEND_DST_RGB:
1385 case GL_BLEND_DST_ALPHA:
1386 case GL_BLEND_EQUATION_RGB:
1387 case GL_BLEND_EQUATION_ALPHA:
1388 case GL_STENCIL_WRITEMASK:
1389 case GL_STENCIL_BACK_WRITEMASK:
1390 case GL_STENCIL_CLEAR_VALUE:
1391 case GL_SUBPIXEL_BITS:
1392 case GL_MAX_TEXTURE_SIZE:
1393 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1394 case GL_SAMPLE_BUFFERS:
1395 case GL_SAMPLES:
1396 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1397 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1398 case GL_TEXTURE_BINDING_2D:
1399 case GL_TEXTURE_BINDING_CUBE_MAP:
1400 {
1401 *type = GL_INT;
1402 *numParams = 1;
1403 }
1404 break;
1405 case GL_MAX_VIEWPORT_DIMS:
1406 {
1407 *type = GL_INT;
1408 *numParams = 2;
1409 }
1410 break;
1411 case GL_VIEWPORT:
1412 case GL_SCISSOR_BOX:
1413 {
1414 *type = GL_INT;
1415 *numParams = 4;
1416 }
1417 break;
1418 case GL_SHADER_COMPILER:
1419 case GL_SAMPLE_COVERAGE_INVERT:
1420 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001421 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1422 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1423 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1424 case GL_SAMPLE_COVERAGE:
1425 case GL_SCISSOR_TEST:
1426 case GL_STENCIL_TEST:
1427 case GL_DEPTH_TEST:
1428 case GL_BLEND:
1429 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001430 {
1431 *type = GL_BOOL;
1432 *numParams = 1;
1433 }
1434 break;
1435 case GL_COLOR_WRITEMASK:
1436 {
1437 *type = GL_BOOL;
1438 *numParams = 4;
1439 }
1440 break;
1441 case GL_POLYGON_OFFSET_FACTOR:
1442 case GL_POLYGON_OFFSET_UNITS:
1443 case GL_SAMPLE_COVERAGE_VALUE:
1444 case GL_DEPTH_CLEAR_VALUE:
1445 case GL_LINE_WIDTH:
1446 {
1447 *type = GL_FLOAT;
1448 *numParams = 1;
1449 }
1450 break;
1451 case GL_ALIASED_LINE_WIDTH_RANGE:
1452 case GL_ALIASED_POINT_SIZE_RANGE:
1453 case GL_DEPTH_RANGE:
1454 {
1455 *type = GL_FLOAT;
1456 *numParams = 2;
1457 }
1458 break;
1459 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001460 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001461 {
1462 *type = GL_FLOAT;
1463 *numParams = 4;
1464 }
1465 break;
1466 default:
1467 return false;
1468 }
1469
1470 return true;
1471}
1472
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001473// Applies the render target surface, depth stencil surface, viewport rectangle and
1474// scissor rectangle to the Direct3D 9 device
1475bool Context::applyRenderTarget(bool ignoreViewport)
1476{
1477 IDirect3DDevice9 *device = getDevice();
1478 Framebuffer *framebufferObject = getFramebuffer();
1479
1480 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1481 {
1482 return false;
1483 }
1484
1485 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1486 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1487
1488 device->SetRenderTarget(0, renderTarget);
1489 device->SetDepthStencilSurface(depthStencil);
1490
1491 D3DVIEWPORT9 viewport;
1492 D3DSURFACE_DESC desc;
1493 renderTarget->GetDesc(&desc);
1494
1495 if (ignoreViewport)
1496 {
1497 viewport.X = 0;
1498 viewport.Y = 0;
1499 viewport.Width = desc.Width;
1500 viewport.Height = desc.Height;
1501 viewport.MinZ = 0.0f;
1502 viewport.MaxZ = 1.0f;
1503 }
1504 else
1505 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001506 viewport.X = std::max(mState.viewportX, 0);
1507 viewport.Y = std::max(mState.viewportY, 0);
1508 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1509 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1510 viewport.MinZ = clamp01(mState.zNear);
1511 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001512 }
1513
1514 device->SetViewport(&viewport);
1515
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001516 if (mState.scissorTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001517 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001518 RECT rect = {mState.scissorX,
1519 mState.scissorY,
1520 mState.scissorX + mState.scissorWidth,
1521 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001522
1523 device->SetScissorRect(&rect);
1524 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1525 }
1526 else
1527 {
1528 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1529 }
1530
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001531 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001532 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001533 Program *programObject = getCurrentProgram();
1534
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001535 GLint halfPixelSize = programObject->getUniformLocation("dx_HalfPixelSize");
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001536 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001537 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001538
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001539 GLint window = programObject->getUniformLocation("dx_Window");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001540 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1541 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1542 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001543 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1544
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001545 GLint depth = programObject->getUniformLocation("dx_Depth");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001546 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001547 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1548
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001549 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001550 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001551
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001552 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001553 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001554
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001555 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001556 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001557 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001558 }
1559
1560 return true;
1561}
1562
1563// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001564void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001565{
1566 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001567 Program *programObject = getCurrentProgram();
1568
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001569 GLint frontCCW = programObject->getUniformLocation("dx_FrontCCW");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001570 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001571 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001572
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001573 GLint pointsOrLines = programObject->getUniformLocation("dx_PointsOrLines");
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001574 GLint alwaysFront = !isTriangleMode(drawMode);
1575 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1576
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001577 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001578 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001579 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001580 }
1581 else
1582 {
1583 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1584 }
1585
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001586 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001587 {
1588 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001589 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001590 }
1591 else
1592 {
1593 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
1594 }
1595
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001596 if (mState.blend)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001597 {
1598 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1599
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001600 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1601 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001602 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001603 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001604 }
1605 else
1606 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001607 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1608 unorm<8>(mState.blendColor.alpha),
1609 unorm<8>(mState.blendColor.alpha),
1610 unorm<8>(mState.blendColor.alpha)));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001611 }
1612
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001613 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1614 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1615 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001616
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001617 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1618 mState.destBlendRGB != mState.destBlendAlpha ||
1619 mState.blendEquationRGB != mState.blendEquationAlpha)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001620 {
1621 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1622
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001623 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1624 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1625 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001626
1627 }
1628 else
1629 {
1630 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1631 }
1632 }
1633 else
1634 {
1635 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1636 }
1637
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001638 if (mState.stencilTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001639 {
1640 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1641 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1642
1643 // FIXME: Unsupported by D3D9
1644 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1645 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1646 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001647 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1648 mState.stencilRef != mState.stencilBackRef ||
1649 mState.stencilMask != mState.stencilBackMask)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001650 {
1651 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1652 return error(GL_INVALID_OPERATION);
1653 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001654
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001655 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1656 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1657 es2dx::ConvertComparison(mState.stencilFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001658
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001659 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilRef); // FIXME: Clamp to range
1660 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001661
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001662 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1663 es2dx::ConvertStencilOp(mState.stencilFail));
1664 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1665 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1666 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1667 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001668
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001669 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1670 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1671 es2dx::ConvertComparison(mState.stencilBackFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001672
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001673 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilBackRef); // FIXME: Clamp to range
1674 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001675
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001676 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1677 es2dx::ConvertStencilOp(mState.stencilBackFail));
1678 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1679 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1680 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1681 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001682 }
1683 else
1684 {
1685 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1686 }
1687
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001688 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1689 mState.colorMaskBlue, mState.colorMaskAlpha));
1690 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001691
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001692 if (mState.polygonOffsetFill)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001693 {
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001694 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1695 if (depthbuffer)
1696 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001697 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1698 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001699 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1700 }
1701 }
1702 else
1703 {
1704 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1705 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001706 }
1707
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001708 if (mConfig->mMultiSample != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001709 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001710 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001711 {
1712 FIXME("Sample alpha to coverage is unimplemented.");
1713 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001714
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001715 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001716 {
1717 FIXME("Sample coverage is unimplemented.");
1718 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001719 }
1720
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001721 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001722}
1723
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001724// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001725void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001726{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001727 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001728 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001729 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001730 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001731 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001732 }
1733 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001734}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001735
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001736void Context::applyVertexBuffer(GLint first, GLsizei count)
1737{
1738 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1739
1740 mVertexDataManager->preRenderValidate(first, count, translated);
1741
1742 lookupAttributeMapping(translated);
1743
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001744 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001745}
1746
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001747void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001748{
1749 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1750
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00001751 mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001752
1753 lookupAttributeMapping(translated);
1754
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001755 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001756}
1757
1758// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001759TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001760{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001761 TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001762 mBufferBackEnd->setupIndicesPreDraw(indexInfo);
1763 return indexInfo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001764}
1765
1766// Applies the shaders and shader constants to the Direct3D 9 device
1767void Context::applyShaders()
1768{
1769 IDirect3DDevice9 *device = getDevice();
1770 Program *programObject = getCurrentProgram();
1771 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1772 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1773
1774 device->SetVertexShader(vertexShader);
1775 device->SetPixelShader(pixelShader);
1776
1777 programObject->applyUniforms();
1778}
1779
1780// Applies the textures and sampler states to the Direct3D 9 device
1781void Context::applyTextures()
1782{
1783 IDirect3DDevice9 *device = getDevice();
1784 Program *programObject = getCurrentProgram();
1785
1786 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1787 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001788 int textureUnit = programObject->getSamplerMapping(sampler);
1789 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001790 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001791 SamplerType textureType = programObject->getSamplerType(sampler);
1792
1793 Texture *texture = getSamplerTexture(textureUnit, textureType);
1794
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001795 if (texture->isComplete())
1796 {
1797 GLenum wrapS = texture->getWrapS();
1798 GLenum wrapT = texture->getWrapT();
1799 GLenum minFilter = texture->getMinFilter();
1800 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001801
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001802 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1803 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001804
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001805 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1806 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1807 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1808 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1809 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001810
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001811 device->SetTexture(sampler, texture->getTexture());
1812 }
1813 else
1814 {
1815 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1816 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001817 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001818 else
1819 {
1820 device->SetTexture(sampler, NULL);
1821 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001822 }
1823}
1824
1825void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1826{
1827 Framebuffer *framebuffer = getFramebuffer();
1828 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1829 IDirect3DDevice9 *device = getDevice();
1830
1831 D3DSURFACE_DESC desc;
1832 renderTarget->GetDesc(&desc);
1833
1834 IDirect3DSurface9 *systemSurface;
1835 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1836
1837 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1838 {
1839 return error(GL_OUT_OF_MEMORY);
1840 }
1841
1842 ASSERT(SUCCEEDED(result));
1843
1844 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1845 {
1846 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1847 }
1848
1849 result = device->GetRenderTargetData(renderTarget, systemSurface);
1850
1851 if (result == D3DERR_DRIVERINTERNALERROR)
1852 {
1853 systemSurface->Release();
1854
1855 return error(GL_OUT_OF_MEMORY);
1856 }
1857
1858 if (FAILED(result))
1859 {
1860 UNREACHABLE();
1861 systemSurface->Release();
1862
1863 return; // No sensible error to generate
1864 }
1865
1866 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001867 RECT rect = {std::max(x, 0),
1868 std::max(y, 0),
1869 std::min(x + width, (int)desc.Width),
1870 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001871
1872 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1873
1874 if (FAILED(result))
1875 {
1876 UNREACHABLE();
1877 systemSurface->Release();
1878
1879 return; // No sensible error to generate
1880 }
1881
1882 unsigned char *source = (unsigned char*)lock.pBits;
1883 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001884 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001885
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001886 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001887
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001888 for (int j = 0; j < rect.bottom - rect.top; j++)
1889 {
1890 for (int i = 0; i < rect.right - rect.left; i++)
1891 {
1892 float r;
1893 float g;
1894 float b;
1895 float a;
1896
1897 switch (desc.Format)
1898 {
1899 case D3DFMT_R5G6B5:
1900 {
1901 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1902
1903 a = 1.0f;
1904 b = (rgb & 0x001F) * (1.0f / 0x001F);
1905 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1906 r = (rgb & 0xF800) * (1.0f / 0xF800);
1907 }
1908 break;
1909 case D3DFMT_X1R5G5B5:
1910 {
1911 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1912
1913 a = 1.0f;
1914 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1915 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1916 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1917 }
1918 break;
1919 case D3DFMT_A1R5G5B5:
1920 {
1921 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1922
1923 a = (argb & 0x8000) ? 1.0f : 0.0f;
1924 b = (argb & 0x001F) * (1.0f / 0x001F);
1925 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1926 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1927 }
1928 break;
1929 case D3DFMT_A8R8G8B8:
1930 {
1931 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1932
1933 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1934 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1935 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1936 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1937 }
1938 break;
1939 case D3DFMT_X8R8G8B8:
1940 {
1941 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1942
1943 a = 1.0f;
1944 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
1945 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
1946 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
1947 }
1948 break;
1949 case D3DFMT_A2R10G10B10:
1950 {
1951 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1952
1953 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
1954 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
1955 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
1956 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
1957 }
1958 break;
1959 default:
1960 UNIMPLEMENTED(); // FIXME
1961 UNREACHABLE();
1962 }
1963
1964 switch (format)
1965 {
1966 case GL_RGBA:
1967 switch (type)
1968 {
1969 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001970 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
1971 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
1972 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
1973 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001974 break;
1975 default: UNREACHABLE();
1976 }
1977 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001978 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001979 switch (type)
1980 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001981 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001982 dest16[i + j * outputPitch / sizeof(unsigned short)] =
1983 ((unsigned short)(31 * b + 0.5f) << 0) |
1984 ((unsigned short)(63 * g + 0.5f) << 5) |
1985 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001986 break;
1987 default: UNREACHABLE();
1988 }
1989 break;
1990 default: UNREACHABLE();
1991 }
1992 }
1993 }
1994
1995 systemSurface->UnlockRect();
1996
1997 systemSurface->Release();
1998}
1999
2000void Context::clear(GLbitfield mask)
2001{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002002 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002003 IDirect3DDevice9 *device = getDevice();
2004 DWORD flags = 0;
2005
2006 if (mask & GL_COLOR_BUFFER_BIT)
2007 {
2008 mask &= ~GL_COLOR_BUFFER_BIT;
2009 flags |= D3DCLEAR_TARGET;
2010 }
2011
2012 if (mask & GL_DEPTH_BUFFER_BIT)
2013 {
2014 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002015 if (mState.depthMask)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002016 {
2017 flags |= D3DCLEAR_ZBUFFER;
2018 }
2019 }
2020
2021 Framebuffer *framebufferObject = getFramebuffer();
2022 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
2023
2024 GLuint stencilUnmasked = 0x0;
2025
2026 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
2027 {
2028 D3DSURFACE_DESC desc;
2029 depthStencil->GetDesc(&desc);
2030
2031 mask &= ~GL_STENCIL_BUFFER_BIT;
2032 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2033 stencilUnmasked = (0x1 << stencilSize) - 1;
2034
2035 if (stencilUnmasked != 0x0)
2036 {
2037 flags |= D3DCLEAR_STENCIL;
2038 }
2039 }
2040
2041 if (mask != 0)
2042 {
2043 return error(GL_INVALID_VALUE);
2044 }
2045
2046 applyRenderTarget(true); // Clips the clear to the scissor rectangle but not the viewport
2047
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002048 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2049 unorm<8>(mState.colorClearValue.red),
2050 unorm<8>(mState.colorClearValue.green),
2051 unorm<8>(mState.colorClearValue.blue));
2052 float depth = clamp01(mState.depthClearValue);
2053 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002054
2055 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2056
2057 D3DSURFACE_DESC desc;
2058 renderTarget->GetDesc(&desc);
2059
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002060 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002061
2062 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002063 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002064 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002065 !(mState.colorMaskRed && mState.colorMaskGreen &&
2066 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002067
2068 if (needMaskedColorClear || needMaskedStencilClear)
2069 {
2070 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2071 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2072 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2073 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2074 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2075 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2076 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2077 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2078
2079 if (flags & D3DCLEAR_TARGET)
2080 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002081 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2082 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2083 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2084 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002085 }
2086 else
2087 {
2088 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2089 }
2090
2091 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2092 {
2093 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2094 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2095 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2096 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002097 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002098 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002099 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2100 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
2101 }
2102 else
2103 {
2104 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2105 }
2106
2107 device->SetPixelShader(NULL);
2108 device->SetVertexShader(NULL);
2109 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2110
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002111 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002112 {
2113 float x, y, z, w;
2114 D3DCOLOR diffuse;
2115 };
2116
2117 Vertex quad[4];
2118 quad[0].x = 0.0f;
2119 quad[0].y = (float)desc.Height;
2120 quad[0].z = 0.0f;
2121 quad[0].w = 1.0f;
2122 quad[0].diffuse = color;
2123
2124 quad[1].x = (float)desc.Width;
2125 quad[1].y = (float)desc.Height;
2126 quad[1].z = 0.0f;
2127 quad[1].w = 1.0f;
2128 quad[1].diffuse = color;
2129
2130 quad[2].x = 0.0f;
2131 quad[2].y = 0.0f;
2132 quad[2].z = 0.0f;
2133 quad[2].w = 1.0f;
2134 quad[2].diffuse = color;
2135
2136 quad[3].x = (float)desc.Width;
2137 quad[3].y = 0.0f;
2138 quad[3].z = 0.0f;
2139 quad[3].w = 1.0f;
2140 quad[3].diffuse = color;
2141
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002142 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002143 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002144
2145 if (flags & D3DCLEAR_ZBUFFER)
2146 {
2147 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2148 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2149 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2150 }
2151 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002152 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002153 {
2154 device->Clear(0, NULL, flags, color, depth, stencil);
2155 }
2156}
2157
2158void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2159{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002160 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002161 {
2162 return error(GL_INVALID_OPERATION);
2163 }
2164
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002165 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002166 IDirect3DDevice9 *device = getDevice();
2167 D3DPRIMITIVETYPE primitiveType;
2168 int primitiveCount;
2169
2170 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2171 return error(GL_INVALID_ENUM);
2172
2173 if (primitiveCount <= 0)
2174 {
2175 return;
2176 }
2177
2178 if (!applyRenderTarget(false))
2179 {
2180 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
2181 }
2182
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002183 applyState(mode);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002184 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002185 applyShaders();
2186 applyTextures();
2187
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002188 if (!getCurrentProgram()->validateSamplers())
2189 {
2190 return error(GL_INVALID_OPERATION);
2191 }
2192
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002193 if (!cullSkipsDraw(mode))
2194 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002195 display->startScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002196 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002197 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002198}
2199
2200void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2201{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002202 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002203 {
2204 return error(GL_INVALID_OPERATION);
2205 }
2206
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002207 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002208 {
2209 return error(GL_INVALID_OPERATION);
2210 }
2211
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002212 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002213 IDirect3DDevice9 *device = getDevice();
2214 D3DPRIMITIVETYPE primitiveType;
2215 int primitiveCount;
2216
2217 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2218 return error(GL_INVALID_ENUM);
2219
2220 if (primitiveCount <= 0)
2221 {
2222 return;
2223 }
2224
2225 if (!applyRenderTarget(false))
2226 {
2227 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
2228 }
2229
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002230 applyState(mode);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002231 TranslatedIndexData indexInfo = applyIndexBuffer(indices, count, mode, type);
2232 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002233 applyShaders();
2234 applyTextures();
2235
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002236 if (!getCurrentProgram()->validateSamplers())
2237 {
2238 return error(GL_INVALID_OPERATION);
2239 }
2240
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002241 if (!cullSkipsDraw(mode))
2242 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002243 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002244 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002245 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002246}
2247
2248void Context::finish()
2249{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002250 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002251 IDirect3DDevice9 *device = getDevice();
2252 IDirect3DQuery9 *occlusionQuery = NULL;
2253
2254 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2255
2256 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2257 {
2258 return error(GL_OUT_OF_MEMORY);
2259 }
2260
2261 ASSERT(SUCCEEDED(result));
2262
2263 if (occlusionQuery)
2264 {
2265 occlusionQuery->Issue(D3DISSUE_BEGIN);
2266
2267 // Render something outside the render target
2268 device->SetPixelShader(NULL);
2269 device->SetVertexShader(NULL);
2270 device->SetFVF(D3DFVF_XYZRHW);
2271 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002272 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002273 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002274
2275 occlusionQuery->Issue(D3DISSUE_END);
2276
2277 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2278 {
2279 // Keep polling, but allow other threads to do something useful first
2280 Sleep(0);
2281 }
2282
2283 occlusionQuery->Release();
2284 }
2285}
2286
2287void Context::flush()
2288{
2289 IDirect3DDevice9 *device = getDevice();
2290 IDirect3DQuery9 *eventQuery = NULL;
2291
2292 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2293
2294 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2295 {
2296 return error(GL_OUT_OF_MEMORY);
2297 }
2298
2299 ASSERT(SUCCEEDED(result));
2300
2301 if (eventQuery)
2302 {
2303 eventQuery->Issue(D3DISSUE_END);
2304
2305 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2306 {
2307 // Keep polling, but allow other threads to do something useful first
2308 Sleep(0);
2309 }
2310
2311 eventQuery->Release();
2312 }
2313}
2314
2315void Context::recordInvalidEnum()
2316{
2317 mInvalidEnum = true;
2318}
2319
2320void Context::recordInvalidValue()
2321{
2322 mInvalidValue = true;
2323}
2324
2325void Context::recordInvalidOperation()
2326{
2327 mInvalidOperation = true;
2328}
2329
2330void Context::recordOutOfMemory()
2331{
2332 mOutOfMemory = true;
2333}
2334
2335void Context::recordInvalidFramebufferOperation()
2336{
2337 mInvalidFramebufferOperation = true;
2338}
2339
2340// Get one of the recorded errors and clear its flag, if any.
2341// [OpenGL ES 2.0.24] section 2.5 page 13.
2342GLenum Context::getError()
2343{
2344 if (mInvalidEnum)
2345 {
2346 mInvalidEnum = false;
2347
2348 return GL_INVALID_ENUM;
2349 }
2350
2351 if (mInvalidValue)
2352 {
2353 mInvalidValue = false;
2354
2355 return GL_INVALID_VALUE;
2356 }
2357
2358 if (mInvalidOperation)
2359 {
2360 mInvalidOperation = false;
2361
2362 return GL_INVALID_OPERATION;
2363 }
2364
2365 if (mOutOfMemory)
2366 {
2367 mOutOfMemory = false;
2368
2369 return GL_OUT_OF_MEMORY;
2370 }
2371
2372 if (mInvalidFramebufferOperation)
2373 {
2374 mInvalidFramebufferOperation = false;
2375
2376 return GL_INVALID_FRAMEBUFFER_OPERATION;
2377 }
2378
2379 return GL_NO_ERROR;
2380}
2381
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002382const char *Context::getPixelShaderProfile()
2383{
2384 return mPsProfile;
2385}
2386
2387const char *Context::getVertexShaderProfile()
2388{
2389 return mVsProfile;
2390}
2391
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002392void Context::detachBuffer(GLuint buffer)
2393{
2394 // [OpenGL ES 2.0.24] section 2.9 page 22:
2395 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2396 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2397
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002398 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002399 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002400 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002401 }
2402
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002403 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002404 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002405 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002406 }
2407
2408 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2409 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002410 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002411 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002412 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002413 }
2414 }
2415}
2416
2417void Context::detachTexture(GLuint texture)
2418{
2419 // [OpenGL ES 2.0.24] section 3.8 page 84:
2420 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2421 // rebound to texture object zero
2422
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002423 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002424 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002425 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002426 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002427 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002428 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002429 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002430 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002431 }
2432 }
2433
2434 // [OpenGL ES 2.0.24] section 4.4 page 112:
2435 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2436 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2437 // image was attached in the currently bound framebuffer.
2438
2439 Framebuffer *framebuffer = getFramebuffer();
2440
2441 if (framebuffer)
2442 {
2443 framebuffer->detachTexture(texture);
2444 }
2445}
2446
2447void Context::detachFramebuffer(GLuint framebuffer)
2448{
2449 // [OpenGL ES 2.0.24] section 4.4 page 107:
2450 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2451 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2452
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002453 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002454 {
2455 bindFramebuffer(0);
2456 }
2457}
2458
2459void Context::detachRenderbuffer(GLuint renderbuffer)
2460{
2461 // [OpenGL ES 2.0.24] section 4.4 page 109:
2462 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2463 // had been executed with the target RENDERBUFFER and name of zero.
2464
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002465 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002466 {
2467 bindRenderbuffer(0);
2468 }
2469
2470 // [OpenGL ES 2.0.24] section 4.4 page 111:
2471 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2472 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2473 // point to which this image was attached in the currently bound framebuffer.
2474
2475 Framebuffer *framebuffer = getFramebuffer();
2476
2477 if (framebuffer)
2478 {
2479 framebuffer->detachRenderbuffer(renderbuffer);
2480 }
2481}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002482
2483Texture *Context::getIncompleteTexture(SamplerType type)
2484{
2485 Texture *t = mIncompleteTextures[type];
2486
2487 if (t == NULL)
2488 {
2489 static const GLubyte color[] = { 0, 0, 0, 255 };
2490
2491 switch (type)
2492 {
2493 default:
2494 UNREACHABLE();
2495 // default falls through to SAMPLER_2D
2496
2497 case SAMPLER_2D:
2498 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002499 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002500 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002501 t = incomplete2d;
2502 }
2503 break;
2504
2505 case SAMPLER_CUBE:
2506 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002507 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002508
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002509 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2510 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2511 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2512 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2513 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2514 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002515
2516 t = incompleteCube;
2517 }
2518 break;
2519 }
2520
2521 mIncompleteTextures[type] = t;
2522 }
2523
2524 return t;
2525}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002526
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002527bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002528{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002529 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002530}
2531
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002532bool Context::isTriangleMode(GLenum drawMode)
2533{
2534 switch (drawMode)
2535 {
2536 case GL_TRIANGLES:
2537 case GL_TRIANGLE_FAN:
2538 case GL_TRIANGLE_STRIP:
2539 return true;
2540 case GL_POINTS:
2541 case GL_LINES:
2542 case GL_LINE_LOOP:
2543 case GL_LINE_STRIP:
2544 return false;
2545 default: UNREACHABLE();
2546 }
2547
2548 return false;
2549}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002550
2551void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2552{
2553 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2554
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002555 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2556 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2557 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2558 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002559
2560 mVertexDataManager->dirtyCurrentValues();
2561}
2562
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002563void Context::initExtensionString()
2564{
2565 if (mBufferBackEnd->supportIntIndices())
2566 {
2567 mExtensionString += "GL_OES_element_index_uint ";
2568 }
2569
2570 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2571 if (end != std::string::npos)
2572 {
2573 mExtensionString.resize(end+1);
2574 }
2575}
2576
2577const char *Context::getExtensionString() const
2578{
2579 return mExtensionString.c_str();
2580}
2581
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002582}
2583
2584extern "C"
2585{
2586gl::Context *glCreateContext(const egl::Config *config)
2587{
2588 return new gl::Context(config);
2589}
2590
2591void glDestroyContext(gl::Context *context)
2592{
2593 delete context;
2594
2595 if (context == gl::getContext())
2596 {
2597 gl::makeCurrent(NULL, NULL, NULL);
2598 }
2599}
2600
2601void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2602{
2603 gl::makeCurrent(context, display, surface);
2604}
2605
2606gl::Context *glGetCurrentContext()
2607{
2608 return gl::getContext();
2609}
2610}