blob: 98abe79aa39fea65bdf4140e972e0a55580bc700 [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{
daniel@transgaming.com092bd482010-05-12 03:39:36 +000039 mAppliedRenderTargetSerial = 0;
40
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000041 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com092bd482010-05-12 03:39:36 +000042
daniel@transgaming.com428d1582010-05-04 03:35:25 +000043 mState.depthClearValue = 1.0f;
44 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000045
daniel@transgaming.com428d1582010-05-04 03:35:25 +000046 mState.cullFace = false;
47 mState.cullMode = GL_BACK;
48 mState.frontFace = GL_CCW;
49 mState.depthTest = false;
50 mState.depthFunc = GL_LESS;
51 mState.blend = false;
52 mState.sourceBlendRGB = GL_ONE;
53 mState.sourceBlendAlpha = GL_ONE;
54 mState.destBlendRGB = GL_ZERO;
55 mState.destBlendAlpha = GL_ZERO;
56 mState.blendEquationRGB = GL_FUNC_ADD;
57 mState.blendEquationAlpha = GL_FUNC_ADD;
58 mState.blendColor.red = 0;
59 mState.blendColor.green = 0;
60 mState.blendColor.blue = 0;
61 mState.blendColor.alpha = 0;
62 mState.stencilTest = false;
63 mState.stencilFunc = GL_ALWAYS;
64 mState.stencilRef = 0;
65 mState.stencilMask = -1;
66 mState.stencilWritemask = -1;
67 mState.stencilBackFunc = GL_ALWAYS;
68 mState.stencilBackRef = 0;
69 mState.stencilBackMask = - 1;
70 mState.stencilBackWritemask = -1;
71 mState.stencilFail = GL_KEEP;
72 mState.stencilPassDepthFail = GL_KEEP;
73 mState.stencilPassDepthPass = GL_KEEP;
74 mState.stencilBackFail = GL_KEEP;
75 mState.stencilBackPassDepthFail = GL_KEEP;
76 mState.stencilBackPassDepthPass = GL_KEEP;
77 mState.polygonOffsetFill = false;
78 mState.polygonOffsetFactor = 0.0f;
79 mState.polygonOffsetUnits = 0.0f;
80 mState.sampleAlphaToCoverage = false;
81 mState.sampleCoverage = false;
82 mState.sampleCoverageValue = 1.0f;
83 mState.sampleCoverageInvert = GL_FALSE;
84 mState.scissorTest = false;
85 mState.dither = true;
86 mState.generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087
daniel@transgaming.com428d1582010-05-04 03:35:25 +000088 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000089
daniel@transgaming.com428d1582010-05-04 03:35:25 +000090 mState.viewportX = 0;
91 mState.viewportY = 0;
92 mState.viewportWidth = config->mDisplayMode.Width;
93 mState.viewportHeight = config->mDisplayMode.Height;
94 mState.zNear = 0.0f;
95 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000096
daniel@transgaming.com428d1582010-05-04 03:35:25 +000097 mState.scissorX = 0;
98 mState.scissorY = 0;
99 mState.scissorWidth = config->mDisplayMode.Width;
100 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000102 mState.colorMaskRed = true;
103 mState.colorMaskGreen = true;
104 mState.colorMaskBlue = true;
105 mState.colorMaskAlpha = true;
106 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107
108 // [OpenGL ES 2.0.24] section 3.7 page 83:
109 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
110 // and cube map texture state vectors respectively associated with them.
111 // In order that access to these initial textures not be lost, they are treated as texture
112 // objects all of whose names are 0.
113
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000114 mTexture2DZero = new Texture2D(this);
115 mTextureCubeMapZero = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000116
117 mColorbufferZero = NULL;
118 mDepthbufferZero = NULL;
119 mStencilbufferZero = NULL;
120
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000121 mState.activeSampler = 0;
122 mState.arrayBuffer = 0;
123 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124 bindTextureCubeMap(0);
125 bindTexture2D(0);
126 bindFramebuffer(0);
127 bindRenderbuffer(0);
128
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000129 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000130 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000131 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
132 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000133 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000134 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135 }
136
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000137 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
138 {
139 mIncompleteTextures[type] = NULL;
140 }
141
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000142 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000144 mState.packAlignment = 4;
145 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000146
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000147 mBufferBackEnd = NULL;
148 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000149 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000150 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000151
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152 mInvalidEnum = false;
153 mInvalidValue = false;
154 mInvalidOperation = false;
155 mOutOfMemory = false;
156 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000157
158 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000159
160 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000161}
162
163Context::~Context()
164{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000165 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000167 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
168 {
169 delete mIncompleteTextures[type];
170 }
171
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172 delete mTexture2DZero;
173 delete mTextureCubeMapZero;
174
175 delete mColorbufferZero;
176 delete mDepthbufferZero;
177 delete mStencilbufferZero;
178
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000179 delete mBufferBackEnd;
180 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000181 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000182 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000183
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184 while (!mBufferMap.empty())
185 {
186 deleteBuffer(mBufferMap.begin()->first);
187 }
188
189 while (!mProgramMap.empty())
190 {
191 deleteProgram(mProgramMap.begin()->first);
192 }
193
194 while (!mShaderMap.empty())
195 {
196 deleteShader(mShaderMap.begin()->first);
197 }
198
199 while (!mFramebufferMap.empty())
200 {
201 deleteFramebuffer(mFramebufferMap.begin()->first);
202 }
203
204 while (!mRenderbufferMap.empty())
205 {
206 deleteRenderbuffer(mRenderbufferMap.begin()->first);
207 }
208
209 while (!mTextureMap.empty())
210 {
211 deleteTexture(mTextureMap.begin()->first);
212 }
213}
214
215void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
216{
217 IDirect3DDevice9 *device = display->getDevice();
218
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000219 if (!mBufferBackEnd)
220 {
221 mBufferBackEnd = new Dx9BackEnd(device);
222 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000223 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000224 mBlit = new Blit(this);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000225 }
226
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000227 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
228 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000229 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230
231 Framebuffer *framebufferZero = new Framebuffer();
232 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000233 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
234 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235
236 setFramebufferZero(framebufferZero);
237 setColorbufferZero(colorbufferZero);
238 setDepthbufferZero(depthbufferZero);
239 setStencilbufferZero(stencilbufferZero);
240
241 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
242 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
243 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
244
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000245 if (!mHasBeenCurrent)
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000246 {
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000247 initExtensionString();
248
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000249 mState.viewportX = 0;
250 mState.viewportY = 0;
251 mState.viewportWidth = surface->getWidth();
252 mState.viewportHeight = surface->getHeight();
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000253
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000254 mState.scissorX = 0;
255 mState.scissorY = 0;
256 mState.scissorWidth = surface->getWidth();
257 mState.scissorHeight = surface->getHeight();
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000258
259 mHasBeenCurrent = true;
260 }
261
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262 defaultRenderTarget->Release();
263
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000264 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000266 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000267 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000268
269 D3DCAPS9 capabilities;
270 device->GetDeviceCaps(&capabilities);
271
272 if (capabilities.PixelShaderVersion == D3DPS_VERSION(3, 0))
273 {
274 mPsProfile = "ps_3_0";
275 mVsProfile = "vs_3_0";
276 }
277 else // egl::Display guarantees support for at least 2.0
278 {
279 mPsProfile = "ps_2_0";
280 mVsProfile = "vs_2_0";
281 }
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000282
283 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284}
285
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000286// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000287void Context::markAllStateDirty()
288{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000289 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000290 mAppliedProgram = 0;
291}
292
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000293void Context::setClearColor(float red, float green, float blue, float alpha)
294{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000295 mState.colorClearValue.red = red;
296 mState.colorClearValue.green = green;
297 mState.colorClearValue.blue = blue;
298 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299}
300
301void Context::setClearDepth(float depth)
302{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000303 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000304}
305
306void Context::setClearStencil(int stencil)
307{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000308 mState.stencilClearValue = stencil;
309}
310
311void Context::setCullFace(bool enabled)
312{
313 mState.cullFace = enabled;
314}
315
316bool Context::isCullFaceEnabled() const
317{
318 return mState.cullFace;
319}
320
321void Context::setCullMode(GLenum mode)
322{
323 mState.cullMode = mode;
324}
325
326void Context::setFrontFace(GLenum front)
327{
328 mState.frontFace = front;
329}
330
331void Context::setDepthTest(bool enabled)
332{
333 mState.depthTest = enabled;
334}
335
336bool Context::isDepthTestEnabled() const
337{
338 return mState.depthTest;
339}
340
341void Context::setDepthFunc(GLenum depthFunc)
342{
343 mState.depthFunc = depthFunc;
344}
345
346void Context::setDepthRange(float zNear, float zFar)
347{
348 mState.zNear = zNear;
349 mState.zFar = zFar;
350}
351
352void Context::setBlend(bool enabled)
353{
354 mState.blend = enabled;
355}
356
357bool Context::isBlendEnabled() const
358{
359 return mState.blend;
360}
361
362void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
363{
364 mState.sourceBlendRGB = sourceRGB;
365 mState.destBlendRGB = destRGB;
366 mState.sourceBlendAlpha = sourceAlpha;
367 mState.destBlendAlpha = destAlpha;
368}
369
370void Context::setBlendColor(float red, float green, float blue, float alpha)
371{
372 mState.blendColor.red = red;
373 mState.blendColor.green = green;
374 mState.blendColor.blue = blue;
375 mState.blendColor.alpha = alpha;
376}
377
378void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
379{
380 mState.blendEquationRGB = rgbEquation;
381 mState.blendEquationAlpha = alphaEquation;
382}
383
384void Context::setStencilTest(bool enabled)
385{
386 mState.stencilTest = enabled;
387}
388
389bool Context::isStencilTestEnabled() const
390{
391 return mState.stencilTest;
392}
393
394void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
395{
396 mState.stencilFunc = stencilFunc;
397 mState.stencilRef = stencilRef;
398 mState.stencilMask = stencilMask;
399}
400
401void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
402{
403 mState.stencilBackFunc = stencilBackFunc;
404 mState.stencilBackRef = stencilBackRef;
405 mState.stencilBackMask = stencilBackMask;
406}
407
408void Context::setStencilWritemask(GLuint stencilWritemask)
409{
410 mState.stencilWritemask = stencilWritemask;
411}
412
413void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
414{
415 mState.stencilBackWritemask = stencilBackWritemask;
416}
417
418void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
419{
420 mState.stencilFail = stencilFail;
421 mState.stencilPassDepthFail = stencilPassDepthFail;
422 mState.stencilPassDepthPass = stencilPassDepthPass;
423}
424
425void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
426{
427 mState.stencilBackFail = stencilBackFail;
428 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
429 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
430}
431
432void Context::setPolygonOffsetFill(bool enabled)
433{
434 mState.polygonOffsetFill = enabled;
435}
436
437bool Context::isPolygonOffsetFillEnabled() const
438{
439 return mState.polygonOffsetFill;
440}
441
442void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
443{
444 mState.polygonOffsetFactor = factor;
445 mState.polygonOffsetUnits = units;
446}
447
448void Context::setSampleAlphaToCoverage(bool enabled)
449{
450 mState.sampleAlphaToCoverage = enabled;
451}
452
453bool Context::isSampleAlphaToCoverageEnabled() const
454{
455 return mState.sampleAlphaToCoverage;
456}
457
458void Context::setSampleCoverage(bool enabled)
459{
460 mState.sampleCoverage = enabled;
461}
462
463bool Context::isSampleCoverageEnabled() const
464{
465 return mState.sampleCoverage;
466}
467
468void Context::setSampleCoverageParams(GLclampf value, GLboolean invert)
469{
470 mState.sampleCoverageValue = value;
471 mState.sampleCoverageInvert = invert;
472}
473
474void Context::setScissorTest(bool enabled)
475{
476 mState.scissorTest = enabled;
477}
478
479bool Context::isScissorTestEnabled() const
480{
481 return mState.scissorTest;
482}
483
484void Context::setDither(bool enabled)
485{
486 mState.dither = enabled;
487}
488
489bool Context::isDitherEnabled() const
490{
491 return mState.dither;
492}
493
494void Context::setLineWidth(GLfloat width)
495{
496 mState.lineWidth = width;
497}
498
499void Context::setGenerateMipmapHint(GLenum hint)
500{
501 mState.generateMipmapHint = hint;
502}
503
504void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
505{
506 mState.viewportX = x;
507 mState.viewportY = y;
508 mState.viewportWidth = width;
509 mState.viewportHeight = height;
510}
511
512void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
513{
514 mState.scissorX = x;
515 mState.scissorY = y;
516 mState.scissorWidth = width;
517 mState.scissorHeight = height;
518}
519
520void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
521{
522 mState.colorMaskRed = red;
523 mState.colorMaskGreen = green;
524 mState.colorMaskBlue = blue;
525 mState.colorMaskAlpha = alpha;
526}
527
528void Context::setDepthMask(bool mask)
529{
530 mState.depthMask = mask;
531}
532
533void Context::setActiveSampler(int active)
534{
535 mState.activeSampler = active;
536}
537
538GLuint Context::getFramebufferHandle() const
539{
540 return mState.framebuffer;
541}
542
543GLuint Context::getRenderbufferHandle() const
544{
545 return mState.renderbuffer;
546}
547
548GLuint Context::getArrayBufferHandle() const
549{
550 return mState.arrayBuffer;
551}
552
553void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
554{
555 mState.vertexAttribute[attribNum].mEnabled = enabled;
556}
557
558const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
559{
560 return mState.vertexAttribute[attribNum];
561}
562
563void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
564 GLsizei stride, const void *pointer)
565{
566 mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
567 mState.vertexAttribute[attribNum].mSize = size;
568 mState.vertexAttribute[attribNum].mType = type;
569 mState.vertexAttribute[attribNum].mNormalized = normalized;
570 mState.vertexAttribute[attribNum].mStride = stride;
571 mState.vertexAttribute[attribNum].mPointer = pointer;
572}
573
574const void *Context::getVertexAttribPointer(unsigned int attribNum) const
575{
576 return mState.vertexAttribute[attribNum].mPointer;
577}
578
579// returns entire set of attributes as a block
580const AttributeState *Context::getVertexAttribBlock()
581{
582 return mState.vertexAttribute;
583}
584
585void Context::setPackAlignment(GLint alignment)
586{
587 mState.packAlignment = alignment;
588}
589
590GLint Context::getPackAlignment() const
591{
592 return mState.packAlignment;
593}
594
595void Context::setUnpackAlignment(GLint alignment)
596{
597 mState.unpackAlignment = alignment;
598}
599
600GLint Context::getUnpackAlignment() const
601{
602 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000603}
604
605// Returns an unused buffer name
606GLuint Context::createBuffer()
607{
608 unsigned int handle = 1;
609
610 while (mBufferMap.find(handle) != mBufferMap.end())
611 {
612 handle++;
613 }
614
615 mBufferMap[handle] = NULL;
616
617 return handle;
618}
619
620// Returns an unused shader/program name
621GLuint Context::createShader(GLenum type)
622{
623 unsigned int handle = 1;
624
625 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
626 {
627 handle++;
628 }
629
630 if (type == GL_VERTEX_SHADER)
631 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000632 mShaderMap[handle] = new VertexShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000633 }
634 else if (type == GL_FRAGMENT_SHADER)
635 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000636 mShaderMap[handle] = new FragmentShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637 }
638 else UNREACHABLE();
639
640 return handle;
641}
642
643// Returns an unused program/shader name
644GLuint Context::createProgram()
645{
646 unsigned int handle = 1;
647
648 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
649 {
650 handle++;
651 }
652
653 mProgramMap[handle] = new Program();
654
655 return handle;
656}
657
658// Returns an unused texture name
659GLuint Context::createTexture()
660{
661 unsigned int handle = 1;
662
663 while (mTextureMap.find(handle) != mTextureMap.end())
664 {
665 handle++;
666 }
667
668 mTextureMap[handle] = NULL;
669
670 return handle;
671}
672
673// Returns an unused framebuffer name
674GLuint Context::createFramebuffer()
675{
676 unsigned int handle = 1;
677
678 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
679 {
680 handle++;
681 }
682
683 mFramebufferMap[handle] = NULL;
684
685 return handle;
686}
687
688// Returns an unused renderbuffer name
689GLuint Context::createRenderbuffer()
690{
691 unsigned int handle = 1;
692
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000693 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000694 {
695 handle++;
696 }
697
698 mRenderbufferMap[handle] = NULL;
699
700 return handle;
701}
702
703void Context::deleteBuffer(GLuint buffer)
704{
705 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
706
707 if (bufferObject != mBufferMap.end())
708 {
709 detachBuffer(buffer);
710
711 delete bufferObject->second;
712 mBufferMap.erase(bufferObject);
713 }
714}
715
716void Context::deleteShader(GLuint shader)
717{
718 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
719
720 if (shaderObject != mShaderMap.end())
721 {
722 if (!shaderObject->second->isAttached())
723 {
724 delete shaderObject->second;
725 mShaderMap.erase(shaderObject);
726 }
727 else
728 {
729 shaderObject->second->flagForDeletion();
730 }
731 }
732}
733
734void Context::deleteProgram(GLuint program)
735{
736 ProgramMap::iterator programObject = mProgramMap.find(program);
737
738 if (programObject != mProgramMap.end())
739 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000740 if (program != mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000741 {
742 delete programObject->second;
743 mProgramMap.erase(programObject);
744 }
745 else
746 {
747 programObject->second->flagForDeletion();
748 }
749 }
750}
751
752void Context::deleteTexture(GLuint texture)
753{
754 TextureMap::iterator textureObject = mTextureMap.find(texture);
755
756 if (textureObject != mTextureMap.end())
757 {
758 detachTexture(texture);
759
760 if (texture != 0)
761 {
762 delete textureObject->second;
763 }
764
765 mTextureMap.erase(textureObject);
766 }
767}
768
769void Context::deleteFramebuffer(GLuint framebuffer)
770{
771 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
772
773 if (framebufferObject != mFramebufferMap.end())
774 {
775 detachFramebuffer(framebuffer);
776
777 delete framebufferObject->second;
778 mFramebufferMap.erase(framebufferObject);
779 }
780}
781
782void Context::deleteRenderbuffer(GLuint renderbuffer)
783{
784 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
785
786 if (renderbufferObject != mRenderbufferMap.end())
787 {
788 detachRenderbuffer(renderbuffer);
789
790 delete renderbufferObject->second;
791 mRenderbufferMap.erase(renderbufferObject);
792 }
793}
794
795void Context::bindArrayBuffer(unsigned int buffer)
796{
797 if (buffer != 0 && !getBuffer(buffer))
798 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000799 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000800 }
801
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000802 mState.arrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000803}
804
805void Context::bindElementArrayBuffer(unsigned int buffer)
806{
807 if (buffer != 0 && !getBuffer(buffer))
808 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000809 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000810 }
811
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000812 mState.elementArrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000813}
814
815void Context::bindTexture2D(GLuint texture)
816{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000817 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000819 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000820 }
821
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000822 mState.texture2D = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000823
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000824 mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000825}
826
827void Context::bindTextureCubeMap(GLuint texture)
828{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000829 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000830 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000831 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000832 }
833
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000834 mState.textureCubeMap = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000835
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000836 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000837}
838
839void Context::bindFramebuffer(GLuint framebuffer)
840{
841 if (!getFramebuffer(framebuffer))
842 {
843 mFramebufferMap[framebuffer] = new Framebuffer();
844 }
845
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000846 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000847}
848
849void Context::bindRenderbuffer(GLuint renderbuffer)
850{
851 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
852 {
853 mRenderbufferMap[renderbuffer] = new Renderbuffer();
854 }
855
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000856 mState.renderbuffer = renderbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000857}
858
859void Context::useProgram(GLuint program)
860{
861 Program *programObject = getCurrentProgram();
862
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000863 GLuint priorProgram = mState.currentProgram;
864 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000865
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000866 if (programObject && programObject->isFlaggedForDeletion())
867 {
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000868 deleteProgram(priorProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000869 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000870}
871
872void Context::setFramebufferZero(Framebuffer *buffer)
873{
874 delete mFramebufferMap[0];
875 mFramebufferMap[0] = buffer;
876}
877
878void Context::setColorbufferZero(Colorbuffer *buffer)
879{
880 delete mColorbufferZero;
881 mColorbufferZero = buffer;
882}
883
884void Context::setDepthbufferZero(Depthbuffer *buffer)
885{
886 delete mDepthbufferZero;
887 mDepthbufferZero = buffer;
888}
889
890void Context::setStencilbufferZero(Stencilbuffer *buffer)
891{
892 delete mStencilbufferZero;
893 mStencilbufferZero = buffer;
894}
895
896void Context::setRenderbuffer(Renderbuffer *buffer)
897{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000898 delete mRenderbufferMap[mState.renderbuffer];
899 mRenderbufferMap[mState.renderbuffer] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000900}
901
902Buffer *Context::getBuffer(unsigned int handle)
903{
904 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000905
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000906 if (buffer == mBufferMap.end())
907 {
908 return NULL;
909 }
910 else
911 {
912 return buffer->second;
913 }
914}
915
916Shader *Context::getShader(unsigned int handle)
917{
918 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000919
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000920 if (shader == mShaderMap.end())
921 {
922 return NULL;
923 }
924 else
925 {
926 return shader->second;
927 }
928}
929
930Program *Context::getProgram(unsigned int handle)
931{
932 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000933
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000934 if (program == mProgramMap.end())
935 {
936 return NULL;
937 }
938 else
939 {
940 return program->second;
941 }
942}
943
944Texture *Context::getTexture(unsigned int handle)
945{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000946 if (handle == 0) return NULL;
947
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000948 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000949
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000950 if (texture == mTextureMap.end())
951 {
952 return NULL;
953 }
954 else
955 {
956 return texture->second;
957 }
958}
959
960Framebuffer *Context::getFramebuffer(unsigned int handle)
961{
962 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000963
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000964 if (framebuffer == mFramebufferMap.end())
965 {
966 return NULL;
967 }
968 else
969 {
970 return framebuffer->second;
971 }
972}
973
974Renderbuffer *Context::getRenderbuffer(unsigned int handle)
975{
976 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000977
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000978 if (renderbuffer == mRenderbufferMap.end())
979 {
980 return NULL;
981 }
982 else
983 {
984 return renderbuffer->second;
985 }
986}
987
988Colorbuffer *Context::getColorbuffer(GLuint handle)
989{
990 if (handle != 0)
991 {
992 Renderbuffer *renderbuffer = getRenderbuffer(handle);
993
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000994 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000995 {
996 return static_cast<Colorbuffer*>(renderbuffer);
997 }
998 }
999 else // Special case: 0 refers to different initial render targets based on the attachment type
1000 {
1001 return mColorbufferZero;
1002 }
1003
1004 return NULL;
1005}
1006
1007Depthbuffer *Context::getDepthbuffer(GLuint handle)
1008{
1009 if (handle != 0)
1010 {
1011 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1012
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001013 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001014 {
1015 return static_cast<Depthbuffer*>(renderbuffer);
1016 }
1017 }
1018 else // Special case: 0 refers to different initial render targets based on the attachment type
1019 {
1020 return mDepthbufferZero;
1021 }
1022
1023 return NULL;
1024}
1025
1026Stencilbuffer *Context::getStencilbuffer(GLuint handle)
1027{
1028 if (handle != 0)
1029 {
1030 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1031
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001032 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001033 {
1034 return static_cast<Stencilbuffer*>(renderbuffer);
1035 }
1036 }
1037 else
1038 {
1039 return mStencilbufferZero;
1040 }
1041
1042 return NULL;
1043}
1044
1045Buffer *Context::getArrayBuffer()
1046{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001047 return getBuffer(mState.arrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001048}
1049
1050Buffer *Context::getElementArrayBuffer()
1051{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001052 return getBuffer(mState.elementArrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001053}
1054
1055Program *Context::getCurrentProgram()
1056{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001057 return getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001058}
1059
1060Texture2D *Context::getTexture2D()
1061{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001062 if (mState.texture2D == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001063 {
1064 return mTexture2DZero;
1065 }
1066
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001067 return (Texture2D*)getTexture(mState.texture2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001068}
1069
1070TextureCubeMap *Context::getTextureCubeMap()
1071{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001072 if (mState.textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001073 {
1074 return mTextureCubeMapZero;
1075 }
1076
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001077 return (TextureCubeMap*)getTexture(mState.textureCubeMap);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001078}
1079
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001080Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001081{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001082 GLuint texid = mState.samplerTexture[type][sampler];
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001083
1084 if (texid == 0)
1085 {
1086 switch (type)
1087 {
1088 default: UNREACHABLE();
1089 case SAMPLER_2D: return mTexture2DZero;
1090 case SAMPLER_CUBE: return mTextureCubeMapZero;
1091 }
1092 }
1093
1094 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001095}
1096
1097Framebuffer *Context::getFramebuffer()
1098{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001099 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001100}
1101
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001102bool Context::getBooleanv(GLenum pname, GLboolean *params)
1103{
1104 switch (pname)
1105 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001106 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1107 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1108 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001109 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001110 params[0] = mState.colorMaskRed;
1111 params[1] = mState.colorMaskGreen;
1112 params[2] = mState.colorMaskBlue;
1113 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001114 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001115 case GL_CULL_FACE: *params = mState.cullFace;
1116 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1117 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1118 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1119 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1120 case GL_STENCIL_TEST: *params = mState.stencilTest;
1121 case GL_DEPTH_TEST: *params = mState.depthTest;
1122 case GL_BLEND: *params = mState.blend;
1123 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001124 default:
1125 return false;
1126 }
1127
1128 return true;
1129}
1130
1131bool Context::getFloatv(GLenum pname, GLfloat *params)
1132{
1133 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1134 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1135 // GetIntegerv as its native query function. As it would require conversion in any
1136 // case, this should make no difference to the calling application.
1137 switch (pname)
1138 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001139 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1140 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1141 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1142 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1143 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001144 case GL_ALIASED_LINE_WIDTH_RANGE:
1145 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1146 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1147 break;
1148 case GL_ALIASED_POINT_SIZE_RANGE:
1149 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
1150 params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
1151 break;
1152 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001153 params[0] = mState.zNear;
1154 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001155 break;
1156 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001157 params[0] = mState.colorClearValue.red;
1158 params[1] = mState.colorClearValue.green;
1159 params[2] = mState.colorClearValue.blue;
1160 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001161 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001162 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001163 params[0] = mState.blendColor.red;
1164 params[1] = mState.blendColor.green;
1165 params[2] = mState.blendColor.blue;
1166 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001167 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001168 default:
1169 return false;
1170 }
1171
1172 return true;
1173}
1174
1175bool Context::getIntegerv(GLenum pname, GLint *params)
1176{
1177 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1178 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1179 // GetIntegerv as its native query function. As it would require conversion in any
1180 // case, this should make no difference to the calling application. You may find it in
1181 // Context::getFloatv.
1182 switch (pname)
1183 {
1184 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1185 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1186 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1187 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1188 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1189 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1190 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1191 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
1192 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1193 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1194 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1195 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001196 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer; break;
1197 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer; break;
1198 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
1199 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer; break;
1200 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1201 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1202 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1203 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1204 case GL_ACTIVE_TEXTURE: *params = mState.activeSampler; break;
1205 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1206 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1207 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1208 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1209 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1210 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1211 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1212 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1213 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1214 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1215 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1216 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1217 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1218 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1219 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1220 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1221 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1222 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1223 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1224 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1225 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1226 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001227 case GL_SUBPIXEL_BITS: *params = 4; break;
1228 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1229 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1230 case GL_SAMPLE_BUFFERS: *params = 0; break;
1231 case GL_SAMPLES: *params = 0; break;
1232 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1233 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1234 case GL_MAX_VIEWPORT_DIMS:
1235 {
1236 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1237 params[0] = maxDimension;
1238 params[1] = maxDimension;
1239 }
1240 break;
1241 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001242 params[0] = mState.viewportX;
1243 params[1] = mState.viewportY;
1244 params[2] = mState.viewportWidth;
1245 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001246 break;
1247 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001248 params[0] = mState.scissorX;
1249 params[1] = mState.scissorY;
1250 params[2] = mState.scissorWidth;
1251 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001252 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001253 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1254 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001255 case GL_RED_BITS:
1256 case GL_GREEN_BITS:
1257 case GL_BLUE_BITS:
1258 case GL_ALPHA_BITS:
1259 {
1260 gl::Framebuffer *framebuffer = getFramebuffer();
1261 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1262
1263 if (colorbuffer)
1264 {
1265 switch (pname)
1266 {
1267 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1268 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1269 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1270 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1271 }
1272 }
1273 else
1274 {
1275 *params = 0;
1276 }
1277 }
1278 break;
1279 case GL_DEPTH_BITS:
1280 {
1281 gl::Framebuffer *framebuffer = getFramebuffer();
1282 gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
1283
1284 if (depthbuffer)
1285 {
1286 *params = depthbuffer->getDepthSize();
1287 }
1288 else
1289 {
1290 *params = 0;
1291 }
1292 }
1293 break;
1294 case GL_STENCIL_BITS:
1295 {
1296 gl::Framebuffer *framebuffer = getFramebuffer();
1297 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1298
1299 if (stencilbuffer)
1300 {
1301 *params = stencilbuffer->getStencilSize();
1302 }
1303 else
1304 {
1305 *params = 0;
1306 }
1307 }
1308 break;
1309 case GL_TEXTURE_BINDING_2D:
1310 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001311 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001312 {
1313 error(GL_INVALID_OPERATION);
1314 return false;
1315 }
1316
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001317 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001318 }
1319 break;
1320 case GL_TEXTURE_BINDING_CUBE_MAP:
1321 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001322 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001323 {
1324 error(GL_INVALID_OPERATION);
1325 return false;
1326 }
1327
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001328 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001329 }
1330 break;
1331 default:
1332 return false;
1333 }
1334
1335 return true;
1336}
1337
1338bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1339{
1340 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1341 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1342 // to the fact that it is stored internally as a float, and so would require conversion
1343 // if returned from Context::getIntegerv. Since this conversion is already implemented
1344 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1345 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1346 // application.
1347 switch (pname)
1348 {
1349 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1350 case GL_SHADER_BINARY_FORMATS:
1351 {
1352 *type = GL_INT;
1353 *numParams = 0;
1354 }
1355 break;
1356 case GL_MAX_VERTEX_ATTRIBS:
1357 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1358 case GL_MAX_VARYING_VECTORS:
1359 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1360 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1361 case GL_MAX_TEXTURE_IMAGE_UNITS:
1362 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1363 case GL_MAX_RENDERBUFFER_SIZE:
1364 case GL_NUM_SHADER_BINARY_FORMATS:
1365 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1366 case GL_ARRAY_BUFFER_BINDING:
1367 case GL_FRAMEBUFFER_BINDING:
1368 case GL_RENDERBUFFER_BINDING:
1369 case GL_CURRENT_PROGRAM:
1370 case GL_PACK_ALIGNMENT:
1371 case GL_UNPACK_ALIGNMENT:
1372 case GL_GENERATE_MIPMAP_HINT:
1373 case GL_RED_BITS:
1374 case GL_GREEN_BITS:
1375 case GL_BLUE_BITS:
1376 case GL_ALPHA_BITS:
1377 case GL_DEPTH_BITS:
1378 case GL_STENCIL_BITS:
1379 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1380 case GL_CULL_FACE_MODE:
1381 case GL_FRONT_FACE:
1382 case GL_ACTIVE_TEXTURE:
1383 case GL_STENCIL_FUNC:
1384 case GL_STENCIL_VALUE_MASK:
1385 case GL_STENCIL_REF:
1386 case GL_STENCIL_FAIL:
1387 case GL_STENCIL_PASS_DEPTH_FAIL:
1388 case GL_STENCIL_PASS_DEPTH_PASS:
1389 case GL_STENCIL_BACK_FUNC:
1390 case GL_STENCIL_BACK_VALUE_MASK:
1391 case GL_STENCIL_BACK_REF:
1392 case GL_STENCIL_BACK_FAIL:
1393 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1394 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1395 case GL_DEPTH_FUNC:
1396 case GL_BLEND_SRC_RGB:
1397 case GL_BLEND_SRC_ALPHA:
1398 case GL_BLEND_DST_RGB:
1399 case GL_BLEND_DST_ALPHA:
1400 case GL_BLEND_EQUATION_RGB:
1401 case GL_BLEND_EQUATION_ALPHA:
1402 case GL_STENCIL_WRITEMASK:
1403 case GL_STENCIL_BACK_WRITEMASK:
1404 case GL_STENCIL_CLEAR_VALUE:
1405 case GL_SUBPIXEL_BITS:
1406 case GL_MAX_TEXTURE_SIZE:
1407 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1408 case GL_SAMPLE_BUFFERS:
1409 case GL_SAMPLES:
1410 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1411 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1412 case GL_TEXTURE_BINDING_2D:
1413 case GL_TEXTURE_BINDING_CUBE_MAP:
1414 {
1415 *type = GL_INT;
1416 *numParams = 1;
1417 }
1418 break;
1419 case GL_MAX_VIEWPORT_DIMS:
1420 {
1421 *type = GL_INT;
1422 *numParams = 2;
1423 }
1424 break;
1425 case GL_VIEWPORT:
1426 case GL_SCISSOR_BOX:
1427 {
1428 *type = GL_INT;
1429 *numParams = 4;
1430 }
1431 break;
1432 case GL_SHADER_COMPILER:
1433 case GL_SAMPLE_COVERAGE_INVERT:
1434 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001435 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1436 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1437 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1438 case GL_SAMPLE_COVERAGE:
1439 case GL_SCISSOR_TEST:
1440 case GL_STENCIL_TEST:
1441 case GL_DEPTH_TEST:
1442 case GL_BLEND:
1443 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001444 {
1445 *type = GL_BOOL;
1446 *numParams = 1;
1447 }
1448 break;
1449 case GL_COLOR_WRITEMASK:
1450 {
1451 *type = GL_BOOL;
1452 *numParams = 4;
1453 }
1454 break;
1455 case GL_POLYGON_OFFSET_FACTOR:
1456 case GL_POLYGON_OFFSET_UNITS:
1457 case GL_SAMPLE_COVERAGE_VALUE:
1458 case GL_DEPTH_CLEAR_VALUE:
1459 case GL_LINE_WIDTH:
1460 {
1461 *type = GL_FLOAT;
1462 *numParams = 1;
1463 }
1464 break;
1465 case GL_ALIASED_LINE_WIDTH_RANGE:
1466 case GL_ALIASED_POINT_SIZE_RANGE:
1467 case GL_DEPTH_RANGE:
1468 {
1469 *type = GL_FLOAT;
1470 *numParams = 2;
1471 }
1472 break;
1473 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001474 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001475 {
1476 *type = GL_FLOAT;
1477 *numParams = 4;
1478 }
1479 break;
1480 default:
1481 return false;
1482 }
1483
1484 return true;
1485}
1486
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001487// Applies the render target surface, depth stencil surface, viewport rectangle and
1488// scissor rectangle to the Direct3D 9 device
1489bool Context::applyRenderTarget(bool ignoreViewport)
1490{
1491 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001492
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001493 Framebuffer *framebufferObject = getFramebuffer();
1494
1495 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1496 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001497 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1498
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001499 return false;
1500 }
1501
1502 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1503 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1504
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001505 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1506 if (renderTargetSerial != mAppliedRenderTargetSerial)
1507 {
1508 device->SetRenderTarget(0, renderTarget);
1509 mAppliedRenderTargetSerial = renderTargetSerial;
1510 }
1511
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001512 device->SetDepthStencilSurface(depthStencil);
1513
1514 D3DVIEWPORT9 viewport;
1515 D3DSURFACE_DESC desc;
1516 renderTarget->GetDesc(&desc);
1517
1518 if (ignoreViewport)
1519 {
1520 viewport.X = 0;
1521 viewport.Y = 0;
1522 viewport.Width = desc.Width;
1523 viewport.Height = desc.Height;
1524 viewport.MinZ = 0.0f;
1525 viewport.MaxZ = 1.0f;
1526 }
1527 else
1528 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001529 viewport.X = std::max(mState.viewportX, 0);
1530 viewport.Y = std::max(mState.viewportY, 0);
1531 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1532 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1533 viewport.MinZ = clamp01(mState.zNear);
1534 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001535 }
1536
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001537 if (viewport.Width <= 0 || viewport.Height <= 0)
1538 {
1539 return false; // Nothing to render
1540 }
1541
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001542 device->SetViewport(&viewport);
1543
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001544 if (mState.scissorTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001545 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001546 RECT rect = {mState.scissorX,
1547 mState.scissorY,
1548 mState.scissorX + mState.scissorWidth,
1549 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001550
1551 device->SetScissorRect(&rect);
1552 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1553 }
1554 else
1555 {
1556 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1557 }
1558
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001559 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001560 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001561 Program *programObject = getCurrentProgram();
1562
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001563 GLint halfPixelSize = programObject->getUniformLocation("dx_HalfPixelSize");
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001564 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001565 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001566
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001567 GLint window = programObject->getUniformLocation("dx_Window");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001568 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1569 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1570 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001571 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1572
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001573 GLint depth = programObject->getUniformLocation("dx_Depth");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001574 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001575 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1576
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001577 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001578 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001579
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001580 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001581 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001582
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001583 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001584 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001585 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001586 }
1587
1588 return true;
1589}
1590
1591// 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 +00001592void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001593{
1594 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001595 Program *programObject = getCurrentProgram();
1596
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001597 GLint frontCCW = programObject->getUniformLocation("dx_FrontCCW");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001598 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001599 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001600
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001601 GLint pointsOrLines = programObject->getUniformLocation("dx_PointsOrLines");
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001602 GLint alwaysFront = !isTriangleMode(drawMode);
1603 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1604
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001605 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001606 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001607 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001608 }
1609 else
1610 {
1611 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1612 }
1613
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001614 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001615 {
1616 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001617 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001618 }
1619 else
1620 {
1621 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
1622 }
1623
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001624 if (mState.blend)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001625 {
1626 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1627
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001628 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1629 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001630 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001631 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001632 }
1633 else
1634 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001635 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1636 unorm<8>(mState.blendColor.alpha),
1637 unorm<8>(mState.blendColor.alpha),
1638 unorm<8>(mState.blendColor.alpha)));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001639 }
1640
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001641 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1642 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1643 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001644
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001645 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1646 mState.destBlendRGB != mState.destBlendAlpha ||
1647 mState.blendEquationRGB != mState.blendEquationAlpha)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001648 {
1649 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1650
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001651 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1652 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1653 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001654
1655 }
1656 else
1657 {
1658 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1659 }
1660 }
1661 else
1662 {
1663 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1664 }
1665
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00001666 if (mState.stencilTest && hasStencil())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001667 {
1668 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1669 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1670
1671 // FIXME: Unsupported by D3D9
1672 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1673 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1674 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001675 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1676 mState.stencilRef != mState.stencilBackRef ||
1677 mState.stencilMask != mState.stencilBackMask)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001678 {
1679 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1680 return error(GL_INVALID_OPERATION);
1681 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001682
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001683 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1684 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1685 es2dx::ConvertComparison(mState.stencilFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001686
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001687 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilRef); // FIXME: Clamp to range
1688 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001689
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001690 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1691 es2dx::ConvertStencilOp(mState.stencilFail));
1692 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1693 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1694 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1695 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001696
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001697 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1698 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1699 es2dx::ConvertComparison(mState.stencilBackFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001700
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001701 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilBackRef); // FIXME: Clamp to range
1702 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001703
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001704 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1705 es2dx::ConvertStencilOp(mState.stencilBackFail));
1706 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1707 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1708 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1709 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001710 }
1711 else
1712 {
1713 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1714 }
1715
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001716 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1717 mState.colorMaskBlue, mState.colorMaskAlpha));
1718 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001719
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001720 if (mState.polygonOffsetFill)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001721 {
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001722 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1723 if (depthbuffer)
1724 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001725 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1726 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001727 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1728 }
1729 }
1730 else
1731 {
1732 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1733 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001734 }
1735
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001736 if (mConfig->mMultiSample != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001737 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001738 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001739 {
1740 FIXME("Sample alpha to coverage is unimplemented.");
1741 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001742
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001743 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001744 {
1745 FIXME("Sample coverage is unimplemented.");
1746 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001747 }
1748
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001749 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001750}
1751
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001752// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001753void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001754{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001755 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001756 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001757 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001758 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001759 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001760 }
1761 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001762}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001763
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001764void Context::applyVertexBuffer(GLint first, GLsizei count)
1765{
1766 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1767
1768 mVertexDataManager->preRenderValidate(first, count, translated);
1769
1770 lookupAttributeMapping(translated);
1771
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001772 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001773}
1774
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001775void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001776{
1777 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1778
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00001779 mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001780
1781 lookupAttributeMapping(translated);
1782
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001783 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001784}
1785
1786// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001787TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001788{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001789 TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001790 mBufferBackEnd->setupIndicesPreDraw(indexInfo);
1791 return indexInfo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001792}
1793
1794// Applies the shaders and shader constants to the Direct3D 9 device
1795void Context::applyShaders()
1796{
1797 IDirect3DDevice9 *device = getDevice();
1798 Program *programObject = getCurrentProgram();
1799 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1800 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1801
1802 device->SetVertexShader(vertexShader);
1803 device->SetPixelShader(pixelShader);
1804
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001805 if (programObject->getSerial() != mAppliedProgram)
1806 {
1807 programObject->dirtyAllUniforms();
1808 mAppliedProgram = programObject->getSerial();
1809 }
1810
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001811 programObject->applyUniforms();
1812}
1813
1814// Applies the textures and sampler states to the Direct3D 9 device
1815void Context::applyTextures()
1816{
1817 IDirect3DDevice9 *device = getDevice();
1818 Program *programObject = getCurrentProgram();
1819
1820 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1821 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001822 int textureUnit = programObject->getSamplerMapping(sampler);
1823 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001824 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001825 SamplerType textureType = programObject->getSamplerType(sampler);
1826
1827 Texture *texture = getSamplerTexture(textureUnit, textureType);
1828
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001829 if (texture->isComplete())
1830 {
1831 GLenum wrapS = texture->getWrapS();
1832 GLenum wrapT = texture->getWrapT();
1833 GLenum minFilter = texture->getMinFilter();
1834 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001835
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001836 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1837 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001838
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001839 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1840 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1841 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1842 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1843 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001844
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001845 device->SetTexture(sampler, texture->getTexture());
1846 }
1847 else
1848 {
1849 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1850 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001851 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001852 else
1853 {
1854 device->SetTexture(sampler, NULL);
1855 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001856 }
1857}
1858
1859void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1860{
1861 Framebuffer *framebuffer = getFramebuffer();
1862 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1863 IDirect3DDevice9 *device = getDevice();
1864
1865 D3DSURFACE_DESC desc;
1866 renderTarget->GetDesc(&desc);
1867
1868 IDirect3DSurface9 *systemSurface;
1869 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1870
1871 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1872 {
1873 return error(GL_OUT_OF_MEMORY);
1874 }
1875
1876 ASSERT(SUCCEEDED(result));
1877
1878 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1879 {
1880 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1881 }
1882
1883 result = device->GetRenderTargetData(renderTarget, systemSurface);
1884
1885 if (result == D3DERR_DRIVERINTERNALERROR)
1886 {
1887 systemSurface->Release();
1888
1889 return error(GL_OUT_OF_MEMORY);
1890 }
1891
1892 if (FAILED(result))
1893 {
1894 UNREACHABLE();
1895 systemSurface->Release();
1896
1897 return; // No sensible error to generate
1898 }
1899
1900 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001901 RECT rect = {std::max(x, 0),
1902 std::max(y, 0),
1903 std::min(x + width, (int)desc.Width),
1904 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001905
1906 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1907
1908 if (FAILED(result))
1909 {
1910 UNREACHABLE();
1911 systemSurface->Release();
1912
1913 return; // No sensible error to generate
1914 }
1915
1916 unsigned char *source = (unsigned char*)lock.pBits;
1917 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001918 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001919
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001920 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001921
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001922 for (int j = 0; j < rect.bottom - rect.top; j++)
1923 {
1924 for (int i = 0; i < rect.right - rect.left; i++)
1925 {
1926 float r;
1927 float g;
1928 float b;
1929 float a;
1930
1931 switch (desc.Format)
1932 {
1933 case D3DFMT_R5G6B5:
1934 {
1935 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1936
1937 a = 1.0f;
1938 b = (rgb & 0x001F) * (1.0f / 0x001F);
1939 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1940 r = (rgb & 0xF800) * (1.0f / 0xF800);
1941 }
1942 break;
1943 case D3DFMT_X1R5G5B5:
1944 {
1945 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1946
1947 a = 1.0f;
1948 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1949 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1950 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1951 }
1952 break;
1953 case D3DFMT_A1R5G5B5:
1954 {
1955 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1956
1957 a = (argb & 0x8000) ? 1.0f : 0.0f;
1958 b = (argb & 0x001F) * (1.0f / 0x001F);
1959 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1960 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1961 }
1962 break;
1963 case D3DFMT_A8R8G8B8:
1964 {
1965 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1966
1967 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1968 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1969 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1970 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1971 }
1972 break;
1973 case D3DFMT_X8R8G8B8:
1974 {
1975 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1976
1977 a = 1.0f;
1978 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
1979 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
1980 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
1981 }
1982 break;
1983 case D3DFMT_A2R10G10B10:
1984 {
1985 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1986
1987 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
1988 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
1989 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
1990 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
1991 }
1992 break;
1993 default:
1994 UNIMPLEMENTED(); // FIXME
1995 UNREACHABLE();
1996 }
1997
1998 switch (format)
1999 {
2000 case GL_RGBA:
2001 switch (type)
2002 {
2003 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002004 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2005 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2006 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2007 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002008 break;
2009 default: UNREACHABLE();
2010 }
2011 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002012 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002013 switch (type)
2014 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002015 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002016 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2017 ((unsigned short)(31 * b + 0.5f) << 0) |
2018 ((unsigned short)(63 * g + 0.5f) << 5) |
2019 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002020 break;
2021 default: UNREACHABLE();
2022 }
2023 break;
2024 default: UNREACHABLE();
2025 }
2026 }
2027 }
2028
2029 systemSurface->UnlockRect();
2030
2031 systemSurface->Release();
2032}
2033
2034void Context::clear(GLbitfield mask)
2035{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002036 Framebuffer *framebufferObject = getFramebuffer();
2037
2038 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2039 {
2040 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2041
2042 return;
2043 }
2044
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002045 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002046 IDirect3DDevice9 *device = getDevice();
2047 DWORD flags = 0;
2048
2049 if (mask & GL_COLOR_BUFFER_BIT)
2050 {
2051 mask &= ~GL_COLOR_BUFFER_BIT;
2052 flags |= D3DCLEAR_TARGET;
2053 }
2054
2055 if (mask & GL_DEPTH_BUFFER_BIT)
2056 {
2057 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002058 if (mState.depthMask)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002059 {
2060 flags |= D3DCLEAR_ZBUFFER;
2061 }
2062 }
2063
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002064 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
2065
2066 GLuint stencilUnmasked = 0x0;
2067
2068 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
2069 {
2070 D3DSURFACE_DESC desc;
2071 depthStencil->GetDesc(&desc);
2072
2073 mask &= ~GL_STENCIL_BUFFER_BIT;
2074 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2075 stencilUnmasked = (0x1 << stencilSize) - 1;
2076
2077 if (stencilUnmasked != 0x0)
2078 {
2079 flags |= D3DCLEAR_STENCIL;
2080 }
2081 }
2082
2083 if (mask != 0)
2084 {
2085 return error(GL_INVALID_VALUE);
2086 }
2087
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002088 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2089 {
2090 return;
2091 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002092
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002093 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2094 unorm<8>(mState.colorClearValue.red),
2095 unorm<8>(mState.colorClearValue.green),
2096 unorm<8>(mState.colorClearValue.blue));
2097 float depth = clamp01(mState.depthClearValue);
2098 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002099
2100 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2101
2102 D3DSURFACE_DESC desc;
2103 renderTarget->GetDesc(&desc);
2104
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002105 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002106
2107 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002108 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002109 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002110 !(mState.colorMaskRed && mState.colorMaskGreen &&
2111 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002112
2113 if (needMaskedColorClear || needMaskedStencilClear)
2114 {
2115 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2116 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2117 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2118 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2119 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2120 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2121 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2122 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2123
2124 if (flags & D3DCLEAR_TARGET)
2125 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002126 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2127 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2128 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2129 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002130 }
2131 else
2132 {
2133 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2134 }
2135
2136 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2137 {
2138 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2139 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2140 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2141 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002142 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002143 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002144 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2145 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
2146 }
2147 else
2148 {
2149 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2150 }
2151
2152 device->SetPixelShader(NULL);
2153 device->SetVertexShader(NULL);
2154 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2155
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002156 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002157 {
2158 float x, y, z, w;
2159 D3DCOLOR diffuse;
2160 };
2161
2162 Vertex quad[4];
2163 quad[0].x = 0.0f;
2164 quad[0].y = (float)desc.Height;
2165 quad[0].z = 0.0f;
2166 quad[0].w = 1.0f;
2167 quad[0].diffuse = color;
2168
2169 quad[1].x = (float)desc.Width;
2170 quad[1].y = (float)desc.Height;
2171 quad[1].z = 0.0f;
2172 quad[1].w = 1.0f;
2173 quad[1].diffuse = color;
2174
2175 quad[2].x = 0.0f;
2176 quad[2].y = 0.0f;
2177 quad[2].z = 0.0f;
2178 quad[2].w = 1.0f;
2179 quad[2].diffuse = color;
2180
2181 quad[3].x = (float)desc.Width;
2182 quad[3].y = 0.0f;
2183 quad[3].z = 0.0f;
2184 quad[3].w = 1.0f;
2185 quad[3].diffuse = color;
2186
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002187 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002188 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002189
2190 if (flags & D3DCLEAR_ZBUFFER)
2191 {
2192 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2193 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2194 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2195 }
2196 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002197 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002198 {
2199 device->Clear(0, NULL, flags, color, depth, stencil);
2200 }
2201}
2202
2203void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2204{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002205 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002206 {
2207 return error(GL_INVALID_OPERATION);
2208 }
2209
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002210 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002211 IDirect3DDevice9 *device = getDevice();
2212 D3DPRIMITIVETYPE primitiveType;
2213 int primitiveCount;
2214
2215 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2216 return error(GL_INVALID_ENUM);
2217
2218 if (primitiveCount <= 0)
2219 {
2220 return;
2221 }
2222
2223 if (!applyRenderTarget(false))
2224 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002225 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002226 }
2227
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002228 applyState(mode);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002229 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002230 applyShaders();
2231 applyTextures();
2232
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002233 if (!getCurrentProgram()->validateSamplers())
2234 {
2235 return error(GL_INVALID_OPERATION);
2236 }
2237
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002238 if (!cullSkipsDraw(mode))
2239 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002240 display->startScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002241 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002242 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002243}
2244
2245void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2246{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002247 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002248 {
2249 return error(GL_INVALID_OPERATION);
2250 }
2251
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002252 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002253 {
2254 return error(GL_INVALID_OPERATION);
2255 }
2256
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002257 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002258 IDirect3DDevice9 *device = getDevice();
2259 D3DPRIMITIVETYPE primitiveType;
2260 int primitiveCount;
2261
2262 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2263 return error(GL_INVALID_ENUM);
2264
2265 if (primitiveCount <= 0)
2266 {
2267 return;
2268 }
2269
2270 if (!applyRenderTarget(false))
2271 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002272 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002273 }
2274
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002275 applyState(mode);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002276 TranslatedIndexData indexInfo = applyIndexBuffer(indices, count, mode, type);
2277 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002278 applyShaders();
2279 applyTextures();
2280
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002281 if (!getCurrentProgram()->validateSamplers())
2282 {
2283 return error(GL_INVALID_OPERATION);
2284 }
2285
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002286 if (!cullSkipsDraw(mode))
2287 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002288 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002289 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 +00002290 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002291}
2292
2293void Context::finish()
2294{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002295 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002296 IDirect3DDevice9 *device = getDevice();
2297 IDirect3DQuery9 *occlusionQuery = NULL;
2298
2299 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2300
2301 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2302 {
2303 return error(GL_OUT_OF_MEMORY);
2304 }
2305
2306 ASSERT(SUCCEEDED(result));
2307
2308 if (occlusionQuery)
2309 {
2310 occlusionQuery->Issue(D3DISSUE_BEGIN);
2311
2312 // Render something outside the render target
2313 device->SetPixelShader(NULL);
2314 device->SetVertexShader(NULL);
2315 device->SetFVF(D3DFVF_XYZRHW);
2316 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002317 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002318 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002319
2320 occlusionQuery->Issue(D3DISSUE_END);
2321
2322 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2323 {
2324 // Keep polling, but allow other threads to do something useful first
2325 Sleep(0);
2326 }
2327
2328 occlusionQuery->Release();
2329 }
2330}
2331
2332void Context::flush()
2333{
2334 IDirect3DDevice9 *device = getDevice();
2335 IDirect3DQuery9 *eventQuery = NULL;
2336
2337 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2338
2339 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2340 {
2341 return error(GL_OUT_OF_MEMORY);
2342 }
2343
2344 ASSERT(SUCCEEDED(result));
2345
2346 if (eventQuery)
2347 {
2348 eventQuery->Issue(D3DISSUE_END);
2349
2350 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2351 {
2352 // Keep polling, but allow other threads to do something useful first
2353 Sleep(0);
2354 }
2355
2356 eventQuery->Release();
2357 }
2358}
2359
2360void Context::recordInvalidEnum()
2361{
2362 mInvalidEnum = true;
2363}
2364
2365void Context::recordInvalidValue()
2366{
2367 mInvalidValue = true;
2368}
2369
2370void Context::recordInvalidOperation()
2371{
2372 mInvalidOperation = true;
2373}
2374
2375void Context::recordOutOfMemory()
2376{
2377 mOutOfMemory = true;
2378}
2379
2380void Context::recordInvalidFramebufferOperation()
2381{
2382 mInvalidFramebufferOperation = true;
2383}
2384
2385// Get one of the recorded errors and clear its flag, if any.
2386// [OpenGL ES 2.0.24] section 2.5 page 13.
2387GLenum Context::getError()
2388{
2389 if (mInvalidEnum)
2390 {
2391 mInvalidEnum = false;
2392
2393 return GL_INVALID_ENUM;
2394 }
2395
2396 if (mInvalidValue)
2397 {
2398 mInvalidValue = false;
2399
2400 return GL_INVALID_VALUE;
2401 }
2402
2403 if (mInvalidOperation)
2404 {
2405 mInvalidOperation = false;
2406
2407 return GL_INVALID_OPERATION;
2408 }
2409
2410 if (mOutOfMemory)
2411 {
2412 mOutOfMemory = false;
2413
2414 return GL_OUT_OF_MEMORY;
2415 }
2416
2417 if (mInvalidFramebufferOperation)
2418 {
2419 mInvalidFramebufferOperation = false;
2420
2421 return GL_INVALID_FRAMEBUFFER_OPERATION;
2422 }
2423
2424 return GL_NO_ERROR;
2425}
2426
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002427const char *Context::getPixelShaderProfile()
2428{
2429 return mPsProfile;
2430}
2431
2432const char *Context::getVertexShaderProfile()
2433{
2434 return mVsProfile;
2435}
2436
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002437void Context::detachBuffer(GLuint buffer)
2438{
2439 // [OpenGL ES 2.0.24] section 2.9 page 22:
2440 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2441 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2442
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002443 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002444 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002445 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002446 }
2447
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002448 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002449 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002450 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002451 }
2452
2453 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2454 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002455 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002456 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002457 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002458 }
2459 }
2460}
2461
2462void Context::detachTexture(GLuint texture)
2463{
2464 // [OpenGL ES 2.0.24] section 3.8 page 84:
2465 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2466 // rebound to texture object zero
2467
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002468 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002469 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002470 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002471 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002472 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002473 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002474 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002475 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002476 }
2477 }
2478
2479 // [OpenGL ES 2.0.24] section 4.4 page 112:
2480 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2481 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2482 // image was attached in the currently bound framebuffer.
2483
2484 Framebuffer *framebuffer = getFramebuffer();
2485
2486 if (framebuffer)
2487 {
2488 framebuffer->detachTexture(texture);
2489 }
2490}
2491
2492void Context::detachFramebuffer(GLuint framebuffer)
2493{
2494 // [OpenGL ES 2.0.24] section 4.4 page 107:
2495 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2496 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2497
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002498 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002499 {
2500 bindFramebuffer(0);
2501 }
2502}
2503
2504void Context::detachRenderbuffer(GLuint renderbuffer)
2505{
2506 // [OpenGL ES 2.0.24] section 4.4 page 109:
2507 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2508 // had been executed with the target RENDERBUFFER and name of zero.
2509
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002510 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002511 {
2512 bindRenderbuffer(0);
2513 }
2514
2515 // [OpenGL ES 2.0.24] section 4.4 page 111:
2516 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2517 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2518 // point to which this image was attached in the currently bound framebuffer.
2519
2520 Framebuffer *framebuffer = getFramebuffer();
2521
2522 if (framebuffer)
2523 {
2524 framebuffer->detachRenderbuffer(renderbuffer);
2525 }
2526}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002527
2528Texture *Context::getIncompleteTexture(SamplerType type)
2529{
2530 Texture *t = mIncompleteTextures[type];
2531
2532 if (t == NULL)
2533 {
2534 static const GLubyte color[] = { 0, 0, 0, 255 };
2535
2536 switch (type)
2537 {
2538 default:
2539 UNREACHABLE();
2540 // default falls through to SAMPLER_2D
2541
2542 case SAMPLER_2D:
2543 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002544 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002545 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002546 t = incomplete2d;
2547 }
2548 break;
2549
2550 case SAMPLER_CUBE:
2551 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002552 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002553
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002554 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2555 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2556 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2557 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2558 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2559 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002560
2561 t = incompleteCube;
2562 }
2563 break;
2564 }
2565
2566 mIncompleteTextures[type] = t;
2567 }
2568
2569 return t;
2570}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002571
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002572bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002573{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002574 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002575}
2576
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002577bool Context::isTriangleMode(GLenum drawMode)
2578{
2579 switch (drawMode)
2580 {
2581 case GL_TRIANGLES:
2582 case GL_TRIANGLE_FAN:
2583 case GL_TRIANGLE_STRIP:
2584 return true;
2585 case GL_POINTS:
2586 case GL_LINES:
2587 case GL_LINE_LOOP:
2588 case GL_LINE_STRIP:
2589 return false;
2590 default: UNREACHABLE();
2591 }
2592
2593 return false;
2594}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002595
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002596bool Context::hasStencil()
2597{
2598 Framebuffer *framebufferObject = getFramebuffer();
2599
2600 if (framebufferObject)
2601 {
2602 Stencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
2603
2604 if (stencilbufferObject)
2605 {
2606 return stencilbufferObject->getStencilSize() > 0;
2607 }
2608 }
2609
2610 return false;
2611}
2612
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002613void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2614{
2615 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2616
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002617 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2618 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2619 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2620 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002621
2622 mVertexDataManager->dirtyCurrentValues();
2623}
2624
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002625void Context::initExtensionString()
2626{
2627 if (mBufferBackEnd->supportIntIndices())
2628 {
2629 mExtensionString += "GL_OES_element_index_uint ";
2630 }
2631
2632 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2633 if (end != std::string::npos)
2634 {
2635 mExtensionString.resize(end+1);
2636 }
2637}
2638
2639const char *Context::getExtensionString() const
2640{
2641 return mExtensionString.c_str();
2642}
2643
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002644}
2645
2646extern "C"
2647{
2648gl::Context *glCreateContext(const egl::Config *config)
2649{
2650 return new gl::Context(config);
2651}
2652
2653void glDestroyContext(gl::Context *context)
2654{
2655 delete context;
2656
2657 if (context == gl::getContext())
2658 {
2659 gl::makeCurrent(NULL, NULL, NULL);
2660 }
2661}
2662
2663void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2664{
2665 gl::makeCurrent(context, display, surface);
2666}
2667
2668gl::Context *glGetCurrentContext()
2669{
2670 return gl::getContext();
2671}
2672}