blob: bece470574eb5932d936e32c65f79e7954a442df [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Context.cpp: Implements the gl::Context class, managing all GL state and performing
8// rendering operations. It is the GLES2 specific implementation of EGLContext.
9
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Context.h"
daniel@transgaming.com16973022010-03-11 19:22:19 +000011
12#include <algorithm>
13
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000014#include "libEGL/Display.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000015
16#include "libGLESv2/main.h"
17#include "libGLESv2/mathutil.h"
18#include "libGLESv2/utilities.h"
19#include "libGLESv2/Blit.h"
20#include "libGLESv2/Buffer.h"
21#include "libGLESv2/FrameBuffer.h"
22#include "libGLESv2/Program.h"
23#include "libGLESv2/RenderBuffer.h"
24#include "libGLESv2/Shader.h"
25#include "libGLESv2/Texture.h"
26#include "libGLESv2/geometry/backend.h"
27#include "libGLESv2/geometry/VertexDataManager.h"
28#include "libGLESv2/geometry/IndexDataManager.h"
29#include "libGLESv2/geometry/dx9.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030
daniel@transgaming.com86487c22010-03-11 19:41:43 +000031#undef near
32#undef far
33
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034namespace gl
35{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000036Context::Context(const egl::Config *config)
37 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038{
39 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com428d1582010-05-04 03:35:25 +000040 mState.depthClearValue = 1.0f;
41 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042
daniel@transgaming.com428d1582010-05-04 03:35:25 +000043 mState.cullFace = false;
44 mState.cullMode = GL_BACK;
45 mState.frontFace = GL_CCW;
46 mState.depthTest = false;
47 mState.depthFunc = GL_LESS;
48 mState.blend = false;
49 mState.sourceBlendRGB = GL_ONE;
50 mState.sourceBlendAlpha = GL_ONE;
51 mState.destBlendRGB = GL_ZERO;
52 mState.destBlendAlpha = GL_ZERO;
53 mState.blendEquationRGB = GL_FUNC_ADD;
54 mState.blendEquationAlpha = GL_FUNC_ADD;
55 mState.blendColor.red = 0;
56 mState.blendColor.green = 0;
57 mState.blendColor.blue = 0;
58 mState.blendColor.alpha = 0;
59 mState.stencilTest = false;
60 mState.stencilFunc = GL_ALWAYS;
61 mState.stencilRef = 0;
62 mState.stencilMask = -1;
63 mState.stencilWritemask = -1;
64 mState.stencilBackFunc = GL_ALWAYS;
65 mState.stencilBackRef = 0;
66 mState.stencilBackMask = - 1;
67 mState.stencilBackWritemask = -1;
68 mState.stencilFail = GL_KEEP;
69 mState.stencilPassDepthFail = GL_KEEP;
70 mState.stencilPassDepthPass = GL_KEEP;
71 mState.stencilBackFail = GL_KEEP;
72 mState.stencilBackPassDepthFail = GL_KEEP;
73 mState.stencilBackPassDepthPass = GL_KEEP;
74 mState.polygonOffsetFill = false;
75 mState.polygonOffsetFactor = 0.0f;
76 mState.polygonOffsetUnits = 0.0f;
77 mState.sampleAlphaToCoverage = false;
78 mState.sampleCoverage = false;
79 mState.sampleCoverageValue = 1.0f;
80 mState.sampleCoverageInvert = GL_FALSE;
81 mState.scissorTest = false;
82 mState.dither = true;
83 mState.generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084
daniel@transgaming.com428d1582010-05-04 03:35:25 +000085 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000086
daniel@transgaming.com428d1582010-05-04 03:35:25 +000087 mState.viewportX = 0;
88 mState.viewportY = 0;
89 mState.viewportWidth = config->mDisplayMode.Width;
90 mState.viewportHeight = config->mDisplayMode.Height;
91 mState.zNear = 0.0f;
92 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000093
daniel@transgaming.com428d1582010-05-04 03:35:25 +000094 mState.scissorX = 0;
95 mState.scissorY = 0;
96 mState.scissorWidth = config->mDisplayMode.Width;
97 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098
daniel@transgaming.com428d1582010-05-04 03:35:25 +000099 mState.colorMaskRed = true;
100 mState.colorMaskGreen = true;
101 mState.colorMaskBlue = true;
102 mState.colorMaskAlpha = true;
103 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104
105 // [OpenGL ES 2.0.24] section 3.7 page 83:
106 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
107 // and cube map texture state vectors respectively associated with them.
108 // In order that access to these initial textures not be lost, they are treated as texture
109 // objects all of whose names are 0.
110
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000111 mTexture2DZero = new Texture2D(this);
112 mTextureCubeMapZero = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113
114 mColorbufferZero = NULL;
115 mDepthbufferZero = NULL;
116 mStencilbufferZero = NULL;
117
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000118 mState.activeSampler = 0;
119 mState.arrayBuffer = 0;
120 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121 bindTextureCubeMap(0);
122 bindTexture2D(0);
123 bindFramebuffer(0);
124 bindRenderbuffer(0);
125
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000126 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000128 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
129 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000130 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000131 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132 }
133
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000134 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
135 {
136 mIncompleteTextures[type] = NULL;
137 }
138
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000139 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000141 mState.packAlignment = 4;
142 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000143
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000144 mBufferBackEnd = NULL;
145 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000146 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000147 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000148
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149 mInvalidEnum = false;
150 mInvalidValue = false;
151 mInvalidOperation = false;
152 mOutOfMemory = false;
153 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000154
155 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000156
157 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000158}
159
160Context::~Context()
161{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000162 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000163
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000164 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
165 {
166 delete mIncompleteTextures[type];
167 }
168
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169 delete mTexture2DZero;
170 delete mTextureCubeMapZero;
171
172 delete mColorbufferZero;
173 delete mDepthbufferZero;
174 delete mStencilbufferZero;
175
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000176 delete mBufferBackEnd;
177 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000178 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000179 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000180
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181 while (!mBufferMap.empty())
182 {
183 deleteBuffer(mBufferMap.begin()->first);
184 }
185
186 while (!mProgramMap.empty())
187 {
188 deleteProgram(mProgramMap.begin()->first);
189 }
190
191 while (!mShaderMap.empty())
192 {
193 deleteShader(mShaderMap.begin()->first);
194 }
195
196 while (!mFramebufferMap.empty())
197 {
198 deleteFramebuffer(mFramebufferMap.begin()->first);
199 }
200
201 while (!mRenderbufferMap.empty())
202 {
203 deleteRenderbuffer(mRenderbufferMap.begin()->first);
204 }
205
206 while (!mTextureMap.empty())
207 {
208 deleteTexture(mTextureMap.begin()->first);
209 }
210}
211
212void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
213{
214 IDirect3DDevice9 *device = display->getDevice();
215
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000216 if (!mBufferBackEnd)
217 {
218 mBufferBackEnd = new Dx9BackEnd(device);
219 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000220 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000221 mBlit = new Blit(this);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000222 }
223
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
225 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000226 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000227
228 Framebuffer *framebufferZero = new Framebuffer();
229 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000230 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
231 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232
233 setFramebufferZero(framebufferZero);
234 setColorbufferZero(colorbufferZero);
235 setDepthbufferZero(depthbufferZero);
236 setStencilbufferZero(stencilbufferZero);
237
238 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
239 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
240 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
241
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000242 if (!mHasBeenCurrent)
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000243 {
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000244 initExtensionString();
245
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000246 mState.viewportX = 0;
247 mState.viewportY = 0;
248 mState.viewportWidth = surface->getWidth();
249 mState.viewportHeight = surface->getHeight();
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000250
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000251 mState.scissorX = 0;
252 mState.scissorY = 0;
253 mState.scissorWidth = surface->getWidth();
254 mState.scissorHeight = surface->getHeight();
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000255
256 mHasBeenCurrent = true;
257 }
258
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259 defaultRenderTarget->Release();
260
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000261 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000263 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000265
266 D3DCAPS9 capabilities;
267 device->GetDeviceCaps(&capabilities);
268
269 if (capabilities.PixelShaderVersion == D3DPS_VERSION(3, 0))
270 {
271 mPsProfile = "ps_3_0";
272 mVsProfile = "vs_3_0";
273 }
274 else // egl::Display guarantees support for at least 2.0
275 {
276 mPsProfile = "ps_2_0";
277 mVsProfile = "vs_2_0";
278 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279}
280
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000281void Context::markAllStateDirty()
282{
283 mAppliedProgram = 0;
284}
285
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286void Context::setClearColor(float red, float green, float blue, float alpha)
287{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000288 mState.colorClearValue.red = red;
289 mState.colorClearValue.green = green;
290 mState.colorClearValue.blue = blue;
291 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292}
293
294void Context::setClearDepth(float depth)
295{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000296 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297}
298
299void Context::setClearStencil(int stencil)
300{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000301 mState.stencilClearValue = stencil;
302}
303
304void Context::setCullFace(bool enabled)
305{
306 mState.cullFace = enabled;
307}
308
309bool Context::isCullFaceEnabled() const
310{
311 return mState.cullFace;
312}
313
314void Context::setCullMode(GLenum mode)
315{
316 mState.cullMode = mode;
317}
318
319void Context::setFrontFace(GLenum front)
320{
321 mState.frontFace = front;
322}
323
324void Context::setDepthTest(bool enabled)
325{
326 mState.depthTest = enabled;
327}
328
329bool Context::isDepthTestEnabled() const
330{
331 return mState.depthTest;
332}
333
334void Context::setDepthFunc(GLenum depthFunc)
335{
336 mState.depthFunc = depthFunc;
337}
338
339void Context::setDepthRange(float zNear, float zFar)
340{
341 mState.zNear = zNear;
342 mState.zFar = zFar;
343}
344
345void Context::setBlend(bool enabled)
346{
347 mState.blend = enabled;
348}
349
350bool Context::isBlendEnabled() const
351{
352 return mState.blend;
353}
354
355void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
356{
357 mState.sourceBlendRGB = sourceRGB;
358 mState.destBlendRGB = destRGB;
359 mState.sourceBlendAlpha = sourceAlpha;
360 mState.destBlendAlpha = destAlpha;
361}
362
363void Context::setBlendColor(float red, float green, float blue, float alpha)
364{
365 mState.blendColor.red = red;
366 mState.blendColor.green = green;
367 mState.blendColor.blue = blue;
368 mState.blendColor.alpha = alpha;
369}
370
371void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
372{
373 mState.blendEquationRGB = rgbEquation;
374 mState.blendEquationAlpha = alphaEquation;
375}
376
377void Context::setStencilTest(bool enabled)
378{
379 mState.stencilTest = enabled;
380}
381
382bool Context::isStencilTestEnabled() const
383{
384 return mState.stencilTest;
385}
386
387void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
388{
389 mState.stencilFunc = stencilFunc;
390 mState.stencilRef = stencilRef;
391 mState.stencilMask = stencilMask;
392}
393
394void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
395{
396 mState.stencilBackFunc = stencilBackFunc;
397 mState.stencilBackRef = stencilBackRef;
398 mState.stencilBackMask = stencilBackMask;
399}
400
401void Context::setStencilWritemask(GLuint stencilWritemask)
402{
403 mState.stencilWritemask = stencilWritemask;
404}
405
406void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
407{
408 mState.stencilBackWritemask = stencilBackWritemask;
409}
410
411void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
412{
413 mState.stencilFail = stencilFail;
414 mState.stencilPassDepthFail = stencilPassDepthFail;
415 mState.stencilPassDepthPass = stencilPassDepthPass;
416}
417
418void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
419{
420 mState.stencilBackFail = stencilBackFail;
421 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
422 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
423}
424
425void Context::setPolygonOffsetFill(bool enabled)
426{
427 mState.polygonOffsetFill = enabled;
428}
429
430bool Context::isPolygonOffsetFillEnabled() const
431{
432 return mState.polygonOffsetFill;
433}
434
435void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
436{
437 mState.polygonOffsetFactor = factor;
438 mState.polygonOffsetUnits = units;
439}
440
441void Context::setSampleAlphaToCoverage(bool enabled)
442{
443 mState.sampleAlphaToCoverage = enabled;
444}
445
446bool Context::isSampleAlphaToCoverageEnabled() const
447{
448 return mState.sampleAlphaToCoverage;
449}
450
451void Context::setSampleCoverage(bool enabled)
452{
453 mState.sampleCoverage = enabled;
454}
455
456bool Context::isSampleCoverageEnabled() const
457{
458 return mState.sampleCoverage;
459}
460
461void Context::setSampleCoverageParams(GLclampf value, GLboolean invert)
462{
463 mState.sampleCoverageValue = value;
464 mState.sampleCoverageInvert = invert;
465}
466
467void Context::setScissorTest(bool enabled)
468{
469 mState.scissorTest = enabled;
470}
471
472bool Context::isScissorTestEnabled() const
473{
474 return mState.scissorTest;
475}
476
477void Context::setDither(bool enabled)
478{
479 mState.dither = enabled;
480}
481
482bool Context::isDitherEnabled() const
483{
484 return mState.dither;
485}
486
487void Context::setLineWidth(GLfloat width)
488{
489 mState.lineWidth = width;
490}
491
492void Context::setGenerateMipmapHint(GLenum hint)
493{
494 mState.generateMipmapHint = hint;
495}
496
497void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
498{
499 mState.viewportX = x;
500 mState.viewportY = y;
501 mState.viewportWidth = width;
502 mState.viewportHeight = height;
503}
504
505void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
506{
507 mState.scissorX = x;
508 mState.scissorY = y;
509 mState.scissorWidth = width;
510 mState.scissorHeight = height;
511}
512
513void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
514{
515 mState.colorMaskRed = red;
516 mState.colorMaskGreen = green;
517 mState.colorMaskBlue = blue;
518 mState.colorMaskAlpha = alpha;
519}
520
521void Context::setDepthMask(bool mask)
522{
523 mState.depthMask = mask;
524}
525
526void Context::setActiveSampler(int active)
527{
528 mState.activeSampler = active;
529}
530
531GLuint Context::getFramebufferHandle() const
532{
533 return mState.framebuffer;
534}
535
536GLuint Context::getRenderbufferHandle() const
537{
538 return mState.renderbuffer;
539}
540
541GLuint Context::getArrayBufferHandle() const
542{
543 return mState.arrayBuffer;
544}
545
546void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
547{
548 mState.vertexAttribute[attribNum].mEnabled = enabled;
549}
550
551const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
552{
553 return mState.vertexAttribute[attribNum];
554}
555
556void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
557 GLsizei stride, const void *pointer)
558{
559 mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
560 mState.vertexAttribute[attribNum].mSize = size;
561 mState.vertexAttribute[attribNum].mType = type;
562 mState.vertexAttribute[attribNum].mNormalized = normalized;
563 mState.vertexAttribute[attribNum].mStride = stride;
564 mState.vertexAttribute[attribNum].mPointer = pointer;
565}
566
567const void *Context::getVertexAttribPointer(unsigned int attribNum) const
568{
569 return mState.vertexAttribute[attribNum].mPointer;
570}
571
572// returns entire set of attributes as a block
573const AttributeState *Context::getVertexAttribBlock()
574{
575 return mState.vertexAttribute;
576}
577
578void Context::setPackAlignment(GLint alignment)
579{
580 mState.packAlignment = alignment;
581}
582
583GLint Context::getPackAlignment() const
584{
585 return mState.packAlignment;
586}
587
588void Context::setUnpackAlignment(GLint alignment)
589{
590 mState.unpackAlignment = alignment;
591}
592
593GLint Context::getUnpackAlignment() const
594{
595 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000596}
597
598// Returns an unused buffer name
599GLuint Context::createBuffer()
600{
601 unsigned int handle = 1;
602
603 while (mBufferMap.find(handle) != mBufferMap.end())
604 {
605 handle++;
606 }
607
608 mBufferMap[handle] = NULL;
609
610 return handle;
611}
612
613// Returns an unused shader/program name
614GLuint Context::createShader(GLenum type)
615{
616 unsigned int handle = 1;
617
618 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
619 {
620 handle++;
621 }
622
623 if (type == GL_VERTEX_SHADER)
624 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000625 mShaderMap[handle] = new VertexShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626 }
627 else if (type == GL_FRAGMENT_SHADER)
628 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000629 mShaderMap[handle] = new FragmentShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000630 }
631 else UNREACHABLE();
632
633 return handle;
634}
635
636// Returns an unused program/shader name
637GLuint Context::createProgram()
638{
639 unsigned int handle = 1;
640
641 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
642 {
643 handle++;
644 }
645
646 mProgramMap[handle] = new Program();
647
648 return handle;
649}
650
651// Returns an unused texture name
652GLuint Context::createTexture()
653{
654 unsigned int handle = 1;
655
656 while (mTextureMap.find(handle) != mTextureMap.end())
657 {
658 handle++;
659 }
660
661 mTextureMap[handle] = NULL;
662
663 return handle;
664}
665
666// Returns an unused framebuffer name
667GLuint Context::createFramebuffer()
668{
669 unsigned int handle = 1;
670
671 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
672 {
673 handle++;
674 }
675
676 mFramebufferMap[handle] = NULL;
677
678 return handle;
679}
680
681// Returns an unused renderbuffer name
682GLuint Context::createRenderbuffer()
683{
684 unsigned int handle = 1;
685
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000686 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000687 {
688 handle++;
689 }
690
691 mRenderbufferMap[handle] = NULL;
692
693 return handle;
694}
695
696void Context::deleteBuffer(GLuint buffer)
697{
698 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
699
700 if (bufferObject != mBufferMap.end())
701 {
702 detachBuffer(buffer);
703
704 delete bufferObject->second;
705 mBufferMap.erase(bufferObject);
706 }
707}
708
709void Context::deleteShader(GLuint shader)
710{
711 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
712
713 if (shaderObject != mShaderMap.end())
714 {
715 if (!shaderObject->second->isAttached())
716 {
717 delete shaderObject->second;
718 mShaderMap.erase(shaderObject);
719 }
720 else
721 {
722 shaderObject->second->flagForDeletion();
723 }
724 }
725}
726
727void Context::deleteProgram(GLuint program)
728{
729 ProgramMap::iterator programObject = mProgramMap.find(program);
730
731 if (programObject != mProgramMap.end())
732 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000733 if (program != mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000734 {
735 delete programObject->second;
736 mProgramMap.erase(programObject);
737 }
738 else
739 {
740 programObject->second->flagForDeletion();
741 }
742 }
743}
744
745void Context::deleteTexture(GLuint texture)
746{
747 TextureMap::iterator textureObject = mTextureMap.find(texture);
748
749 if (textureObject != mTextureMap.end())
750 {
751 detachTexture(texture);
752
753 if (texture != 0)
754 {
755 delete textureObject->second;
756 }
757
758 mTextureMap.erase(textureObject);
759 }
760}
761
762void Context::deleteFramebuffer(GLuint framebuffer)
763{
764 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
765
766 if (framebufferObject != mFramebufferMap.end())
767 {
768 detachFramebuffer(framebuffer);
769
770 delete framebufferObject->second;
771 mFramebufferMap.erase(framebufferObject);
772 }
773}
774
775void Context::deleteRenderbuffer(GLuint renderbuffer)
776{
777 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
778
779 if (renderbufferObject != mRenderbufferMap.end())
780 {
781 detachRenderbuffer(renderbuffer);
782
783 delete renderbufferObject->second;
784 mRenderbufferMap.erase(renderbufferObject);
785 }
786}
787
788void Context::bindArrayBuffer(unsigned int buffer)
789{
790 if (buffer != 0 && !getBuffer(buffer))
791 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000792 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000793 }
794
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000795 mState.arrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000796}
797
798void Context::bindElementArrayBuffer(unsigned int buffer)
799{
800 if (buffer != 0 && !getBuffer(buffer))
801 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000802 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000803 }
804
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000805 mState.elementArrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000806}
807
808void Context::bindTexture2D(GLuint texture)
809{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000810 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000811 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000812 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000813 }
814
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000815 mState.texture2D = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000816
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000817 mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818}
819
820void Context::bindTextureCubeMap(GLuint texture)
821{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000822 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000823 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000824 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000825 }
826
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000827 mState.textureCubeMap = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000828
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000829 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000830}
831
832void Context::bindFramebuffer(GLuint framebuffer)
833{
834 if (!getFramebuffer(framebuffer))
835 {
836 mFramebufferMap[framebuffer] = new Framebuffer();
837 }
838
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000839 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000840}
841
842void Context::bindRenderbuffer(GLuint renderbuffer)
843{
844 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
845 {
846 mRenderbufferMap[renderbuffer] = new Renderbuffer();
847 }
848
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000849 mState.renderbuffer = renderbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000850}
851
852void Context::useProgram(GLuint program)
853{
854 Program *programObject = getCurrentProgram();
855
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000856 GLuint priorProgram = mState.currentProgram;
857 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000858
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000859 if (programObject && programObject->isFlaggedForDeletion())
860 {
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000861 deleteProgram(priorProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000862 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000863}
864
865void Context::setFramebufferZero(Framebuffer *buffer)
866{
867 delete mFramebufferMap[0];
868 mFramebufferMap[0] = buffer;
869}
870
871void Context::setColorbufferZero(Colorbuffer *buffer)
872{
873 delete mColorbufferZero;
874 mColorbufferZero = buffer;
875}
876
877void Context::setDepthbufferZero(Depthbuffer *buffer)
878{
879 delete mDepthbufferZero;
880 mDepthbufferZero = buffer;
881}
882
883void Context::setStencilbufferZero(Stencilbuffer *buffer)
884{
885 delete mStencilbufferZero;
886 mStencilbufferZero = buffer;
887}
888
889void Context::setRenderbuffer(Renderbuffer *buffer)
890{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000891 delete mRenderbufferMap[mState.renderbuffer];
892 mRenderbufferMap[mState.renderbuffer] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000893}
894
895Buffer *Context::getBuffer(unsigned int handle)
896{
897 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000898
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000899 if (buffer == mBufferMap.end())
900 {
901 return NULL;
902 }
903 else
904 {
905 return buffer->second;
906 }
907}
908
909Shader *Context::getShader(unsigned int handle)
910{
911 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000912
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000913 if (shader == mShaderMap.end())
914 {
915 return NULL;
916 }
917 else
918 {
919 return shader->second;
920 }
921}
922
923Program *Context::getProgram(unsigned int handle)
924{
925 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000926
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000927 if (program == mProgramMap.end())
928 {
929 return NULL;
930 }
931 else
932 {
933 return program->second;
934 }
935}
936
937Texture *Context::getTexture(unsigned int handle)
938{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000939 if (handle == 0) return NULL;
940
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000941 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000942
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000943 if (texture == mTextureMap.end())
944 {
945 return NULL;
946 }
947 else
948 {
949 return texture->second;
950 }
951}
952
953Framebuffer *Context::getFramebuffer(unsigned int handle)
954{
955 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000956
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000957 if (framebuffer == mFramebufferMap.end())
958 {
959 return NULL;
960 }
961 else
962 {
963 return framebuffer->second;
964 }
965}
966
967Renderbuffer *Context::getRenderbuffer(unsigned int handle)
968{
969 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000970
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000971 if (renderbuffer == mRenderbufferMap.end())
972 {
973 return NULL;
974 }
975 else
976 {
977 return renderbuffer->second;
978 }
979}
980
981Colorbuffer *Context::getColorbuffer(GLuint handle)
982{
983 if (handle != 0)
984 {
985 Renderbuffer *renderbuffer = getRenderbuffer(handle);
986
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000987 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000988 {
989 return static_cast<Colorbuffer*>(renderbuffer);
990 }
991 }
992 else // Special case: 0 refers to different initial render targets based on the attachment type
993 {
994 return mColorbufferZero;
995 }
996
997 return NULL;
998}
999
1000Depthbuffer *Context::getDepthbuffer(GLuint handle)
1001{
1002 if (handle != 0)
1003 {
1004 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1005
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001006 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001007 {
1008 return static_cast<Depthbuffer*>(renderbuffer);
1009 }
1010 }
1011 else // Special case: 0 refers to different initial render targets based on the attachment type
1012 {
1013 return mDepthbufferZero;
1014 }
1015
1016 return NULL;
1017}
1018
1019Stencilbuffer *Context::getStencilbuffer(GLuint handle)
1020{
1021 if (handle != 0)
1022 {
1023 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1024
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001025 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001026 {
1027 return static_cast<Stencilbuffer*>(renderbuffer);
1028 }
1029 }
1030 else
1031 {
1032 return mStencilbufferZero;
1033 }
1034
1035 return NULL;
1036}
1037
1038Buffer *Context::getArrayBuffer()
1039{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001040 return getBuffer(mState.arrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001041}
1042
1043Buffer *Context::getElementArrayBuffer()
1044{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001045 return getBuffer(mState.elementArrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001046}
1047
1048Program *Context::getCurrentProgram()
1049{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001050 return getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001051}
1052
1053Texture2D *Context::getTexture2D()
1054{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001055 if (mState.texture2D == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001056 {
1057 return mTexture2DZero;
1058 }
1059
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001060 return (Texture2D*)getTexture(mState.texture2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001061}
1062
1063TextureCubeMap *Context::getTextureCubeMap()
1064{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001065 if (mState.textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001066 {
1067 return mTextureCubeMapZero;
1068 }
1069
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001070 return (TextureCubeMap*)getTexture(mState.textureCubeMap);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001071}
1072
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001073Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001074{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001075 GLuint texid = mState.samplerTexture[type][sampler];
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001076
1077 if (texid == 0)
1078 {
1079 switch (type)
1080 {
1081 default: UNREACHABLE();
1082 case SAMPLER_2D: return mTexture2DZero;
1083 case SAMPLER_CUBE: return mTextureCubeMapZero;
1084 }
1085 }
1086
1087 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001088}
1089
1090Framebuffer *Context::getFramebuffer()
1091{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001092 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001093}
1094
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001095bool Context::getBooleanv(GLenum pname, GLboolean *params)
1096{
1097 switch (pname)
1098 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001099 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1100 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1101 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001102 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001103 params[0] = mState.colorMaskRed;
1104 params[1] = mState.colorMaskGreen;
1105 params[2] = mState.colorMaskBlue;
1106 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001107 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001108 case GL_CULL_FACE: *params = mState.cullFace;
1109 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1110 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1111 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1112 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1113 case GL_STENCIL_TEST: *params = mState.stencilTest;
1114 case GL_DEPTH_TEST: *params = mState.depthTest;
1115 case GL_BLEND: *params = mState.blend;
1116 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001117 default:
1118 return false;
1119 }
1120
1121 return true;
1122}
1123
1124bool Context::getFloatv(GLenum pname, GLfloat *params)
1125{
1126 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1127 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1128 // GetIntegerv as its native query function. As it would require conversion in any
1129 // case, this should make no difference to the calling application.
1130 switch (pname)
1131 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001132 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1133 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1134 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1135 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1136 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001137 case GL_ALIASED_LINE_WIDTH_RANGE:
1138 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1139 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1140 break;
1141 case GL_ALIASED_POINT_SIZE_RANGE:
1142 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
1143 params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
1144 break;
1145 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001146 params[0] = mState.zNear;
1147 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001148 break;
1149 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001150 params[0] = mState.colorClearValue.red;
1151 params[1] = mState.colorClearValue.green;
1152 params[2] = mState.colorClearValue.blue;
1153 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001154 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001155 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001156 params[0] = mState.blendColor.red;
1157 params[1] = mState.blendColor.green;
1158 params[2] = mState.blendColor.blue;
1159 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001160 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001161 default:
1162 return false;
1163 }
1164
1165 return true;
1166}
1167
1168bool Context::getIntegerv(GLenum pname, GLint *params)
1169{
1170 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1171 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1172 // GetIntegerv as its native query function. As it would require conversion in any
1173 // case, this should make no difference to the calling application. You may find it in
1174 // Context::getFloatv.
1175 switch (pname)
1176 {
1177 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1178 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1179 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1180 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1181 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1182 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1183 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1184 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
1185 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1186 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1187 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1188 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001189 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer; break;
1190 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer; break;
1191 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
1192 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer; break;
1193 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1194 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1195 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1196 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1197 case GL_ACTIVE_TEXTURE: *params = mState.activeSampler; break;
1198 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1199 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1200 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1201 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1202 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1203 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1204 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1205 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1206 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1207 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1208 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1209 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1210 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1211 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1212 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1213 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1214 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1215 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1216 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1217 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1218 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1219 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001220 case GL_SUBPIXEL_BITS: *params = 4; break;
1221 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1222 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1223 case GL_SAMPLE_BUFFERS: *params = 0; break;
1224 case GL_SAMPLES: *params = 0; break;
1225 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1226 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1227 case GL_MAX_VIEWPORT_DIMS:
1228 {
1229 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1230 params[0] = maxDimension;
1231 params[1] = maxDimension;
1232 }
1233 break;
1234 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001235 params[0] = mState.viewportX;
1236 params[1] = mState.viewportY;
1237 params[2] = mState.viewportWidth;
1238 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001239 break;
1240 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001241 params[0] = mState.scissorX;
1242 params[1] = mState.scissorY;
1243 params[2] = mState.scissorWidth;
1244 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001245 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001246 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1247 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001248 case GL_RED_BITS:
1249 case GL_GREEN_BITS:
1250 case GL_BLUE_BITS:
1251 case GL_ALPHA_BITS:
1252 {
1253 gl::Framebuffer *framebuffer = getFramebuffer();
1254 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1255
1256 if (colorbuffer)
1257 {
1258 switch (pname)
1259 {
1260 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1261 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1262 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1263 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1264 }
1265 }
1266 else
1267 {
1268 *params = 0;
1269 }
1270 }
1271 break;
1272 case GL_DEPTH_BITS:
1273 {
1274 gl::Framebuffer *framebuffer = getFramebuffer();
1275 gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
1276
1277 if (depthbuffer)
1278 {
1279 *params = depthbuffer->getDepthSize();
1280 }
1281 else
1282 {
1283 *params = 0;
1284 }
1285 }
1286 break;
1287 case GL_STENCIL_BITS:
1288 {
1289 gl::Framebuffer *framebuffer = getFramebuffer();
1290 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1291
1292 if (stencilbuffer)
1293 {
1294 *params = stencilbuffer->getStencilSize();
1295 }
1296 else
1297 {
1298 *params = 0;
1299 }
1300 }
1301 break;
1302 case GL_TEXTURE_BINDING_2D:
1303 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001304 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001305 {
1306 error(GL_INVALID_OPERATION);
1307 return false;
1308 }
1309
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001310 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001311 }
1312 break;
1313 case GL_TEXTURE_BINDING_CUBE_MAP:
1314 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001315 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001316 {
1317 error(GL_INVALID_OPERATION);
1318 return false;
1319 }
1320
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001321 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001322 }
1323 break;
1324 default:
1325 return false;
1326 }
1327
1328 return true;
1329}
1330
1331bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1332{
1333 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1334 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1335 // to the fact that it is stored internally as a float, and so would require conversion
1336 // if returned from Context::getIntegerv. Since this conversion is already implemented
1337 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1338 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1339 // application.
1340 switch (pname)
1341 {
1342 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1343 case GL_SHADER_BINARY_FORMATS:
1344 {
1345 *type = GL_INT;
1346 *numParams = 0;
1347 }
1348 break;
1349 case GL_MAX_VERTEX_ATTRIBS:
1350 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1351 case GL_MAX_VARYING_VECTORS:
1352 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1353 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1354 case GL_MAX_TEXTURE_IMAGE_UNITS:
1355 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1356 case GL_MAX_RENDERBUFFER_SIZE:
1357 case GL_NUM_SHADER_BINARY_FORMATS:
1358 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1359 case GL_ARRAY_BUFFER_BINDING:
1360 case GL_FRAMEBUFFER_BINDING:
1361 case GL_RENDERBUFFER_BINDING:
1362 case GL_CURRENT_PROGRAM:
1363 case GL_PACK_ALIGNMENT:
1364 case GL_UNPACK_ALIGNMENT:
1365 case GL_GENERATE_MIPMAP_HINT:
1366 case GL_RED_BITS:
1367 case GL_GREEN_BITS:
1368 case GL_BLUE_BITS:
1369 case GL_ALPHA_BITS:
1370 case GL_DEPTH_BITS:
1371 case GL_STENCIL_BITS:
1372 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1373 case GL_CULL_FACE_MODE:
1374 case GL_FRONT_FACE:
1375 case GL_ACTIVE_TEXTURE:
1376 case GL_STENCIL_FUNC:
1377 case GL_STENCIL_VALUE_MASK:
1378 case GL_STENCIL_REF:
1379 case GL_STENCIL_FAIL:
1380 case GL_STENCIL_PASS_DEPTH_FAIL:
1381 case GL_STENCIL_PASS_DEPTH_PASS:
1382 case GL_STENCIL_BACK_FUNC:
1383 case GL_STENCIL_BACK_VALUE_MASK:
1384 case GL_STENCIL_BACK_REF:
1385 case GL_STENCIL_BACK_FAIL:
1386 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1387 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1388 case GL_DEPTH_FUNC:
1389 case GL_BLEND_SRC_RGB:
1390 case GL_BLEND_SRC_ALPHA:
1391 case GL_BLEND_DST_RGB:
1392 case GL_BLEND_DST_ALPHA:
1393 case GL_BLEND_EQUATION_RGB:
1394 case GL_BLEND_EQUATION_ALPHA:
1395 case GL_STENCIL_WRITEMASK:
1396 case GL_STENCIL_BACK_WRITEMASK:
1397 case GL_STENCIL_CLEAR_VALUE:
1398 case GL_SUBPIXEL_BITS:
1399 case GL_MAX_TEXTURE_SIZE:
1400 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1401 case GL_SAMPLE_BUFFERS:
1402 case GL_SAMPLES:
1403 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1404 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1405 case GL_TEXTURE_BINDING_2D:
1406 case GL_TEXTURE_BINDING_CUBE_MAP:
1407 {
1408 *type = GL_INT;
1409 *numParams = 1;
1410 }
1411 break;
1412 case GL_MAX_VIEWPORT_DIMS:
1413 {
1414 *type = GL_INT;
1415 *numParams = 2;
1416 }
1417 break;
1418 case GL_VIEWPORT:
1419 case GL_SCISSOR_BOX:
1420 {
1421 *type = GL_INT;
1422 *numParams = 4;
1423 }
1424 break;
1425 case GL_SHADER_COMPILER:
1426 case GL_SAMPLE_COVERAGE_INVERT:
1427 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001428 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1429 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1430 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1431 case GL_SAMPLE_COVERAGE:
1432 case GL_SCISSOR_TEST:
1433 case GL_STENCIL_TEST:
1434 case GL_DEPTH_TEST:
1435 case GL_BLEND:
1436 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001437 {
1438 *type = GL_BOOL;
1439 *numParams = 1;
1440 }
1441 break;
1442 case GL_COLOR_WRITEMASK:
1443 {
1444 *type = GL_BOOL;
1445 *numParams = 4;
1446 }
1447 break;
1448 case GL_POLYGON_OFFSET_FACTOR:
1449 case GL_POLYGON_OFFSET_UNITS:
1450 case GL_SAMPLE_COVERAGE_VALUE:
1451 case GL_DEPTH_CLEAR_VALUE:
1452 case GL_LINE_WIDTH:
1453 {
1454 *type = GL_FLOAT;
1455 *numParams = 1;
1456 }
1457 break;
1458 case GL_ALIASED_LINE_WIDTH_RANGE:
1459 case GL_ALIASED_POINT_SIZE_RANGE:
1460 case GL_DEPTH_RANGE:
1461 {
1462 *type = GL_FLOAT;
1463 *numParams = 2;
1464 }
1465 break;
1466 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001467 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001468 {
1469 *type = GL_FLOAT;
1470 *numParams = 4;
1471 }
1472 break;
1473 default:
1474 return false;
1475 }
1476
1477 return true;
1478}
1479
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001480// Applies the render target surface, depth stencil surface, viewport rectangle and
1481// scissor rectangle to the Direct3D 9 device
1482bool Context::applyRenderTarget(bool ignoreViewport)
1483{
1484 IDirect3DDevice9 *device = getDevice();
1485 Framebuffer *framebufferObject = getFramebuffer();
1486
1487 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1488 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001489 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1490
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001491 return false;
1492 }
1493
1494 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1495 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1496
1497 device->SetRenderTarget(0, renderTarget);
1498 device->SetDepthStencilSurface(depthStencil);
1499
1500 D3DVIEWPORT9 viewport;
1501 D3DSURFACE_DESC desc;
1502 renderTarget->GetDesc(&desc);
1503
1504 if (ignoreViewport)
1505 {
1506 viewport.X = 0;
1507 viewport.Y = 0;
1508 viewport.Width = desc.Width;
1509 viewport.Height = desc.Height;
1510 viewport.MinZ = 0.0f;
1511 viewport.MaxZ = 1.0f;
1512 }
1513 else
1514 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001515 viewport.X = std::max(mState.viewportX, 0);
1516 viewport.Y = std::max(mState.viewportY, 0);
1517 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1518 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1519 viewport.MinZ = clamp01(mState.zNear);
1520 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001521 }
1522
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001523 if (viewport.Width <= 0 || viewport.Height <= 0)
1524 {
1525 return false; // Nothing to render
1526 }
1527
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001528 device->SetViewport(&viewport);
1529
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001530 if (mState.scissorTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001531 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001532 RECT rect = {mState.scissorX,
1533 mState.scissorY,
1534 mState.scissorX + mState.scissorWidth,
1535 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001536
1537 device->SetScissorRect(&rect);
1538 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1539 }
1540 else
1541 {
1542 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1543 }
1544
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001545 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001546 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001547 Program *programObject = getCurrentProgram();
1548
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001549 GLint halfPixelSize = programObject->getUniformLocation("dx_HalfPixelSize");
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001550 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001551 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001552
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001553 GLint window = programObject->getUniformLocation("dx_Window");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001554 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1555 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1556 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001557 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1558
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001559 GLint depth = programObject->getUniformLocation("dx_Depth");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001560 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001561 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1562
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001563 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001564 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001565
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001566 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001567 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001568
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001569 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001570 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001571 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001572 }
1573
1574 return true;
1575}
1576
1577// 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 +00001578void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001579{
1580 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001581 Program *programObject = getCurrentProgram();
1582
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001583 GLint frontCCW = programObject->getUniformLocation("dx_FrontCCW");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001584 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001585 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001586
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001587 GLint pointsOrLines = programObject->getUniformLocation("dx_PointsOrLines");
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001588 GLint alwaysFront = !isTriangleMode(drawMode);
1589 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1590
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001591 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001592 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001593 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001594 }
1595 else
1596 {
1597 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1598 }
1599
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001600 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001601 {
1602 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001603 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001604 }
1605 else
1606 {
1607 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
1608 }
1609
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001610 if (mState.blend)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001611 {
1612 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1613
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001614 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1615 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001616 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001617 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001618 }
1619 else
1620 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001621 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1622 unorm<8>(mState.blendColor.alpha),
1623 unorm<8>(mState.blendColor.alpha),
1624 unorm<8>(mState.blendColor.alpha)));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001625 }
1626
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001627 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1628 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1629 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001630
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001631 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1632 mState.destBlendRGB != mState.destBlendAlpha ||
1633 mState.blendEquationRGB != mState.blendEquationAlpha)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001634 {
1635 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1636
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001637 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1638 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1639 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001640
1641 }
1642 else
1643 {
1644 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1645 }
1646 }
1647 else
1648 {
1649 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1650 }
1651
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00001652 if (mState.stencilTest && hasStencil())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001653 {
1654 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1655 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1656
1657 // FIXME: Unsupported by D3D9
1658 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1659 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1660 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001661 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1662 mState.stencilRef != mState.stencilBackRef ||
1663 mState.stencilMask != mState.stencilBackMask)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001664 {
1665 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1666 return error(GL_INVALID_OPERATION);
1667 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001668
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001669 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1670 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1671 es2dx::ConvertComparison(mState.stencilFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001672
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001673 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilRef); // FIXME: Clamp to range
1674 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001675
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001676 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1677 es2dx::ConvertStencilOp(mState.stencilFail));
1678 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1679 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1680 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1681 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001682
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001683 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1684 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1685 es2dx::ConvertComparison(mState.stencilBackFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001686
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001687 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilBackRef); // FIXME: Clamp to range
1688 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001689
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001690 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1691 es2dx::ConvertStencilOp(mState.stencilBackFail));
1692 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1693 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1694 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1695 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001696 }
1697 else
1698 {
1699 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1700 }
1701
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001702 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1703 mState.colorMaskBlue, mState.colorMaskAlpha));
1704 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001705
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001706 if (mState.polygonOffsetFill)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001707 {
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001708 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1709 if (depthbuffer)
1710 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001711 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1712 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001713 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1714 }
1715 }
1716 else
1717 {
1718 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1719 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001720 }
1721
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001722 if (mConfig->mMultiSample != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001723 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001724 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001725 {
1726 FIXME("Sample alpha to coverage is unimplemented.");
1727 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001728
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001729 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001730 {
1731 FIXME("Sample coverage is unimplemented.");
1732 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001733 }
1734
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001735 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001736}
1737
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001738// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001739void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001740{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001741 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001742 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001743 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001744 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001745 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001746 }
1747 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001748}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001749
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001750void Context::applyVertexBuffer(GLint first, GLsizei count)
1751{
1752 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1753
1754 mVertexDataManager->preRenderValidate(first, count, translated);
1755
1756 lookupAttributeMapping(translated);
1757
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001758 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001759}
1760
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001761void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001762{
1763 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1764
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00001765 mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001766
1767 lookupAttributeMapping(translated);
1768
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001769 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001770}
1771
1772// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001773TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001774{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001775 TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001776 mBufferBackEnd->setupIndicesPreDraw(indexInfo);
1777 return indexInfo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001778}
1779
1780// Applies the shaders and shader constants to the Direct3D 9 device
1781void Context::applyShaders()
1782{
1783 IDirect3DDevice9 *device = getDevice();
1784 Program *programObject = getCurrentProgram();
1785 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1786 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1787
1788 device->SetVertexShader(vertexShader);
1789 device->SetPixelShader(pixelShader);
1790
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001791 if (programObject->getSerial() != mAppliedProgram)
1792 {
1793 programObject->dirtyAllUniforms();
1794 mAppliedProgram = programObject->getSerial();
1795 }
1796
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001797 programObject->applyUniforms();
1798}
1799
1800// Applies the textures and sampler states to the Direct3D 9 device
1801void Context::applyTextures()
1802{
1803 IDirect3DDevice9 *device = getDevice();
1804 Program *programObject = getCurrentProgram();
1805
1806 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1807 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001808 int textureUnit = programObject->getSamplerMapping(sampler);
1809 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001810 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001811 SamplerType textureType = programObject->getSamplerType(sampler);
1812
1813 Texture *texture = getSamplerTexture(textureUnit, textureType);
1814
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001815 if (texture->isComplete())
1816 {
1817 GLenum wrapS = texture->getWrapS();
1818 GLenum wrapT = texture->getWrapT();
1819 GLenum minFilter = texture->getMinFilter();
1820 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001821
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001822 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1823 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001824
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001825 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1826 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1827 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1828 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1829 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001830
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001831 device->SetTexture(sampler, texture->getTexture());
1832 }
1833 else
1834 {
1835 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1836 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001837 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001838 else
1839 {
1840 device->SetTexture(sampler, NULL);
1841 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001842 }
1843}
1844
1845void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1846{
1847 Framebuffer *framebuffer = getFramebuffer();
1848 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1849 IDirect3DDevice9 *device = getDevice();
1850
1851 D3DSURFACE_DESC desc;
1852 renderTarget->GetDesc(&desc);
1853
1854 IDirect3DSurface9 *systemSurface;
1855 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1856
1857 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1858 {
1859 return error(GL_OUT_OF_MEMORY);
1860 }
1861
1862 ASSERT(SUCCEEDED(result));
1863
1864 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1865 {
1866 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1867 }
1868
1869 result = device->GetRenderTargetData(renderTarget, systemSurface);
1870
1871 if (result == D3DERR_DRIVERINTERNALERROR)
1872 {
1873 systemSurface->Release();
1874
1875 return error(GL_OUT_OF_MEMORY);
1876 }
1877
1878 if (FAILED(result))
1879 {
1880 UNREACHABLE();
1881 systemSurface->Release();
1882
1883 return; // No sensible error to generate
1884 }
1885
1886 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001887 RECT rect = {std::max(x, 0),
1888 std::max(y, 0),
1889 std::min(x + width, (int)desc.Width),
1890 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001891
1892 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1893
1894 if (FAILED(result))
1895 {
1896 UNREACHABLE();
1897 systemSurface->Release();
1898
1899 return; // No sensible error to generate
1900 }
1901
1902 unsigned char *source = (unsigned char*)lock.pBits;
1903 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001904 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001905
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001906 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001907
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001908 for (int j = 0; j < rect.bottom - rect.top; j++)
1909 {
1910 for (int i = 0; i < rect.right - rect.left; i++)
1911 {
1912 float r;
1913 float g;
1914 float b;
1915 float a;
1916
1917 switch (desc.Format)
1918 {
1919 case D3DFMT_R5G6B5:
1920 {
1921 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1922
1923 a = 1.0f;
1924 b = (rgb & 0x001F) * (1.0f / 0x001F);
1925 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1926 r = (rgb & 0xF800) * (1.0f / 0xF800);
1927 }
1928 break;
1929 case D3DFMT_X1R5G5B5:
1930 {
1931 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1932
1933 a = 1.0f;
1934 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1935 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1936 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1937 }
1938 break;
1939 case D3DFMT_A1R5G5B5:
1940 {
1941 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1942
1943 a = (argb & 0x8000) ? 1.0f : 0.0f;
1944 b = (argb & 0x001F) * (1.0f / 0x001F);
1945 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1946 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1947 }
1948 break;
1949 case D3DFMT_A8R8G8B8:
1950 {
1951 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1952
1953 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1954 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1955 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1956 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1957 }
1958 break;
1959 case D3DFMT_X8R8G8B8:
1960 {
1961 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1962
1963 a = 1.0f;
1964 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
1965 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
1966 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
1967 }
1968 break;
1969 case D3DFMT_A2R10G10B10:
1970 {
1971 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1972
1973 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
1974 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
1975 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
1976 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
1977 }
1978 break;
1979 default:
1980 UNIMPLEMENTED(); // FIXME
1981 UNREACHABLE();
1982 }
1983
1984 switch (format)
1985 {
1986 case GL_RGBA:
1987 switch (type)
1988 {
1989 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001990 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
1991 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
1992 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
1993 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001994 break;
1995 default: UNREACHABLE();
1996 }
1997 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001998 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001999 switch (type)
2000 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002001 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002002 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2003 ((unsigned short)(31 * b + 0.5f) << 0) |
2004 ((unsigned short)(63 * g + 0.5f) << 5) |
2005 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002006 break;
2007 default: UNREACHABLE();
2008 }
2009 break;
2010 default: UNREACHABLE();
2011 }
2012 }
2013 }
2014
2015 systemSurface->UnlockRect();
2016
2017 systemSurface->Release();
2018}
2019
2020void Context::clear(GLbitfield mask)
2021{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002022 Framebuffer *framebufferObject = getFramebuffer();
2023
2024 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2025 {
2026 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2027
2028 return;
2029 }
2030
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002031 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002032 IDirect3DDevice9 *device = getDevice();
2033 DWORD flags = 0;
2034
2035 if (mask & GL_COLOR_BUFFER_BIT)
2036 {
2037 mask &= ~GL_COLOR_BUFFER_BIT;
2038 flags |= D3DCLEAR_TARGET;
2039 }
2040
2041 if (mask & GL_DEPTH_BUFFER_BIT)
2042 {
2043 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002044 if (mState.depthMask)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002045 {
2046 flags |= D3DCLEAR_ZBUFFER;
2047 }
2048 }
2049
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002050 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
2051
2052 GLuint stencilUnmasked = 0x0;
2053
2054 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
2055 {
2056 D3DSURFACE_DESC desc;
2057 depthStencil->GetDesc(&desc);
2058
2059 mask &= ~GL_STENCIL_BUFFER_BIT;
2060 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2061 stencilUnmasked = (0x1 << stencilSize) - 1;
2062
2063 if (stencilUnmasked != 0x0)
2064 {
2065 flags |= D3DCLEAR_STENCIL;
2066 }
2067 }
2068
2069 if (mask != 0)
2070 {
2071 return error(GL_INVALID_VALUE);
2072 }
2073
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002074 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2075 {
2076 return;
2077 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002078
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002079 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2080 unorm<8>(mState.colorClearValue.red),
2081 unorm<8>(mState.colorClearValue.green),
2082 unorm<8>(mState.colorClearValue.blue));
2083 float depth = clamp01(mState.depthClearValue);
2084 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002085
2086 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2087
2088 D3DSURFACE_DESC desc;
2089 renderTarget->GetDesc(&desc);
2090
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002091 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002092
2093 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002094 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002095 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002096 !(mState.colorMaskRed && mState.colorMaskGreen &&
2097 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002098
2099 if (needMaskedColorClear || needMaskedStencilClear)
2100 {
2101 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2102 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2103 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2104 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2105 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2106 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2107 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2108 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2109
2110 if (flags & D3DCLEAR_TARGET)
2111 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002112 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2113 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2114 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2115 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002116 }
2117 else
2118 {
2119 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2120 }
2121
2122 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2123 {
2124 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2125 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2126 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2127 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002128 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002129 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002130 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2131 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
2132 }
2133 else
2134 {
2135 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2136 }
2137
2138 device->SetPixelShader(NULL);
2139 device->SetVertexShader(NULL);
2140 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2141
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002142 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002143 {
2144 float x, y, z, w;
2145 D3DCOLOR diffuse;
2146 };
2147
2148 Vertex quad[4];
2149 quad[0].x = 0.0f;
2150 quad[0].y = (float)desc.Height;
2151 quad[0].z = 0.0f;
2152 quad[0].w = 1.0f;
2153 quad[0].diffuse = color;
2154
2155 quad[1].x = (float)desc.Width;
2156 quad[1].y = (float)desc.Height;
2157 quad[1].z = 0.0f;
2158 quad[1].w = 1.0f;
2159 quad[1].diffuse = color;
2160
2161 quad[2].x = 0.0f;
2162 quad[2].y = 0.0f;
2163 quad[2].z = 0.0f;
2164 quad[2].w = 1.0f;
2165 quad[2].diffuse = color;
2166
2167 quad[3].x = (float)desc.Width;
2168 quad[3].y = 0.0f;
2169 quad[3].z = 0.0f;
2170 quad[3].w = 1.0f;
2171 quad[3].diffuse = color;
2172
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002173 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002174 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002175
2176 if (flags & D3DCLEAR_ZBUFFER)
2177 {
2178 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2179 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2180 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2181 }
2182 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002183 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002184 {
2185 device->Clear(0, NULL, flags, color, depth, stencil);
2186 }
2187}
2188
2189void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2190{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002191 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002192 {
2193 return error(GL_INVALID_OPERATION);
2194 }
2195
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002196 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002197 IDirect3DDevice9 *device = getDevice();
2198 D3DPRIMITIVETYPE primitiveType;
2199 int primitiveCount;
2200
2201 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2202 return error(GL_INVALID_ENUM);
2203
2204 if (primitiveCount <= 0)
2205 {
2206 return;
2207 }
2208
2209 if (!applyRenderTarget(false))
2210 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002211 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002212 }
2213
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002214 applyState(mode);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002215 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002216 applyShaders();
2217 applyTextures();
2218
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002219 if (!getCurrentProgram()->validateSamplers())
2220 {
2221 return error(GL_INVALID_OPERATION);
2222 }
2223
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002224 if (!cullSkipsDraw(mode))
2225 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002226 display->startScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002227 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002228 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002229}
2230
2231void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2232{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002233 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002234 {
2235 return error(GL_INVALID_OPERATION);
2236 }
2237
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002238 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002239 {
2240 return error(GL_INVALID_OPERATION);
2241 }
2242
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002243 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002244 IDirect3DDevice9 *device = getDevice();
2245 D3DPRIMITIVETYPE primitiveType;
2246 int primitiveCount;
2247
2248 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2249 return error(GL_INVALID_ENUM);
2250
2251 if (primitiveCount <= 0)
2252 {
2253 return;
2254 }
2255
2256 if (!applyRenderTarget(false))
2257 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002258 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002259 }
2260
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002261 applyState(mode);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002262 TranslatedIndexData indexInfo = applyIndexBuffer(indices, count, mode, type);
2263 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002264 applyShaders();
2265 applyTextures();
2266
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002267 if (!getCurrentProgram()->validateSamplers())
2268 {
2269 return error(GL_INVALID_OPERATION);
2270 }
2271
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002272 if (!cullSkipsDraw(mode))
2273 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002274 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002275 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 +00002276 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002277}
2278
2279void Context::finish()
2280{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002281 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002282 IDirect3DDevice9 *device = getDevice();
2283 IDirect3DQuery9 *occlusionQuery = NULL;
2284
2285 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2286
2287 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2288 {
2289 return error(GL_OUT_OF_MEMORY);
2290 }
2291
2292 ASSERT(SUCCEEDED(result));
2293
2294 if (occlusionQuery)
2295 {
2296 occlusionQuery->Issue(D3DISSUE_BEGIN);
2297
2298 // Render something outside the render target
2299 device->SetPixelShader(NULL);
2300 device->SetVertexShader(NULL);
2301 device->SetFVF(D3DFVF_XYZRHW);
2302 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002303 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002304 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002305
2306 occlusionQuery->Issue(D3DISSUE_END);
2307
2308 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2309 {
2310 // Keep polling, but allow other threads to do something useful first
2311 Sleep(0);
2312 }
2313
2314 occlusionQuery->Release();
2315 }
2316}
2317
2318void Context::flush()
2319{
2320 IDirect3DDevice9 *device = getDevice();
2321 IDirect3DQuery9 *eventQuery = NULL;
2322
2323 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2324
2325 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2326 {
2327 return error(GL_OUT_OF_MEMORY);
2328 }
2329
2330 ASSERT(SUCCEEDED(result));
2331
2332 if (eventQuery)
2333 {
2334 eventQuery->Issue(D3DISSUE_END);
2335
2336 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2337 {
2338 // Keep polling, but allow other threads to do something useful first
2339 Sleep(0);
2340 }
2341
2342 eventQuery->Release();
2343 }
2344}
2345
2346void Context::recordInvalidEnum()
2347{
2348 mInvalidEnum = true;
2349}
2350
2351void Context::recordInvalidValue()
2352{
2353 mInvalidValue = true;
2354}
2355
2356void Context::recordInvalidOperation()
2357{
2358 mInvalidOperation = true;
2359}
2360
2361void Context::recordOutOfMemory()
2362{
2363 mOutOfMemory = true;
2364}
2365
2366void Context::recordInvalidFramebufferOperation()
2367{
2368 mInvalidFramebufferOperation = true;
2369}
2370
2371// Get one of the recorded errors and clear its flag, if any.
2372// [OpenGL ES 2.0.24] section 2.5 page 13.
2373GLenum Context::getError()
2374{
2375 if (mInvalidEnum)
2376 {
2377 mInvalidEnum = false;
2378
2379 return GL_INVALID_ENUM;
2380 }
2381
2382 if (mInvalidValue)
2383 {
2384 mInvalidValue = false;
2385
2386 return GL_INVALID_VALUE;
2387 }
2388
2389 if (mInvalidOperation)
2390 {
2391 mInvalidOperation = false;
2392
2393 return GL_INVALID_OPERATION;
2394 }
2395
2396 if (mOutOfMemory)
2397 {
2398 mOutOfMemory = false;
2399
2400 return GL_OUT_OF_MEMORY;
2401 }
2402
2403 if (mInvalidFramebufferOperation)
2404 {
2405 mInvalidFramebufferOperation = false;
2406
2407 return GL_INVALID_FRAMEBUFFER_OPERATION;
2408 }
2409
2410 return GL_NO_ERROR;
2411}
2412
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002413const char *Context::getPixelShaderProfile()
2414{
2415 return mPsProfile;
2416}
2417
2418const char *Context::getVertexShaderProfile()
2419{
2420 return mVsProfile;
2421}
2422
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002423void Context::detachBuffer(GLuint buffer)
2424{
2425 // [OpenGL ES 2.0.24] section 2.9 page 22:
2426 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2427 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2428
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002429 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002430 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002431 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002432 }
2433
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002434 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002435 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002436 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002437 }
2438
2439 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2440 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002441 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002442 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002443 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002444 }
2445 }
2446}
2447
2448void Context::detachTexture(GLuint texture)
2449{
2450 // [OpenGL ES 2.0.24] section 3.8 page 84:
2451 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2452 // rebound to texture object zero
2453
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002454 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002455 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002456 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002457 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002458 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002459 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002460 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002461 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002462 }
2463 }
2464
2465 // [OpenGL ES 2.0.24] section 4.4 page 112:
2466 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2467 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2468 // image was attached in the currently bound framebuffer.
2469
2470 Framebuffer *framebuffer = getFramebuffer();
2471
2472 if (framebuffer)
2473 {
2474 framebuffer->detachTexture(texture);
2475 }
2476}
2477
2478void Context::detachFramebuffer(GLuint framebuffer)
2479{
2480 // [OpenGL ES 2.0.24] section 4.4 page 107:
2481 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2482 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2483
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002484 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002485 {
2486 bindFramebuffer(0);
2487 }
2488}
2489
2490void Context::detachRenderbuffer(GLuint renderbuffer)
2491{
2492 // [OpenGL ES 2.0.24] section 4.4 page 109:
2493 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2494 // had been executed with the target RENDERBUFFER and name of zero.
2495
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002496 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002497 {
2498 bindRenderbuffer(0);
2499 }
2500
2501 // [OpenGL ES 2.0.24] section 4.4 page 111:
2502 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2503 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2504 // point to which this image was attached in the currently bound framebuffer.
2505
2506 Framebuffer *framebuffer = getFramebuffer();
2507
2508 if (framebuffer)
2509 {
2510 framebuffer->detachRenderbuffer(renderbuffer);
2511 }
2512}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002513
2514Texture *Context::getIncompleteTexture(SamplerType type)
2515{
2516 Texture *t = mIncompleteTextures[type];
2517
2518 if (t == NULL)
2519 {
2520 static const GLubyte color[] = { 0, 0, 0, 255 };
2521
2522 switch (type)
2523 {
2524 default:
2525 UNREACHABLE();
2526 // default falls through to SAMPLER_2D
2527
2528 case SAMPLER_2D:
2529 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002530 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002531 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002532 t = incomplete2d;
2533 }
2534 break;
2535
2536 case SAMPLER_CUBE:
2537 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002538 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002539
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002540 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2541 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2542 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2543 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2544 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2545 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002546
2547 t = incompleteCube;
2548 }
2549 break;
2550 }
2551
2552 mIncompleteTextures[type] = t;
2553 }
2554
2555 return t;
2556}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002557
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002558bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002559{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002560 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002561}
2562
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002563bool Context::isTriangleMode(GLenum drawMode)
2564{
2565 switch (drawMode)
2566 {
2567 case GL_TRIANGLES:
2568 case GL_TRIANGLE_FAN:
2569 case GL_TRIANGLE_STRIP:
2570 return true;
2571 case GL_POINTS:
2572 case GL_LINES:
2573 case GL_LINE_LOOP:
2574 case GL_LINE_STRIP:
2575 return false;
2576 default: UNREACHABLE();
2577 }
2578
2579 return false;
2580}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002581
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002582bool Context::hasStencil()
2583{
2584 Framebuffer *framebufferObject = getFramebuffer();
2585
2586 if (framebufferObject)
2587 {
2588 Stencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
2589
2590 if (stencilbufferObject)
2591 {
2592 return stencilbufferObject->getStencilSize() > 0;
2593 }
2594 }
2595
2596 return false;
2597}
2598
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002599void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2600{
2601 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2602
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002603 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2604 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2605 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2606 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002607
2608 mVertexDataManager->dirtyCurrentValues();
2609}
2610
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002611void Context::initExtensionString()
2612{
2613 if (mBufferBackEnd->supportIntIndices())
2614 {
2615 mExtensionString += "GL_OES_element_index_uint ";
2616 }
2617
2618 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2619 if (end != std::string::npos)
2620 {
2621 mExtensionString.resize(end+1);
2622 }
2623}
2624
2625const char *Context::getExtensionString() const
2626{
2627 return mExtensionString.c_str();
2628}
2629
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002630}
2631
2632extern "C"
2633{
2634gl::Context *glCreateContext(const egl::Config *config)
2635{
2636 return new gl::Context(config);
2637}
2638
2639void glDestroyContext(gl::Context *context)
2640{
2641 delete context;
2642
2643 if (context == gl::getContext())
2644 {
2645 gl::makeCurrent(NULL, NULL, NULL);
2646 }
2647}
2648
2649void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2650{
2651 gl::makeCurrent(context, display, surface);
2652}
2653
2654gl::Context *glGetCurrentContext()
2655{
2656 return gl::getContext();
2657}
2658}