blob: 94836802cc701ba1bfe7f70928f6d502b2e3eecb [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 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001482 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1483
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001484 return false;
1485 }
1486
1487 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1488 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1489
1490 device->SetRenderTarget(0, renderTarget);
1491 device->SetDepthStencilSurface(depthStencil);
1492
1493 D3DVIEWPORT9 viewport;
1494 D3DSURFACE_DESC desc;
1495 renderTarget->GetDesc(&desc);
1496
1497 if (ignoreViewport)
1498 {
1499 viewport.X = 0;
1500 viewport.Y = 0;
1501 viewport.Width = desc.Width;
1502 viewport.Height = desc.Height;
1503 viewport.MinZ = 0.0f;
1504 viewport.MaxZ = 1.0f;
1505 }
1506 else
1507 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001508 viewport.X = std::max(mState.viewportX, 0);
1509 viewport.Y = std::max(mState.viewportY, 0);
1510 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1511 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1512 viewport.MinZ = clamp01(mState.zNear);
1513 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001514 }
1515
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001516 if (viewport.Width <= 0 || viewport.Height <= 0)
1517 {
1518 return false; // Nothing to render
1519 }
1520
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001521 device->SetViewport(&viewport);
1522
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001523 if (mState.scissorTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001524 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001525 RECT rect = {mState.scissorX,
1526 mState.scissorY,
1527 mState.scissorX + mState.scissorWidth,
1528 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001529
1530 device->SetScissorRect(&rect);
1531 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1532 }
1533 else
1534 {
1535 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1536 }
1537
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001538 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001539 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001540 Program *programObject = getCurrentProgram();
1541
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001542 GLint halfPixelSize = programObject->getUniformLocation("dx_HalfPixelSize");
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001543 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001544 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001545
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001546 GLint window = programObject->getUniformLocation("dx_Window");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001547 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1548 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1549 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001550 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1551
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001552 GLint depth = programObject->getUniformLocation("dx_Depth");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001553 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001554 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1555
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001556 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001557 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001558
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001559 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001560 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001561
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001562 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001563 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001564 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001565 }
1566
1567 return true;
1568}
1569
1570// 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 +00001571void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001572{
1573 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001574 Program *programObject = getCurrentProgram();
1575
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001576 GLint frontCCW = programObject->getUniformLocation("dx_FrontCCW");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001577 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001578 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001579
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001580 GLint pointsOrLines = programObject->getUniformLocation("dx_PointsOrLines");
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001581 GLint alwaysFront = !isTriangleMode(drawMode);
1582 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1583
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001584 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001585 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001586 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001587 }
1588 else
1589 {
1590 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1591 }
1592
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001593 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001594 {
1595 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001596 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001597 }
1598 else
1599 {
1600 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
1601 }
1602
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001603 if (mState.blend)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001604 {
1605 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1606
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001607 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1608 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001609 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001610 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001611 }
1612 else
1613 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001614 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1615 unorm<8>(mState.blendColor.alpha),
1616 unorm<8>(mState.blendColor.alpha),
1617 unorm<8>(mState.blendColor.alpha)));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001618 }
1619
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001620 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1621 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1622 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001623
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001624 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1625 mState.destBlendRGB != mState.destBlendAlpha ||
1626 mState.blendEquationRGB != mState.blendEquationAlpha)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001627 {
1628 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1629
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001630 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1631 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1632 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001633
1634 }
1635 else
1636 {
1637 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1638 }
1639 }
1640 else
1641 {
1642 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1643 }
1644
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001645 if (mState.stencilTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001646 {
1647 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1648 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1649
1650 // FIXME: Unsupported by D3D9
1651 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1652 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1653 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001654 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1655 mState.stencilRef != mState.stencilBackRef ||
1656 mState.stencilMask != mState.stencilBackMask)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001657 {
1658 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1659 return error(GL_INVALID_OPERATION);
1660 }
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_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1663 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1664 es2dx::ConvertComparison(mState.stencilFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001665
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001666 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilRef); // FIXME: Clamp to range
1667 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001668
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001669 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1670 es2dx::ConvertStencilOp(mState.stencilFail));
1671 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1672 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1673 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1674 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
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_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1677 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1678 es2dx::ConvertComparison(mState.stencilBackFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001679
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001680 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilBackRef); // FIXME: Clamp to range
1681 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001682
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001683 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1684 es2dx::ConvertStencilOp(mState.stencilBackFail));
1685 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1686 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1687 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1688 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001689 }
1690 else
1691 {
1692 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1693 }
1694
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001695 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1696 mState.colorMaskBlue, mState.colorMaskAlpha));
1697 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001698
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001699 if (mState.polygonOffsetFill)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001700 {
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001701 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1702 if (depthbuffer)
1703 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001704 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1705 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001706 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1707 }
1708 }
1709 else
1710 {
1711 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1712 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001713 }
1714
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001715 if (mConfig->mMultiSample != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001716 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001717 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001718 {
1719 FIXME("Sample alpha to coverage is unimplemented.");
1720 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001721
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001722 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001723 {
1724 FIXME("Sample coverage is unimplemented.");
1725 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001726 }
1727
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001728 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001729}
1730
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001731// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001732void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001733{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001734 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001735 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001736 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001737 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001738 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001739 }
1740 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001741}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001742
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001743void Context::applyVertexBuffer(GLint first, GLsizei count)
1744{
1745 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1746
1747 mVertexDataManager->preRenderValidate(first, count, translated);
1748
1749 lookupAttributeMapping(translated);
1750
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001751 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001752}
1753
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001754void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001755{
1756 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1757
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00001758 mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001759
1760 lookupAttributeMapping(translated);
1761
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001762 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001763}
1764
1765// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001766TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001767{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001768 TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001769 mBufferBackEnd->setupIndicesPreDraw(indexInfo);
1770 return indexInfo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001771}
1772
1773// Applies the shaders and shader constants to the Direct3D 9 device
1774void Context::applyShaders()
1775{
1776 IDirect3DDevice9 *device = getDevice();
1777 Program *programObject = getCurrentProgram();
1778 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1779 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1780
1781 device->SetVertexShader(vertexShader);
1782 device->SetPixelShader(pixelShader);
1783
1784 programObject->applyUniforms();
1785}
1786
1787// Applies the textures and sampler states to the Direct3D 9 device
1788void Context::applyTextures()
1789{
1790 IDirect3DDevice9 *device = getDevice();
1791 Program *programObject = getCurrentProgram();
1792
1793 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1794 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001795 int textureUnit = programObject->getSamplerMapping(sampler);
1796 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001797 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001798 SamplerType textureType = programObject->getSamplerType(sampler);
1799
1800 Texture *texture = getSamplerTexture(textureUnit, textureType);
1801
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001802 if (texture->isComplete())
1803 {
1804 GLenum wrapS = texture->getWrapS();
1805 GLenum wrapT = texture->getWrapT();
1806 GLenum minFilter = texture->getMinFilter();
1807 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001808
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001809 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1810 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001811
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001812 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1813 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1814 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1815 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1816 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001817
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001818 device->SetTexture(sampler, texture->getTexture());
1819 }
1820 else
1821 {
1822 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1823 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001824 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001825 else
1826 {
1827 device->SetTexture(sampler, NULL);
1828 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001829 }
1830}
1831
1832void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1833{
1834 Framebuffer *framebuffer = getFramebuffer();
1835 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1836 IDirect3DDevice9 *device = getDevice();
1837
1838 D3DSURFACE_DESC desc;
1839 renderTarget->GetDesc(&desc);
1840
1841 IDirect3DSurface9 *systemSurface;
1842 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1843
1844 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1845 {
1846 return error(GL_OUT_OF_MEMORY);
1847 }
1848
1849 ASSERT(SUCCEEDED(result));
1850
1851 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1852 {
1853 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1854 }
1855
1856 result = device->GetRenderTargetData(renderTarget, systemSurface);
1857
1858 if (result == D3DERR_DRIVERINTERNALERROR)
1859 {
1860 systemSurface->Release();
1861
1862 return error(GL_OUT_OF_MEMORY);
1863 }
1864
1865 if (FAILED(result))
1866 {
1867 UNREACHABLE();
1868 systemSurface->Release();
1869
1870 return; // No sensible error to generate
1871 }
1872
1873 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001874 RECT rect = {std::max(x, 0),
1875 std::max(y, 0),
1876 std::min(x + width, (int)desc.Width),
1877 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001878
1879 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1880
1881 if (FAILED(result))
1882 {
1883 UNREACHABLE();
1884 systemSurface->Release();
1885
1886 return; // No sensible error to generate
1887 }
1888
1889 unsigned char *source = (unsigned char*)lock.pBits;
1890 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001891 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001892
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001893 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001894
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001895 for (int j = 0; j < rect.bottom - rect.top; j++)
1896 {
1897 for (int i = 0; i < rect.right - rect.left; i++)
1898 {
1899 float r;
1900 float g;
1901 float b;
1902 float a;
1903
1904 switch (desc.Format)
1905 {
1906 case D3DFMT_R5G6B5:
1907 {
1908 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1909
1910 a = 1.0f;
1911 b = (rgb & 0x001F) * (1.0f / 0x001F);
1912 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1913 r = (rgb & 0xF800) * (1.0f / 0xF800);
1914 }
1915 break;
1916 case D3DFMT_X1R5G5B5:
1917 {
1918 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1919
1920 a = 1.0f;
1921 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1922 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1923 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1924 }
1925 break;
1926 case D3DFMT_A1R5G5B5:
1927 {
1928 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1929
1930 a = (argb & 0x8000) ? 1.0f : 0.0f;
1931 b = (argb & 0x001F) * (1.0f / 0x001F);
1932 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1933 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1934 }
1935 break;
1936 case D3DFMT_A8R8G8B8:
1937 {
1938 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1939
1940 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1941 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1942 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1943 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1944 }
1945 break;
1946 case D3DFMT_X8R8G8B8:
1947 {
1948 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1949
1950 a = 1.0f;
1951 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
1952 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
1953 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
1954 }
1955 break;
1956 case D3DFMT_A2R10G10B10:
1957 {
1958 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1959
1960 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
1961 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
1962 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
1963 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
1964 }
1965 break;
1966 default:
1967 UNIMPLEMENTED(); // FIXME
1968 UNREACHABLE();
1969 }
1970
1971 switch (format)
1972 {
1973 case GL_RGBA:
1974 switch (type)
1975 {
1976 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001977 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
1978 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
1979 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
1980 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001981 break;
1982 default: UNREACHABLE();
1983 }
1984 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001985 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001986 switch (type)
1987 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001988 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001989 dest16[i + j * outputPitch / sizeof(unsigned short)] =
1990 ((unsigned short)(31 * b + 0.5f) << 0) |
1991 ((unsigned short)(63 * g + 0.5f) << 5) |
1992 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001993 break;
1994 default: UNREACHABLE();
1995 }
1996 break;
1997 default: UNREACHABLE();
1998 }
1999 }
2000 }
2001
2002 systemSurface->UnlockRect();
2003
2004 systemSurface->Release();
2005}
2006
2007void Context::clear(GLbitfield mask)
2008{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002009 Framebuffer *framebufferObject = getFramebuffer();
2010
2011 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2012 {
2013 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2014
2015 return;
2016 }
2017
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002018 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002019 IDirect3DDevice9 *device = getDevice();
2020 DWORD flags = 0;
2021
2022 if (mask & GL_COLOR_BUFFER_BIT)
2023 {
2024 mask &= ~GL_COLOR_BUFFER_BIT;
2025 flags |= D3DCLEAR_TARGET;
2026 }
2027
2028 if (mask & GL_DEPTH_BUFFER_BIT)
2029 {
2030 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002031 if (mState.depthMask)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002032 {
2033 flags |= D3DCLEAR_ZBUFFER;
2034 }
2035 }
2036
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002037 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
2038
2039 GLuint stencilUnmasked = 0x0;
2040
2041 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
2042 {
2043 D3DSURFACE_DESC desc;
2044 depthStencil->GetDesc(&desc);
2045
2046 mask &= ~GL_STENCIL_BUFFER_BIT;
2047 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2048 stencilUnmasked = (0x1 << stencilSize) - 1;
2049
2050 if (stencilUnmasked != 0x0)
2051 {
2052 flags |= D3DCLEAR_STENCIL;
2053 }
2054 }
2055
2056 if (mask != 0)
2057 {
2058 return error(GL_INVALID_VALUE);
2059 }
2060
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002061 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2062 {
2063 return;
2064 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002065
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002066 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2067 unorm<8>(mState.colorClearValue.red),
2068 unorm<8>(mState.colorClearValue.green),
2069 unorm<8>(mState.colorClearValue.blue));
2070 float depth = clamp01(mState.depthClearValue);
2071 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002072
2073 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2074
2075 D3DSURFACE_DESC desc;
2076 renderTarget->GetDesc(&desc);
2077
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002078 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002079
2080 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002081 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002082 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002083 !(mState.colorMaskRed && mState.colorMaskGreen &&
2084 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002085
2086 if (needMaskedColorClear || needMaskedStencilClear)
2087 {
2088 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2089 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2090 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2091 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2092 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2093 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2094 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2095 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2096
2097 if (flags & D3DCLEAR_TARGET)
2098 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002099 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2100 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2101 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2102 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002103 }
2104 else
2105 {
2106 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2107 }
2108
2109 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2110 {
2111 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2112 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2113 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2114 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002115 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002116 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002117 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2118 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
2119 }
2120 else
2121 {
2122 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2123 }
2124
2125 device->SetPixelShader(NULL);
2126 device->SetVertexShader(NULL);
2127 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2128
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002129 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002130 {
2131 float x, y, z, w;
2132 D3DCOLOR diffuse;
2133 };
2134
2135 Vertex quad[4];
2136 quad[0].x = 0.0f;
2137 quad[0].y = (float)desc.Height;
2138 quad[0].z = 0.0f;
2139 quad[0].w = 1.0f;
2140 quad[0].diffuse = color;
2141
2142 quad[1].x = (float)desc.Width;
2143 quad[1].y = (float)desc.Height;
2144 quad[1].z = 0.0f;
2145 quad[1].w = 1.0f;
2146 quad[1].diffuse = color;
2147
2148 quad[2].x = 0.0f;
2149 quad[2].y = 0.0f;
2150 quad[2].z = 0.0f;
2151 quad[2].w = 1.0f;
2152 quad[2].diffuse = color;
2153
2154 quad[3].x = (float)desc.Width;
2155 quad[3].y = 0.0f;
2156 quad[3].z = 0.0f;
2157 quad[3].w = 1.0f;
2158 quad[3].diffuse = color;
2159
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002160 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002161 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002162
2163 if (flags & D3DCLEAR_ZBUFFER)
2164 {
2165 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2166 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2167 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2168 }
2169 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002170 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002171 {
2172 device->Clear(0, NULL, flags, color, depth, stencil);
2173 }
2174}
2175
2176void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2177{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002178 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002179 {
2180 return error(GL_INVALID_OPERATION);
2181 }
2182
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002183 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002184 IDirect3DDevice9 *device = getDevice();
2185 D3DPRIMITIVETYPE primitiveType;
2186 int primitiveCount;
2187
2188 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2189 return error(GL_INVALID_ENUM);
2190
2191 if (primitiveCount <= 0)
2192 {
2193 return;
2194 }
2195
2196 if (!applyRenderTarget(false))
2197 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002198 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002199 }
2200
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002201 applyState(mode);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002202 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002203 applyShaders();
2204 applyTextures();
2205
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002206 if (!getCurrentProgram()->validateSamplers())
2207 {
2208 return error(GL_INVALID_OPERATION);
2209 }
2210
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002211 if (!cullSkipsDraw(mode))
2212 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002213 display->startScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002214 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002215 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002216}
2217
2218void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2219{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002220 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002221 {
2222 return error(GL_INVALID_OPERATION);
2223 }
2224
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002225 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002226 {
2227 return error(GL_INVALID_OPERATION);
2228 }
2229
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002230 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002231 IDirect3DDevice9 *device = getDevice();
2232 D3DPRIMITIVETYPE primitiveType;
2233 int primitiveCount;
2234
2235 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2236 return error(GL_INVALID_ENUM);
2237
2238 if (primitiveCount <= 0)
2239 {
2240 return;
2241 }
2242
2243 if (!applyRenderTarget(false))
2244 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002245 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002246 }
2247
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002248 applyState(mode);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002249 TranslatedIndexData indexInfo = applyIndexBuffer(indices, count, mode, type);
2250 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002251 applyShaders();
2252 applyTextures();
2253
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002254 if (!getCurrentProgram()->validateSamplers())
2255 {
2256 return error(GL_INVALID_OPERATION);
2257 }
2258
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002259 if (!cullSkipsDraw(mode))
2260 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002261 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002262 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 +00002263 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002264}
2265
2266void Context::finish()
2267{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002268 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002269 IDirect3DDevice9 *device = getDevice();
2270 IDirect3DQuery9 *occlusionQuery = NULL;
2271
2272 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2273
2274 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2275 {
2276 return error(GL_OUT_OF_MEMORY);
2277 }
2278
2279 ASSERT(SUCCEEDED(result));
2280
2281 if (occlusionQuery)
2282 {
2283 occlusionQuery->Issue(D3DISSUE_BEGIN);
2284
2285 // Render something outside the render target
2286 device->SetPixelShader(NULL);
2287 device->SetVertexShader(NULL);
2288 device->SetFVF(D3DFVF_XYZRHW);
2289 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002290 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002291 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002292
2293 occlusionQuery->Issue(D3DISSUE_END);
2294
2295 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2296 {
2297 // Keep polling, but allow other threads to do something useful first
2298 Sleep(0);
2299 }
2300
2301 occlusionQuery->Release();
2302 }
2303}
2304
2305void Context::flush()
2306{
2307 IDirect3DDevice9 *device = getDevice();
2308 IDirect3DQuery9 *eventQuery = NULL;
2309
2310 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2311
2312 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2313 {
2314 return error(GL_OUT_OF_MEMORY);
2315 }
2316
2317 ASSERT(SUCCEEDED(result));
2318
2319 if (eventQuery)
2320 {
2321 eventQuery->Issue(D3DISSUE_END);
2322
2323 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2324 {
2325 // Keep polling, but allow other threads to do something useful first
2326 Sleep(0);
2327 }
2328
2329 eventQuery->Release();
2330 }
2331}
2332
2333void Context::recordInvalidEnum()
2334{
2335 mInvalidEnum = true;
2336}
2337
2338void Context::recordInvalidValue()
2339{
2340 mInvalidValue = true;
2341}
2342
2343void Context::recordInvalidOperation()
2344{
2345 mInvalidOperation = true;
2346}
2347
2348void Context::recordOutOfMemory()
2349{
2350 mOutOfMemory = true;
2351}
2352
2353void Context::recordInvalidFramebufferOperation()
2354{
2355 mInvalidFramebufferOperation = true;
2356}
2357
2358// Get one of the recorded errors and clear its flag, if any.
2359// [OpenGL ES 2.0.24] section 2.5 page 13.
2360GLenum Context::getError()
2361{
2362 if (mInvalidEnum)
2363 {
2364 mInvalidEnum = false;
2365
2366 return GL_INVALID_ENUM;
2367 }
2368
2369 if (mInvalidValue)
2370 {
2371 mInvalidValue = false;
2372
2373 return GL_INVALID_VALUE;
2374 }
2375
2376 if (mInvalidOperation)
2377 {
2378 mInvalidOperation = false;
2379
2380 return GL_INVALID_OPERATION;
2381 }
2382
2383 if (mOutOfMemory)
2384 {
2385 mOutOfMemory = false;
2386
2387 return GL_OUT_OF_MEMORY;
2388 }
2389
2390 if (mInvalidFramebufferOperation)
2391 {
2392 mInvalidFramebufferOperation = false;
2393
2394 return GL_INVALID_FRAMEBUFFER_OPERATION;
2395 }
2396
2397 return GL_NO_ERROR;
2398}
2399
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002400const char *Context::getPixelShaderProfile()
2401{
2402 return mPsProfile;
2403}
2404
2405const char *Context::getVertexShaderProfile()
2406{
2407 return mVsProfile;
2408}
2409
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002410void Context::detachBuffer(GLuint buffer)
2411{
2412 // [OpenGL ES 2.0.24] section 2.9 page 22:
2413 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2414 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2415
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002416 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002417 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002418 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002419 }
2420
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002421 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002422 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002423 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002424 }
2425
2426 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2427 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002428 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002429 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002430 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002431 }
2432 }
2433}
2434
2435void Context::detachTexture(GLuint texture)
2436{
2437 // [OpenGL ES 2.0.24] section 3.8 page 84:
2438 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2439 // rebound to texture object zero
2440
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002441 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002442 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002443 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002444 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002445 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002446 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002447 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002448 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002449 }
2450 }
2451
2452 // [OpenGL ES 2.0.24] section 4.4 page 112:
2453 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2454 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2455 // image was attached in the currently bound framebuffer.
2456
2457 Framebuffer *framebuffer = getFramebuffer();
2458
2459 if (framebuffer)
2460 {
2461 framebuffer->detachTexture(texture);
2462 }
2463}
2464
2465void Context::detachFramebuffer(GLuint framebuffer)
2466{
2467 // [OpenGL ES 2.0.24] section 4.4 page 107:
2468 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2469 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2470
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002471 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002472 {
2473 bindFramebuffer(0);
2474 }
2475}
2476
2477void Context::detachRenderbuffer(GLuint renderbuffer)
2478{
2479 // [OpenGL ES 2.0.24] section 4.4 page 109:
2480 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2481 // had been executed with the target RENDERBUFFER and name of zero.
2482
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002483 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002484 {
2485 bindRenderbuffer(0);
2486 }
2487
2488 // [OpenGL ES 2.0.24] section 4.4 page 111:
2489 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2490 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2491 // point to which this image was attached in the currently bound framebuffer.
2492
2493 Framebuffer *framebuffer = getFramebuffer();
2494
2495 if (framebuffer)
2496 {
2497 framebuffer->detachRenderbuffer(renderbuffer);
2498 }
2499}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002500
2501Texture *Context::getIncompleteTexture(SamplerType type)
2502{
2503 Texture *t = mIncompleteTextures[type];
2504
2505 if (t == NULL)
2506 {
2507 static const GLubyte color[] = { 0, 0, 0, 255 };
2508
2509 switch (type)
2510 {
2511 default:
2512 UNREACHABLE();
2513 // default falls through to SAMPLER_2D
2514
2515 case SAMPLER_2D:
2516 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002517 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002518 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002519 t = incomplete2d;
2520 }
2521 break;
2522
2523 case SAMPLER_CUBE:
2524 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002525 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002526
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002527 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2528 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2529 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2530 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2531 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2532 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002533
2534 t = incompleteCube;
2535 }
2536 break;
2537 }
2538
2539 mIncompleteTextures[type] = t;
2540 }
2541
2542 return t;
2543}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002544
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002545bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002546{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002547 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002548}
2549
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002550bool Context::isTriangleMode(GLenum drawMode)
2551{
2552 switch (drawMode)
2553 {
2554 case GL_TRIANGLES:
2555 case GL_TRIANGLE_FAN:
2556 case GL_TRIANGLE_STRIP:
2557 return true;
2558 case GL_POINTS:
2559 case GL_LINES:
2560 case GL_LINE_LOOP:
2561 case GL_LINE_STRIP:
2562 return false;
2563 default: UNREACHABLE();
2564 }
2565
2566 return false;
2567}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002568
2569void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2570{
2571 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2572
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002573 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2574 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2575 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2576 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002577
2578 mVertexDataManager->dirtyCurrentValues();
2579}
2580
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002581void Context::initExtensionString()
2582{
2583 if (mBufferBackEnd->supportIntIndices())
2584 {
2585 mExtensionString += "GL_OES_element_index_uint ";
2586 }
2587
2588 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2589 if (end != std::string::npos)
2590 {
2591 mExtensionString.resize(end+1);
2592 }
2593}
2594
2595const char *Context::getExtensionString() const
2596{
2597 return mExtensionString.c_str();
2598}
2599
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002600}
2601
2602extern "C"
2603{
2604gl::Context *glCreateContext(const egl::Config *config)
2605{
2606 return new gl::Context(config);
2607}
2608
2609void glDestroyContext(gl::Context *context)
2610{
2611 delete context;
2612
2613 if (context == gl::getContext())
2614 {
2615 gl::makeCurrent(NULL, NULL, NULL);
2616 }
2617}
2618
2619void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2620{
2621 gl::makeCurrent(context, display, surface);
2622}
2623
2624gl::Context *glGetCurrentContext()
2625{
2626 return gl::getContext();
2627}
2628}