blob: 1bad7b653d62558ff25c120f25dbc52f546b81b5 [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.com092bd482010-05-12 03:39:36 +000040
daniel@transgaming.com428d1582010-05-04 03:35:25 +000041 mState.depthClearValue = 1.0f;
42 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043
daniel@transgaming.com428d1582010-05-04 03:35:25 +000044 mState.cullFace = false;
45 mState.cullMode = GL_BACK;
46 mState.frontFace = GL_CCW;
47 mState.depthTest = false;
48 mState.depthFunc = GL_LESS;
49 mState.blend = false;
50 mState.sourceBlendRGB = GL_ONE;
51 mState.sourceBlendAlpha = GL_ONE;
52 mState.destBlendRGB = GL_ZERO;
53 mState.destBlendAlpha = GL_ZERO;
54 mState.blendEquationRGB = GL_FUNC_ADD;
55 mState.blendEquationAlpha = GL_FUNC_ADD;
56 mState.blendColor.red = 0;
57 mState.blendColor.green = 0;
58 mState.blendColor.blue = 0;
59 mState.blendColor.alpha = 0;
60 mState.stencilTest = false;
61 mState.stencilFunc = GL_ALWAYS;
62 mState.stencilRef = 0;
63 mState.stencilMask = -1;
64 mState.stencilWritemask = -1;
65 mState.stencilBackFunc = GL_ALWAYS;
66 mState.stencilBackRef = 0;
67 mState.stencilBackMask = - 1;
68 mState.stencilBackWritemask = -1;
69 mState.stencilFail = GL_KEEP;
70 mState.stencilPassDepthFail = GL_KEEP;
71 mState.stencilPassDepthPass = GL_KEEP;
72 mState.stencilBackFail = GL_KEEP;
73 mState.stencilBackPassDepthFail = GL_KEEP;
74 mState.stencilBackPassDepthPass = GL_KEEP;
75 mState.polygonOffsetFill = false;
76 mState.polygonOffsetFactor = 0.0f;
77 mState.polygonOffsetUnits = 0.0f;
78 mState.sampleAlphaToCoverage = false;
79 mState.sampleCoverage = false;
80 mState.sampleCoverageValue = 1.0f;
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +000081 mState.sampleCoverageInvert = false;
daniel@transgaming.com428d1582010-05-04 03:35:25 +000082 mState.scissorTest = false;
83 mState.dither = true;
84 mState.generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085
daniel@transgaming.com428d1582010-05-04 03:35:25 +000086 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000087
daniel@transgaming.com428d1582010-05-04 03:35:25 +000088 mState.viewportX = 0;
89 mState.viewportY = 0;
90 mState.viewportWidth = config->mDisplayMode.Width;
91 mState.viewportHeight = config->mDisplayMode.Height;
92 mState.zNear = 0.0f;
93 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000094
daniel@transgaming.com428d1582010-05-04 03:35:25 +000095 mState.scissorX = 0;
96 mState.scissorY = 0;
97 mState.scissorWidth = config->mDisplayMode.Width;
98 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000100 mState.colorMaskRed = true;
101 mState.colorMaskGreen = true;
102 mState.colorMaskBlue = true;
103 mState.colorMaskAlpha = true;
104 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
106 // [OpenGL ES 2.0.24] section 3.7 page 83:
107 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
108 // and cube map texture state vectors respectively associated with them.
109 // In order that access to these initial textures not be lost, they are treated as texture
110 // objects all of whose names are 0.
111
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000112 mTexture2DZero = new Texture2D(this);
113 mTextureCubeMapZero = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114
115 mColorbufferZero = NULL;
116 mDepthbufferZero = NULL;
117 mStencilbufferZero = NULL;
118
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000119 mState.activeSampler = 0;
120 mState.arrayBuffer = 0;
121 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122 bindTextureCubeMap(0);
123 bindTexture2D(0);
124 bindFramebuffer(0);
125 bindRenderbuffer(0);
126
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000127 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000129 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
130 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000131 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000132 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133 }
134
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000135 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
136 {
137 mIncompleteTextures[type] = NULL;
138 }
139
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000140 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000142 mState.packAlignment = 4;
143 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000144
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000145 mBufferBackEnd = NULL;
146 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000147 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000148 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000149
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150 mInvalidEnum = false;
151 mInvalidValue = false;
152 mInvalidOperation = false;
153 mOutOfMemory = false;
154 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000155
156 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000157
158 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159}
160
161Context::~Context()
162{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000163 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000165 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
166 {
167 delete mIncompleteTextures[type];
168 }
169
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170 delete mTexture2DZero;
171 delete mTextureCubeMapZero;
172
173 delete mColorbufferZero;
174 delete mDepthbufferZero;
175 delete mStencilbufferZero;
176
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000177 delete mBufferBackEnd;
178 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000179 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000180 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000181
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182 while (!mBufferMap.empty())
183 {
184 deleteBuffer(mBufferMap.begin()->first);
185 }
186
187 while (!mProgramMap.empty())
188 {
189 deleteProgram(mProgramMap.begin()->first);
190 }
191
192 while (!mShaderMap.empty())
193 {
194 deleteShader(mShaderMap.begin()->first);
195 }
196
197 while (!mFramebufferMap.empty())
198 {
199 deleteFramebuffer(mFramebufferMap.begin()->first);
200 }
201
202 while (!mRenderbufferMap.empty())
203 {
204 deleteRenderbuffer(mRenderbufferMap.begin()->first);
205 }
206
207 while (!mTextureMap.empty())
208 {
209 deleteTexture(mTextureMap.begin()->first);
210 }
211}
212
213void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
214{
215 IDirect3DDevice9 *device = display->getDevice();
216
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000217 if (!mHasBeenCurrent)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000218 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000219 device->GetDeviceCaps(&mDeviceCaps);
220
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000221 mBufferBackEnd = new Dx9BackEnd(device);
222 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000223 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000224 mBlit = new Blit(this);
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000225
226 initExtensionString();
227
228 mState.viewportX = 0;
229 mState.viewportY = 0;
230 mState.viewportWidth = surface->getWidth();
231 mState.viewportHeight = surface->getHeight();
232
233 mState.scissorX = 0;
234 mState.scissorY = 0;
235 mState.scissorWidth = surface->getWidth();
236 mState.scissorHeight = surface->getHeight();
237
238 mHasBeenCurrent = true;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000239 }
240
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
242 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000243 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244
245 Framebuffer *framebufferZero = new Framebuffer();
246 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000247 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
248 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
250 setFramebufferZero(framebufferZero);
251 setColorbufferZero(colorbufferZero);
252 setDepthbufferZero(depthbufferZero);
253 setStencilbufferZero(stencilbufferZero);
254
255 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
256 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
257 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
258
259 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.com092bd482010-05-12 03:39:36 +0000279
280 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281}
282
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000283// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000284void Context::markAllStateDirty()
285{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000286 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000287 mAppliedDepthbufferSerial = 0;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000288 mAppliedProgram = 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000289
290 mClearStateDirty = true;
291 mCullStateDirty = true;
292 mDepthStateDirty = true;
293 mMaskStateDirty = true;
294 mBlendStateDirty = true;
295 mStencilStateDirty = true;
296 mPolygonOffsetStateDirty = true;
297 mScissorStateDirty = true;
298 mSampleStateDirty = true;
299 mDitherStateDirty = true;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000300}
301
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302void Context::setClearColor(float red, float green, float blue, float alpha)
303{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000304 mState.colorClearValue.red = red;
305 mState.colorClearValue.green = green;
306 mState.colorClearValue.blue = blue;
307 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308}
309
310void Context::setClearDepth(float depth)
311{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000312 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313}
314
315void Context::setClearStencil(int stencil)
316{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000317 mState.stencilClearValue = stencil;
318}
319
320void Context::setCullFace(bool enabled)
321{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000322 if (mState.cullFace != enabled)
323 {
324 mState.cullFace = enabled;
325 mCullStateDirty = true;
326 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000327}
328
329bool Context::isCullFaceEnabled() const
330{
331 return mState.cullFace;
332}
333
334void Context::setCullMode(GLenum mode)
335{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000336 if (mState.cullMode != mode)
337 {
338 mState.cullMode = mode;
339 mCullStateDirty = true;
340 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000341}
342
343void Context::setFrontFace(GLenum front)
344{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000345 if (mState.frontFace != front)
346 {
347 mState.frontFace = front;
348 mFrontFaceDirty = true;
349 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000350}
351
352void Context::setDepthTest(bool enabled)
353{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000354 if (mState.depthTest != enabled)
355 {
356 mState.depthTest = enabled;
357 mDepthStateDirty = true;
358 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000359}
360
361bool Context::isDepthTestEnabled() const
362{
363 return mState.depthTest;
364}
365
366void Context::setDepthFunc(GLenum depthFunc)
367{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000368 if (mState.depthFunc != depthFunc)
369 {
370 mState.depthFunc = depthFunc;
371 mDepthStateDirty = true;
372 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000373}
374
375void Context::setDepthRange(float zNear, float zFar)
376{
377 mState.zNear = zNear;
378 mState.zFar = zFar;
379}
380
381void Context::setBlend(bool enabled)
382{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000383 if (mState.blend != enabled)
384 {
385 mState.blend = enabled;
386 mBlendStateDirty = true;
387 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000388}
389
390bool Context::isBlendEnabled() const
391{
392 return mState.blend;
393}
394
395void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
396{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000397 if (mState.sourceBlendRGB != sourceRGB ||
398 mState.sourceBlendAlpha != sourceAlpha ||
399 mState.destBlendRGB != destRGB ||
400 mState.destBlendAlpha != destAlpha)
401 {
402 mState.sourceBlendRGB = sourceRGB;
403 mState.destBlendRGB = destRGB;
404 mState.sourceBlendAlpha = sourceAlpha;
405 mState.destBlendAlpha = destAlpha;
406 mBlendStateDirty = true;
407 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000408}
409
410void Context::setBlendColor(float red, float green, float blue, float alpha)
411{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000412 if (mState.blendColor.red != red ||
413 mState.blendColor.green != green ||
414 mState.blendColor.blue != blue ||
415 mState.blendColor.alpha != alpha)
416 {
417 mState.blendColor.red = red;
418 mState.blendColor.green = green;
419 mState.blendColor.blue = blue;
420 mState.blendColor.alpha = alpha;
421 mBlendStateDirty = true;
422 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000423}
424
425void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
426{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000427 if (mState.blendEquationRGB != rgbEquation ||
428 mState.blendEquationAlpha != alphaEquation)
429 {
430 mState.blendEquationRGB = rgbEquation;
431 mState.blendEquationAlpha = alphaEquation;
432 mBlendStateDirty = true;
433 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000434}
435
436void Context::setStencilTest(bool enabled)
437{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000438 if (mState.stencilTest != enabled)
439 {
440 mState.stencilTest = enabled;
441 mStencilStateDirty = true;
442 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000443}
444
445bool Context::isStencilTestEnabled() const
446{
447 return mState.stencilTest;
448}
449
450void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
451{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000452 if (mState.stencilFunc != stencilFunc ||
453 mState.stencilRef != stencilRef ||
454 mState.stencilMask != stencilMask)
455 {
456 mState.stencilFunc = stencilFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000457 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000458 mState.stencilMask = stencilMask;
459 mStencilStateDirty = true;
460 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000461}
462
463void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
464{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000465 if (mState.stencilBackFunc != stencilBackFunc ||
466 mState.stencilBackRef != stencilBackRef ||
467 mState.stencilBackMask != stencilBackMask)
468 {
469 mState.stencilBackFunc = stencilBackFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000470 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000471 mState.stencilBackMask = stencilBackMask;
472 mStencilStateDirty = true;
473 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000474}
475
476void Context::setStencilWritemask(GLuint stencilWritemask)
477{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000478 if (mState.stencilWritemask != stencilWritemask)
479 {
480 mState.stencilWritemask = stencilWritemask;
481 mStencilStateDirty = true;
482 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000483}
484
485void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
486{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000487 if (mState.stencilBackWritemask != stencilBackWritemask)
488 {
489 mState.stencilBackWritemask = stencilBackWritemask;
490 mStencilStateDirty = true;
491 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000492}
493
494void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
495{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000496 if (mState.stencilFail != stencilFail ||
497 mState.stencilPassDepthFail != stencilPassDepthFail ||
498 mState.stencilPassDepthPass != stencilPassDepthPass)
499 {
500 mState.stencilFail = stencilFail;
501 mState.stencilPassDepthFail = stencilPassDepthFail;
502 mState.stencilPassDepthPass = stencilPassDepthPass;
503 mStencilStateDirty = true;
504 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000505}
506
507void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
508{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000509 if (mState.stencilBackFail != stencilBackFail ||
510 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
511 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
512 {
513 mState.stencilBackFail = stencilBackFail;
514 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
515 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
516 mStencilStateDirty = true;
517 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000518}
519
520void Context::setPolygonOffsetFill(bool enabled)
521{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000522 if (mState.polygonOffsetFill != enabled)
523 {
524 mState.polygonOffsetFill = enabled;
525 mPolygonOffsetStateDirty = true;
526 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000527}
528
529bool Context::isPolygonOffsetFillEnabled() const
530{
531 return mState.polygonOffsetFill;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000532
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000533}
534
535void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
536{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000537 if (mState.polygonOffsetFactor != factor ||
538 mState.polygonOffsetUnits != units)
539 {
540 mState.polygonOffsetFactor = factor;
541 mState.polygonOffsetUnits = units;
542 mPolygonOffsetStateDirty = true;
543 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000544}
545
546void Context::setSampleAlphaToCoverage(bool enabled)
547{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000548 if (mState.sampleAlphaToCoverage != enabled)
549 {
550 mState.sampleAlphaToCoverage = enabled;
551 mSampleStateDirty = true;
552 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000553}
554
555bool Context::isSampleAlphaToCoverageEnabled() const
556{
557 return mState.sampleAlphaToCoverage;
558}
559
560void Context::setSampleCoverage(bool enabled)
561{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000562 if (mState.sampleCoverage != enabled)
563 {
564 mState.sampleCoverage = enabled;
565 mSampleStateDirty = true;
566 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000567}
568
569bool Context::isSampleCoverageEnabled() const
570{
571 return mState.sampleCoverage;
572}
573
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +0000574void Context::setSampleCoverageParams(GLclampf value, bool invert)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000575{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000576 if (mState.sampleCoverageValue != value ||
577 mState.sampleCoverageInvert != invert)
578 {
579 mState.sampleCoverageValue = value;
580 mState.sampleCoverageInvert = invert;
581 mSampleStateDirty = true;
582 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000583}
584
585void Context::setScissorTest(bool enabled)
586{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000587 if (mState.scissorTest != enabled)
588 {
589 mState.scissorTest = enabled;
590 mScissorStateDirty = true;
591 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000592}
593
594bool Context::isScissorTestEnabled() const
595{
596 return mState.scissorTest;
597}
598
599void Context::setDither(bool enabled)
600{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000601 if (mState.dither != enabled)
602 {
603 mState.dither = enabled;
604 mDitherStateDirty = true;
605 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000606}
607
608bool Context::isDitherEnabled() const
609{
610 return mState.dither;
611}
612
613void Context::setLineWidth(GLfloat width)
614{
615 mState.lineWidth = width;
616}
617
618void Context::setGenerateMipmapHint(GLenum hint)
619{
620 mState.generateMipmapHint = hint;
621}
622
623void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
624{
625 mState.viewportX = x;
626 mState.viewportY = y;
627 mState.viewportWidth = width;
628 mState.viewportHeight = height;
629}
630
631void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
632{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000633 if (mState.scissorX != x || mState.scissorY != y ||
634 mState.scissorWidth != width || mState.scissorHeight != height)
635 {
636 mState.scissorX = x;
637 mState.scissorY = y;
638 mState.scissorWidth = width;
639 mState.scissorHeight = height;
640 mScissorStateDirty = true;
641 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000642}
643
644void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
645{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000646 if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
647 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
648 {
649 mState.colorMaskRed = red;
650 mState.colorMaskGreen = green;
651 mState.colorMaskBlue = blue;
652 mState.colorMaskAlpha = alpha;
653 mMaskStateDirty = true;
654 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000655}
656
657void Context::setDepthMask(bool mask)
658{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000659 if (mState.depthMask != mask)
660 {
661 mState.depthMask = mask;
662 mMaskStateDirty = true;
663 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000664}
665
666void Context::setActiveSampler(int active)
667{
668 mState.activeSampler = active;
669}
670
671GLuint Context::getFramebufferHandle() const
672{
673 return mState.framebuffer;
674}
675
676GLuint Context::getRenderbufferHandle() const
677{
678 return mState.renderbuffer;
679}
680
681GLuint Context::getArrayBufferHandle() const
682{
683 return mState.arrayBuffer;
684}
685
686void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
687{
688 mState.vertexAttribute[attribNum].mEnabled = enabled;
689}
690
691const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
692{
693 return mState.vertexAttribute[attribNum];
694}
695
696void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
697 GLsizei stride, const void *pointer)
698{
699 mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
700 mState.vertexAttribute[attribNum].mSize = size;
701 mState.vertexAttribute[attribNum].mType = type;
702 mState.vertexAttribute[attribNum].mNormalized = normalized;
703 mState.vertexAttribute[attribNum].mStride = stride;
704 mState.vertexAttribute[attribNum].mPointer = pointer;
705}
706
707const void *Context::getVertexAttribPointer(unsigned int attribNum) const
708{
709 return mState.vertexAttribute[attribNum].mPointer;
710}
711
712// returns entire set of attributes as a block
713const AttributeState *Context::getVertexAttribBlock()
714{
715 return mState.vertexAttribute;
716}
717
718void Context::setPackAlignment(GLint alignment)
719{
720 mState.packAlignment = alignment;
721}
722
723GLint Context::getPackAlignment() const
724{
725 return mState.packAlignment;
726}
727
728void Context::setUnpackAlignment(GLint alignment)
729{
730 mState.unpackAlignment = alignment;
731}
732
733GLint Context::getUnpackAlignment() const
734{
735 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000736}
737
738// Returns an unused buffer name
739GLuint Context::createBuffer()
740{
741 unsigned int handle = 1;
742
743 while (mBufferMap.find(handle) != mBufferMap.end())
744 {
745 handle++;
746 }
747
748 mBufferMap[handle] = NULL;
749
750 return handle;
751}
752
753// Returns an unused shader/program name
754GLuint Context::createShader(GLenum type)
755{
756 unsigned int handle = 1;
757
758 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
759 {
760 handle++;
761 }
762
763 if (type == GL_VERTEX_SHADER)
764 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000765 mShaderMap[handle] = new VertexShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000766 }
767 else if (type == GL_FRAGMENT_SHADER)
768 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000769 mShaderMap[handle] = new FragmentShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000770 }
771 else UNREACHABLE();
772
773 return handle;
774}
775
776// Returns an unused program/shader name
777GLuint Context::createProgram()
778{
779 unsigned int handle = 1;
780
781 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
782 {
783 handle++;
784 }
785
786 mProgramMap[handle] = new Program();
787
788 return handle;
789}
790
791// Returns an unused texture name
792GLuint Context::createTexture()
793{
794 unsigned int handle = 1;
795
796 while (mTextureMap.find(handle) != mTextureMap.end())
797 {
798 handle++;
799 }
800
801 mTextureMap[handle] = NULL;
802
803 return handle;
804}
805
806// Returns an unused framebuffer name
807GLuint Context::createFramebuffer()
808{
809 unsigned int handle = 1;
810
811 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
812 {
813 handle++;
814 }
815
816 mFramebufferMap[handle] = NULL;
817
818 return handle;
819}
820
821// Returns an unused renderbuffer name
822GLuint Context::createRenderbuffer()
823{
824 unsigned int handle = 1;
825
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000826 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000827 {
828 handle++;
829 }
830
831 mRenderbufferMap[handle] = NULL;
832
833 return handle;
834}
835
836void Context::deleteBuffer(GLuint buffer)
837{
838 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
839
840 if (bufferObject != mBufferMap.end())
841 {
842 detachBuffer(buffer);
843
844 delete bufferObject->second;
845 mBufferMap.erase(bufferObject);
846 }
847}
848
849void Context::deleteShader(GLuint shader)
850{
851 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
852
853 if (shaderObject != mShaderMap.end())
854 {
855 if (!shaderObject->second->isAttached())
856 {
857 delete shaderObject->second;
858 mShaderMap.erase(shaderObject);
859 }
860 else
861 {
862 shaderObject->second->flagForDeletion();
863 }
864 }
865}
866
867void Context::deleteProgram(GLuint program)
868{
869 ProgramMap::iterator programObject = mProgramMap.find(program);
870
871 if (programObject != mProgramMap.end())
872 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000873 if (program != mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000874 {
875 delete programObject->second;
876 mProgramMap.erase(programObject);
877 }
878 else
879 {
880 programObject->second->flagForDeletion();
881 }
882 }
883}
884
885void Context::deleteTexture(GLuint texture)
886{
887 TextureMap::iterator textureObject = mTextureMap.find(texture);
888
889 if (textureObject != mTextureMap.end())
890 {
891 detachTexture(texture);
892
893 if (texture != 0)
894 {
895 delete textureObject->second;
896 }
897
898 mTextureMap.erase(textureObject);
899 }
900}
901
902void Context::deleteFramebuffer(GLuint framebuffer)
903{
904 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
905
906 if (framebufferObject != mFramebufferMap.end())
907 {
908 detachFramebuffer(framebuffer);
909
910 delete framebufferObject->second;
911 mFramebufferMap.erase(framebufferObject);
912 }
913}
914
915void Context::deleteRenderbuffer(GLuint renderbuffer)
916{
917 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
918
919 if (renderbufferObject != mRenderbufferMap.end())
920 {
921 detachRenderbuffer(renderbuffer);
922
923 delete renderbufferObject->second;
924 mRenderbufferMap.erase(renderbufferObject);
925 }
926}
927
928void Context::bindArrayBuffer(unsigned int buffer)
929{
930 if (buffer != 0 && !getBuffer(buffer))
931 {
daniel@transgaming.comdefa1c32010-05-18 18:51:45 +0000932 mBufferMap[buffer] = new Buffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000933 }
934
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000935 mState.arrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000936}
937
938void Context::bindElementArrayBuffer(unsigned int buffer)
939{
940 if (buffer != 0 && !getBuffer(buffer))
941 {
daniel@transgaming.comdefa1c32010-05-18 18:51:45 +0000942 mBufferMap[buffer] = new Buffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000943 }
944
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000945 mState.elementArrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000946}
947
948void Context::bindTexture2D(GLuint texture)
949{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000950 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000951 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000952 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000953 }
954
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000955 mState.texture2D = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000956
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000957 mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000958}
959
960void Context::bindTextureCubeMap(GLuint texture)
961{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000962 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000963 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000964 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000965 }
966
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000967 mState.textureCubeMap = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000969 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000970}
971
972void Context::bindFramebuffer(GLuint framebuffer)
973{
974 if (!getFramebuffer(framebuffer))
975 {
976 mFramebufferMap[framebuffer] = new Framebuffer();
977 }
978
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000979 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000980}
981
982void Context::bindRenderbuffer(GLuint renderbuffer)
983{
984 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
985 {
986 mRenderbufferMap[renderbuffer] = new Renderbuffer();
987 }
988
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000989 mState.renderbuffer = renderbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990}
991
992void Context::useProgram(GLuint program)
993{
994 Program *programObject = getCurrentProgram();
995
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000996 GLuint priorProgram = mState.currentProgram;
997 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000998
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000999 if (programObject && programObject->isFlaggedForDeletion())
1000 {
daniel@transgaming.com71cd8682010-04-29 03:35:25 +00001001 deleteProgram(priorProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001002 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001003}
1004
1005void Context::setFramebufferZero(Framebuffer *buffer)
1006{
1007 delete mFramebufferMap[0];
1008 mFramebufferMap[0] = buffer;
1009}
1010
1011void Context::setColorbufferZero(Colorbuffer *buffer)
1012{
1013 delete mColorbufferZero;
1014 mColorbufferZero = buffer;
1015}
1016
1017void Context::setDepthbufferZero(Depthbuffer *buffer)
1018{
1019 delete mDepthbufferZero;
1020 mDepthbufferZero = buffer;
1021}
1022
1023void Context::setStencilbufferZero(Stencilbuffer *buffer)
1024{
1025 delete mStencilbufferZero;
1026 mStencilbufferZero = buffer;
1027}
1028
1029void Context::setRenderbuffer(Renderbuffer *buffer)
1030{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001031 delete mRenderbufferMap[mState.renderbuffer];
1032 mRenderbufferMap[mState.renderbuffer] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001033}
1034
1035Buffer *Context::getBuffer(unsigned int handle)
1036{
1037 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001038
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001039 if (buffer == mBufferMap.end())
1040 {
1041 return NULL;
1042 }
1043 else
1044 {
1045 return buffer->second;
1046 }
1047}
1048
1049Shader *Context::getShader(unsigned int handle)
1050{
1051 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001052
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001053 if (shader == mShaderMap.end())
1054 {
1055 return NULL;
1056 }
1057 else
1058 {
1059 return shader->second;
1060 }
1061}
1062
1063Program *Context::getProgram(unsigned int handle)
1064{
1065 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001066
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001067 if (program == mProgramMap.end())
1068 {
1069 return NULL;
1070 }
1071 else
1072 {
1073 return program->second;
1074 }
1075}
1076
1077Texture *Context::getTexture(unsigned int handle)
1078{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001079 if (handle == 0) return NULL;
1080
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001081 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001082
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001083 if (texture == mTextureMap.end())
1084 {
1085 return NULL;
1086 }
1087 else
1088 {
1089 return texture->second;
1090 }
1091}
1092
1093Framebuffer *Context::getFramebuffer(unsigned int handle)
1094{
1095 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001096
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001097 if (framebuffer == mFramebufferMap.end())
1098 {
1099 return NULL;
1100 }
1101 else
1102 {
1103 return framebuffer->second;
1104 }
1105}
1106
1107Renderbuffer *Context::getRenderbuffer(unsigned int handle)
1108{
1109 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001110
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001111 if (renderbuffer == mRenderbufferMap.end())
1112 {
1113 return NULL;
1114 }
1115 else
1116 {
1117 return renderbuffer->second;
1118 }
1119}
1120
1121Colorbuffer *Context::getColorbuffer(GLuint handle)
1122{
1123 if (handle != 0)
1124 {
1125 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1126
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001127 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001128 {
1129 return static_cast<Colorbuffer*>(renderbuffer);
1130 }
1131 }
1132 else // Special case: 0 refers to different initial render targets based on the attachment type
1133 {
1134 return mColorbufferZero;
1135 }
1136
1137 return NULL;
1138}
1139
1140Depthbuffer *Context::getDepthbuffer(GLuint handle)
1141{
1142 if (handle != 0)
1143 {
1144 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1145
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001146 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001147 {
1148 return static_cast<Depthbuffer*>(renderbuffer);
1149 }
1150 }
1151 else // Special case: 0 refers to different initial render targets based on the attachment type
1152 {
1153 return mDepthbufferZero;
1154 }
1155
1156 return NULL;
1157}
1158
1159Stencilbuffer *Context::getStencilbuffer(GLuint handle)
1160{
1161 if (handle != 0)
1162 {
1163 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1164
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001165 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001166 {
1167 return static_cast<Stencilbuffer*>(renderbuffer);
1168 }
1169 }
1170 else
1171 {
1172 return mStencilbufferZero;
1173 }
1174
1175 return NULL;
1176}
1177
1178Buffer *Context::getArrayBuffer()
1179{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001180 return getBuffer(mState.arrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001181}
1182
1183Buffer *Context::getElementArrayBuffer()
1184{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001185 return getBuffer(mState.elementArrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001186}
1187
1188Program *Context::getCurrentProgram()
1189{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001190 return getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001191}
1192
1193Texture2D *Context::getTexture2D()
1194{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001195 if (mState.texture2D == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001196 {
1197 return mTexture2DZero;
1198 }
1199
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001200 return (Texture2D*)getTexture(mState.texture2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001201}
1202
1203TextureCubeMap *Context::getTextureCubeMap()
1204{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001205 if (mState.textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001206 {
1207 return mTextureCubeMapZero;
1208 }
1209
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001210 return (TextureCubeMap*)getTexture(mState.textureCubeMap);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001211}
1212
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001213Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001214{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001215 GLuint texid = mState.samplerTexture[type][sampler];
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001216
1217 if (texid == 0)
1218 {
1219 switch (type)
1220 {
1221 default: UNREACHABLE();
1222 case SAMPLER_2D: return mTexture2DZero;
1223 case SAMPLER_CUBE: return mTextureCubeMapZero;
1224 }
1225 }
1226
1227 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001228}
1229
1230Framebuffer *Context::getFramebuffer()
1231{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001232 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001233}
1234
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001235bool Context::getBooleanv(GLenum pname, GLboolean *params)
1236{
1237 switch (pname)
1238 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001239 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1240 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1241 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001242 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001243 params[0] = mState.colorMaskRed;
1244 params[1] = mState.colorMaskGreen;
1245 params[2] = mState.colorMaskBlue;
1246 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001247 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001248 case GL_CULL_FACE: *params = mState.cullFace;
1249 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1250 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1251 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1252 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1253 case GL_STENCIL_TEST: *params = mState.stencilTest;
1254 case GL_DEPTH_TEST: *params = mState.depthTest;
1255 case GL_BLEND: *params = mState.blend;
1256 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001257 default:
1258 return false;
1259 }
1260
1261 return true;
1262}
1263
1264bool Context::getFloatv(GLenum pname, GLfloat *params)
1265{
1266 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1267 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1268 // GetIntegerv as its native query function. As it would require conversion in any
1269 // case, this should make no difference to the calling application.
1270 switch (pname)
1271 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001272 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1273 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1274 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1275 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1276 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001277 case GL_ALIASED_LINE_WIDTH_RANGE:
1278 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1279 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1280 break;
1281 case GL_ALIASED_POINT_SIZE_RANGE:
1282 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
1283 params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
1284 break;
1285 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001286 params[0] = mState.zNear;
1287 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001288 break;
1289 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001290 params[0] = mState.colorClearValue.red;
1291 params[1] = mState.colorClearValue.green;
1292 params[2] = mState.colorClearValue.blue;
1293 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001294 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001295 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001296 params[0] = mState.blendColor.red;
1297 params[1] = mState.blendColor.green;
1298 params[2] = mState.blendColor.blue;
1299 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001300 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001301 default:
1302 return false;
1303 }
1304
1305 return true;
1306}
1307
1308bool Context::getIntegerv(GLenum pname, GLint *params)
1309{
1310 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1311 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1312 // GetIntegerv as its native query function. As it would require conversion in any
1313 // case, this should make no difference to the calling application. You may find it in
1314 // Context::getFloatv.
1315 switch (pname)
1316 {
1317 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1318 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1319 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1320 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1321 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1322 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1323 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1324 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001325 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1326 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1327 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1328 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
1329 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer; break;
1330 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer; break;
1331 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
1332 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer; break;
1333 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1334 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1335 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1336 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1337 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
1338 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1339 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1340 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1341 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1342 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1343 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1344 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1345 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1346 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1347 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1348 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1349 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1350 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1351 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1352 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1353 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1354 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1355 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1356 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1357 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1358 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1359 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
1360 case GL_SUBPIXEL_BITS: *params = 4; break;
1361 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1362 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1363 case GL_SAMPLE_BUFFERS: *params = 0; break;
1364 case GL_SAMPLES: *params = 0; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001365 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1366 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1367 case GL_MAX_VIEWPORT_DIMS:
1368 {
1369 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1370 params[0] = maxDimension;
1371 params[1] = maxDimension;
1372 }
1373 break;
1374 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001375 params[0] = mState.viewportX;
1376 params[1] = mState.viewportY;
1377 params[2] = mState.viewportWidth;
1378 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001379 break;
1380 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001381 params[0] = mState.scissorX;
1382 params[1] = mState.scissorY;
1383 params[2] = mState.scissorWidth;
1384 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001385 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001386 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1387 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001388 case GL_RED_BITS:
1389 case GL_GREEN_BITS:
1390 case GL_BLUE_BITS:
1391 case GL_ALPHA_BITS:
1392 {
1393 gl::Framebuffer *framebuffer = getFramebuffer();
1394 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1395
1396 if (colorbuffer)
1397 {
1398 switch (pname)
1399 {
1400 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1401 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1402 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1403 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1404 }
1405 }
1406 else
1407 {
1408 *params = 0;
1409 }
1410 }
1411 break;
1412 case GL_DEPTH_BITS:
1413 {
1414 gl::Framebuffer *framebuffer = getFramebuffer();
1415 gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
1416
1417 if (depthbuffer)
1418 {
1419 *params = depthbuffer->getDepthSize();
1420 }
1421 else
1422 {
1423 *params = 0;
1424 }
1425 }
1426 break;
1427 case GL_STENCIL_BITS:
1428 {
1429 gl::Framebuffer *framebuffer = getFramebuffer();
1430 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1431
1432 if (stencilbuffer)
1433 {
1434 *params = stencilbuffer->getStencilSize();
1435 }
1436 else
1437 {
1438 *params = 0;
1439 }
1440 }
1441 break;
1442 case GL_TEXTURE_BINDING_2D:
1443 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001444 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001445 {
1446 error(GL_INVALID_OPERATION);
1447 return false;
1448 }
1449
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001450 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001451 }
1452 break;
1453 case GL_TEXTURE_BINDING_CUBE_MAP:
1454 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001455 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001456 {
1457 error(GL_INVALID_OPERATION);
1458 return false;
1459 }
1460
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001461 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001462 }
1463 break;
1464 default:
1465 return false;
1466 }
1467
1468 return true;
1469}
1470
1471bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1472{
1473 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1474 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1475 // to the fact that it is stored internally as a float, and so would require conversion
1476 // if returned from Context::getIntegerv. Since this conversion is already implemented
1477 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1478 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1479 // application.
1480 switch (pname)
1481 {
1482 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1483 case GL_SHADER_BINARY_FORMATS:
1484 {
1485 *type = GL_INT;
1486 *numParams = 0;
1487 }
1488 break;
1489 case GL_MAX_VERTEX_ATTRIBS:
1490 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1491 case GL_MAX_VARYING_VECTORS:
1492 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1493 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1494 case GL_MAX_TEXTURE_IMAGE_UNITS:
1495 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1496 case GL_MAX_RENDERBUFFER_SIZE:
1497 case GL_NUM_SHADER_BINARY_FORMATS:
1498 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1499 case GL_ARRAY_BUFFER_BINDING:
1500 case GL_FRAMEBUFFER_BINDING:
1501 case GL_RENDERBUFFER_BINDING:
1502 case GL_CURRENT_PROGRAM:
1503 case GL_PACK_ALIGNMENT:
1504 case GL_UNPACK_ALIGNMENT:
1505 case GL_GENERATE_MIPMAP_HINT:
1506 case GL_RED_BITS:
1507 case GL_GREEN_BITS:
1508 case GL_BLUE_BITS:
1509 case GL_ALPHA_BITS:
1510 case GL_DEPTH_BITS:
1511 case GL_STENCIL_BITS:
1512 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1513 case GL_CULL_FACE_MODE:
1514 case GL_FRONT_FACE:
1515 case GL_ACTIVE_TEXTURE:
1516 case GL_STENCIL_FUNC:
1517 case GL_STENCIL_VALUE_MASK:
1518 case GL_STENCIL_REF:
1519 case GL_STENCIL_FAIL:
1520 case GL_STENCIL_PASS_DEPTH_FAIL:
1521 case GL_STENCIL_PASS_DEPTH_PASS:
1522 case GL_STENCIL_BACK_FUNC:
1523 case GL_STENCIL_BACK_VALUE_MASK:
1524 case GL_STENCIL_BACK_REF:
1525 case GL_STENCIL_BACK_FAIL:
1526 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1527 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1528 case GL_DEPTH_FUNC:
1529 case GL_BLEND_SRC_RGB:
1530 case GL_BLEND_SRC_ALPHA:
1531 case GL_BLEND_DST_RGB:
1532 case GL_BLEND_DST_ALPHA:
1533 case GL_BLEND_EQUATION_RGB:
1534 case GL_BLEND_EQUATION_ALPHA:
1535 case GL_STENCIL_WRITEMASK:
1536 case GL_STENCIL_BACK_WRITEMASK:
1537 case GL_STENCIL_CLEAR_VALUE:
1538 case GL_SUBPIXEL_BITS:
1539 case GL_MAX_TEXTURE_SIZE:
1540 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1541 case GL_SAMPLE_BUFFERS:
1542 case GL_SAMPLES:
1543 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1544 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1545 case GL_TEXTURE_BINDING_2D:
1546 case GL_TEXTURE_BINDING_CUBE_MAP:
1547 {
1548 *type = GL_INT;
1549 *numParams = 1;
1550 }
1551 break;
1552 case GL_MAX_VIEWPORT_DIMS:
1553 {
1554 *type = GL_INT;
1555 *numParams = 2;
1556 }
1557 break;
1558 case GL_VIEWPORT:
1559 case GL_SCISSOR_BOX:
1560 {
1561 *type = GL_INT;
1562 *numParams = 4;
1563 }
1564 break;
1565 case GL_SHADER_COMPILER:
1566 case GL_SAMPLE_COVERAGE_INVERT:
1567 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001568 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1569 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1570 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1571 case GL_SAMPLE_COVERAGE:
1572 case GL_SCISSOR_TEST:
1573 case GL_STENCIL_TEST:
1574 case GL_DEPTH_TEST:
1575 case GL_BLEND:
1576 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001577 {
1578 *type = GL_BOOL;
1579 *numParams = 1;
1580 }
1581 break;
1582 case GL_COLOR_WRITEMASK:
1583 {
1584 *type = GL_BOOL;
1585 *numParams = 4;
1586 }
1587 break;
1588 case GL_POLYGON_OFFSET_FACTOR:
1589 case GL_POLYGON_OFFSET_UNITS:
1590 case GL_SAMPLE_COVERAGE_VALUE:
1591 case GL_DEPTH_CLEAR_VALUE:
1592 case GL_LINE_WIDTH:
1593 {
1594 *type = GL_FLOAT;
1595 *numParams = 1;
1596 }
1597 break;
1598 case GL_ALIASED_LINE_WIDTH_RANGE:
1599 case GL_ALIASED_POINT_SIZE_RANGE:
1600 case GL_DEPTH_RANGE:
1601 {
1602 *type = GL_FLOAT;
1603 *numParams = 2;
1604 }
1605 break;
1606 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001607 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001608 {
1609 *type = GL_FLOAT;
1610 *numParams = 4;
1611 }
1612 break;
1613 default:
1614 return false;
1615 }
1616
1617 return true;
1618}
1619
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001620// Applies the render target surface, depth stencil surface, viewport rectangle and
1621// scissor rectangle to the Direct3D 9 device
1622bool Context::applyRenderTarget(bool ignoreViewport)
1623{
1624 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001625
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001626 Framebuffer *framebufferObject = getFramebuffer();
1627
1628 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1629 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001630 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1631
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001632 return false;
1633 }
1634
1635 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1636 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1637
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001638 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1639 if (renderTargetSerial != mAppliedRenderTargetSerial)
1640 {
1641 device->SetRenderTarget(0, renderTarget);
1642 mAppliedRenderTargetSerial = renderTargetSerial;
1643 }
1644
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001645 unsigned int depthbufferSerial = framebufferObject->getDepthbufferSerial();
1646 if (depthbufferSerial != mAppliedDepthbufferSerial)
1647 {
1648 device->SetDepthStencilSurface(depthStencil);
1649 mAppliedDepthbufferSerial = depthbufferSerial;
1650 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001651
1652 D3DVIEWPORT9 viewport;
1653 D3DSURFACE_DESC desc;
1654 renderTarget->GetDesc(&desc);
1655
1656 if (ignoreViewport)
1657 {
1658 viewport.X = 0;
1659 viewport.Y = 0;
1660 viewport.Width = desc.Width;
1661 viewport.Height = desc.Height;
1662 viewport.MinZ = 0.0f;
1663 viewport.MaxZ = 1.0f;
1664 }
1665 else
1666 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001667 viewport.X = std::max(mState.viewportX, 0);
1668 viewport.Y = std::max(mState.viewportY, 0);
1669 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1670 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1671 viewport.MinZ = clamp01(mState.zNear);
1672 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001673 }
1674
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001675 if (viewport.Width <= 0 || viewport.Height <= 0)
1676 {
1677 return false; // Nothing to render
1678 }
1679
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001680 device->SetViewport(&viewport);
1681
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001682 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001683 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001684 if (mState.scissorTest)
1685 {
1686 RECT rect = {mState.scissorX,
1687 mState.scissorY,
1688 mState.scissorX + mState.scissorWidth,
1689 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001690
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001691 device->SetScissorRect(&rect);
1692 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1693 }
1694 else
1695 {
1696 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1697 }
1698
1699 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001700 }
1701
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001702 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001703 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001704 Program *programObject = getCurrentProgram();
1705
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001706 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001707 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001708 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001709
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001710 GLint window = programObject->getDxWindowLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001711 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1712 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1713 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001714 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1715
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001716 GLint depth = programObject->getDxDepthLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001717 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001718 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1719
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001720 GLint near = programObject->getDepthRangeNearLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001721 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001722
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001723 GLint far = programObject->getDepthRangeFarLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001724 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001725
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001726 GLint diff = programObject->getDepthRangeDiffLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001727 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001728 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001729 }
1730
1731 return true;
1732}
1733
1734// 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 +00001735void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001736{
1737 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001738 Program *programObject = getCurrentProgram();
1739
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001740 GLint frontCCW = programObject->getDxFrontCCWLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001741 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001742 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001743
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001744 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001745 GLint alwaysFront = !isTriangleMode(drawMode);
1746 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1747
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001748 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001749 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001750 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001751 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001752 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001753 }
1754 else
1755 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001756 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001757 }
1758
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001759 mCullStateDirty = false;
1760 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001761
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001762 if (mDepthStateDirty)
1763 {
1764 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001765 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001766 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1767 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001768 }
1769 else
1770 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001771 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001772 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001773
1774 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001775 }
1776
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001777 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001778 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001779 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001780 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001781 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1782
1783 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1784 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1785 {
1786 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1787 }
1788 else
1789 {
1790 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1791 unorm<8>(mState.blendColor.alpha),
1792 unorm<8>(mState.blendColor.alpha),
1793 unorm<8>(mState.blendColor.alpha)));
1794 }
1795
1796 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1797 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1798 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1799
1800 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1801 mState.destBlendRGB != mState.destBlendAlpha ||
1802 mState.blendEquationRGB != mState.blendEquationAlpha)
1803 {
1804 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1805
1806 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1807 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1808 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1809
1810 }
1811 else
1812 {
1813 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1814 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001815 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001816 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001817 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001818 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001819 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001820
1821 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001822 }
1823
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001824 if (mStencilStateDirty || mFrontFaceDirty)
1825 {
1826 if (mState.stencilTest && hasStencil())
1827 {
1828 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1829 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1830
1831 // FIXME: Unsupported by D3D9
1832 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1833 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1834 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1835 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1836 mState.stencilRef != mState.stencilBackRef ||
1837 mState.stencilMask != mState.stencilBackMask)
1838 {
1839 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1840 return error(GL_INVALID_OPERATION);
1841 }
1842
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001843 // get the maximum size of the stencil ref
1844 gl::Framebuffer *framebuffer = getFramebuffer();
1845 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1846 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
1847
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001848 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1849 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1850 es2dx::ConvertComparison(mState.stencilFunc));
1851
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001852 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001853 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1854
1855 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1856 es2dx::ConvertStencilOp(mState.stencilFail));
1857 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1858 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1859 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1860 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1861
1862 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1863 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1864 es2dx::ConvertComparison(mState.stencilBackFunc));
1865
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001866 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001867 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1868
1869 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1870 es2dx::ConvertStencilOp(mState.stencilBackFail));
1871 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1872 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1873 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1874 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1875 }
1876 else
1877 {
1878 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1879 }
1880
1881 mStencilStateDirty = false;
1882 }
1883
1884 if (mMaskStateDirty)
1885 {
1886 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1887 mState.colorMaskBlue, mState.colorMaskAlpha));
1888 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1889
1890 mMaskStateDirty = false;
1891 }
1892
1893 if (mPolygonOffsetStateDirty)
1894 {
1895 if (mState.polygonOffsetFill)
1896 {
1897 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1898 if (depthbuffer)
1899 {
1900 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1901 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1902 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1903 }
1904 }
1905 else
1906 {
1907 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1908 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1909 }
1910
1911 mPolygonOffsetStateDirty = false;
1912 }
1913
1914 if (mConfig->mMultiSample != 0 && mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001915 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001916 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001917 {
1918 FIXME("Sample alpha to coverage is unimplemented.");
1919 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001920
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001921 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001922 {
1923 FIXME("Sample coverage is unimplemented.");
1924 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001925
1926 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001927 }
1928
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001929 if (mDitherStateDirty)
1930 {
1931 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1932
1933 mDitherStateDirty = false;
1934 }
1935
1936 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001937}
1938
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001939// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001940void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001941{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001942 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001943 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001944 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001945 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001946 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001947 }
1948 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001949}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001950
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001951GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001952{
1953 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1954
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001955 GLenum err = mVertexDataManager->preRenderValidate(first, count, translated);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001956 if (err != GL_NO_ERROR)
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001957 {
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001958 return err;
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001959 }
1960
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001961 lookupAttributeMapping(translated);
1962
1963 mBufferBackEnd->setupAttributesPreDraw(translated);
1964
1965 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1966 {
1967 if (translated[i].enabled && translated[i].nonArray)
1968 {
1969 err = mIndexDataManager->preRenderValidateUnindexed(mode, count, indexInfo);
1970 if (err != GL_NO_ERROR)
1971 {
1972 return err;
1973 }
1974
1975 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1976
1977 *useIndexing = true;
1978 return GL_NO_ERROR;
1979 }
1980 }
1981
1982 *useIndexing = false;
1983 return GL_NO_ERROR;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001984}
1985
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001986GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001987{
1988 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1989
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001990 GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001991
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001992 if (err == GL_NO_ERROR)
1993 {
1994 lookupAttributeMapping(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001995
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001996 mBufferBackEnd->setupAttributesPreDraw(translated);
1997 }
1998
1999 return err;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002000}
2001
2002// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002003GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002004{
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002005 GLenum err = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices, indexInfo);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002006
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002007 if (err == GL_NO_ERROR)
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002008 {
2009 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
2010 }
2011
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002012 return err;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002013}
2014
2015// Applies the shaders and shader constants to the Direct3D 9 device
2016void Context::applyShaders()
2017{
2018 IDirect3DDevice9 *device = getDevice();
2019 Program *programObject = getCurrentProgram();
2020 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
2021 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
2022
2023 device->SetVertexShader(vertexShader);
2024 device->SetPixelShader(pixelShader);
2025
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002026 if (programObject->getSerial() != mAppliedProgram)
2027 {
2028 programObject->dirtyAllUniforms();
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002029 programObject->dirtyAllSamplers();
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002030 mAppliedProgram = programObject->getSerial();
2031 }
2032
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002033 programObject->applyUniforms();
2034}
2035
2036// Applies the textures and sampler states to the Direct3D 9 device
2037void Context::applyTextures()
2038{
2039 IDirect3DDevice9 *device = getDevice();
2040 Program *programObject = getCurrentProgram();
2041
2042 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
2043 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002044 int textureUnit = programObject->getSamplerMapping(sampler);
2045 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002046 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002047 SamplerType textureType = programObject->getSamplerType(sampler);
2048
2049 Texture *texture = getSamplerTexture(textureUnit, textureType);
2050
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002051 if (programObject->isSamplerDirty(sampler) || texture->isDirty())
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002052 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002053 if (texture->isComplete())
2054 {
2055 GLenum wrapS = texture->getWrapS();
2056 GLenum wrapT = texture->getWrapT();
2057 GLenum minFilter = texture->getMinFilter();
2058 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002059
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002060 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
2061 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002062
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002063 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
2064 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
2065 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
2066 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
2067 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002068
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002069 device->SetTexture(sampler, texture->getTexture());
2070 }
2071 else
2072 {
2073 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
2074 }
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002075 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002076
2077 programObject->setSamplerDirty(sampler, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002078 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002079 else
2080 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002081 if (programObject->isSamplerDirty(sampler))
2082 {
2083 device->SetTexture(sampler, NULL);
2084 programObject->setSamplerDirty(sampler, false);
2085 }
2086 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002087 }
2088}
2089
2090void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
2091{
2092 Framebuffer *framebuffer = getFramebuffer();
2093 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
2094 IDirect3DDevice9 *device = getDevice();
2095
2096 D3DSURFACE_DESC desc;
2097 renderTarget->GetDesc(&desc);
2098
2099 IDirect3DSurface9 *systemSurface;
2100 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
2101
2102 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2103 {
2104 return error(GL_OUT_OF_MEMORY);
2105 }
2106
2107 ASSERT(SUCCEEDED(result));
2108
2109 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
2110 {
2111 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
2112 }
2113
2114 result = device->GetRenderTargetData(renderTarget, systemSurface);
2115
2116 if (result == D3DERR_DRIVERINTERNALERROR)
2117 {
2118 systemSurface->Release();
2119
2120 return error(GL_OUT_OF_MEMORY);
2121 }
2122
2123 if (FAILED(result))
2124 {
2125 UNREACHABLE();
2126 systemSurface->Release();
2127
2128 return; // No sensible error to generate
2129 }
2130
2131 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00002132 RECT rect = {std::max(x, 0),
2133 std::max(y, 0),
2134 std::min(x + width, (int)desc.Width),
2135 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002136
2137 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
2138
2139 if (FAILED(result))
2140 {
2141 UNREACHABLE();
2142 systemSurface->Release();
2143
2144 return; // No sensible error to generate
2145 }
2146
2147 unsigned char *source = (unsigned char*)lock.pBits;
2148 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002149 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002150
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002151 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002152
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002153 for (int j = 0; j < rect.bottom - rect.top; j++)
2154 {
2155 for (int i = 0; i < rect.right - rect.left; i++)
2156 {
2157 float r;
2158 float g;
2159 float b;
2160 float a;
2161
2162 switch (desc.Format)
2163 {
2164 case D3DFMT_R5G6B5:
2165 {
2166 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2167
2168 a = 1.0f;
2169 b = (rgb & 0x001F) * (1.0f / 0x001F);
2170 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2171 r = (rgb & 0xF800) * (1.0f / 0xF800);
2172 }
2173 break;
2174 case D3DFMT_X1R5G5B5:
2175 {
2176 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2177
2178 a = 1.0f;
2179 b = (xrgb & 0x001F) * (1.0f / 0x001F);
2180 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
2181 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
2182 }
2183 break;
2184 case D3DFMT_A1R5G5B5:
2185 {
2186 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2187
2188 a = (argb & 0x8000) ? 1.0f : 0.0f;
2189 b = (argb & 0x001F) * (1.0f / 0x001F);
2190 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2191 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2192 }
2193 break;
2194 case D3DFMT_A8R8G8B8:
2195 {
2196 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2197
2198 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2199 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2200 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2201 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2202 }
2203 break;
2204 case D3DFMT_X8R8G8B8:
2205 {
2206 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2207
2208 a = 1.0f;
2209 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2210 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2211 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2212 }
2213 break;
2214 case D3DFMT_A2R10G10B10:
2215 {
2216 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2217
2218 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2219 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2220 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2221 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2222 }
2223 break;
2224 default:
2225 UNIMPLEMENTED(); // FIXME
2226 UNREACHABLE();
2227 }
2228
2229 switch (format)
2230 {
2231 case GL_RGBA:
2232 switch (type)
2233 {
2234 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002235 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2236 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2237 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2238 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002239 break;
2240 default: UNREACHABLE();
2241 }
2242 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002243 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002244 switch (type)
2245 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002246 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002247 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2248 ((unsigned short)(31 * b + 0.5f) << 0) |
2249 ((unsigned short)(63 * g + 0.5f) << 5) |
2250 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002251 break;
2252 default: UNREACHABLE();
2253 }
2254 break;
2255 default: UNREACHABLE();
2256 }
2257 }
2258 }
2259
2260 systemSurface->UnlockRect();
2261
2262 systemSurface->Release();
2263}
2264
2265void Context::clear(GLbitfield mask)
2266{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002267 Framebuffer *framebufferObject = getFramebuffer();
2268
2269 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2270 {
2271 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2272
2273 return;
2274 }
2275
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002276 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002277 IDirect3DDevice9 *device = getDevice();
2278 DWORD flags = 0;
2279
2280 if (mask & GL_COLOR_BUFFER_BIT)
2281 {
2282 mask &= ~GL_COLOR_BUFFER_BIT;
2283 flags |= D3DCLEAR_TARGET;
2284 }
2285
2286 if (mask & GL_DEPTH_BUFFER_BIT)
2287 {
2288 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002289 if (mState.depthMask)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002290 {
2291 flags |= D3DCLEAR_ZBUFFER;
2292 }
2293 }
2294
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002295 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
2296
2297 GLuint stencilUnmasked = 0x0;
2298
2299 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
2300 {
2301 D3DSURFACE_DESC desc;
2302 depthStencil->GetDesc(&desc);
2303
2304 mask &= ~GL_STENCIL_BUFFER_BIT;
2305 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2306 stencilUnmasked = (0x1 << stencilSize) - 1;
2307
2308 if (stencilUnmasked != 0x0)
2309 {
2310 flags |= D3DCLEAR_STENCIL;
2311 }
2312 }
2313
2314 if (mask != 0)
2315 {
2316 return error(GL_INVALID_VALUE);
2317 }
2318
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002319 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2320 {
2321 return;
2322 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002323
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002324 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2325 unorm<8>(mState.colorClearValue.red),
2326 unorm<8>(mState.colorClearValue.green),
2327 unorm<8>(mState.colorClearValue.blue));
2328 float depth = clamp01(mState.depthClearValue);
2329 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002330
2331 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2332
2333 D3DSURFACE_DESC desc;
2334 renderTarget->GetDesc(&desc);
2335
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002336 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002337
2338 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002339 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002340 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002341 !(mState.colorMaskRed && mState.colorMaskGreen &&
2342 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002343
2344 if (needMaskedColorClear || needMaskedStencilClear)
2345 {
2346 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2347 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2348 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2349 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2350 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2351 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2352 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2353 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2354
2355 if (flags & D3DCLEAR_TARGET)
2356 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002357 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2358 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2359 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2360 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002361 }
2362 else
2363 {
2364 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2365 }
2366
2367 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2368 {
2369 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2370 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2371 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2372 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002373 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002374 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002375 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2376 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
2377 }
2378 else
2379 {
2380 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2381 }
2382
2383 device->SetPixelShader(NULL);
2384 device->SetVertexShader(NULL);
2385 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002386 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002387
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002388 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002389 {
2390 float x, y, z, w;
2391 D3DCOLOR diffuse;
2392 };
2393
2394 Vertex quad[4];
2395 quad[0].x = 0.0f;
2396 quad[0].y = (float)desc.Height;
2397 quad[0].z = 0.0f;
2398 quad[0].w = 1.0f;
2399 quad[0].diffuse = color;
2400
2401 quad[1].x = (float)desc.Width;
2402 quad[1].y = (float)desc.Height;
2403 quad[1].z = 0.0f;
2404 quad[1].w = 1.0f;
2405 quad[1].diffuse = color;
2406
2407 quad[2].x = 0.0f;
2408 quad[2].y = 0.0f;
2409 quad[2].z = 0.0f;
2410 quad[2].w = 1.0f;
2411 quad[2].diffuse = color;
2412
2413 quad[3].x = (float)desc.Width;
2414 quad[3].y = 0.0f;
2415 quad[3].z = 0.0f;
2416 quad[3].w = 1.0f;
2417 quad[3].diffuse = color;
2418
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002419 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002420 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002421
2422 if (flags & D3DCLEAR_ZBUFFER)
2423 {
2424 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2425 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2426 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2427 }
2428 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002429 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002430 {
2431 device->Clear(0, NULL, flags, color, depth, stencil);
2432 }
2433}
2434
2435void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2436{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002437 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002438 {
2439 return error(GL_INVALID_OPERATION);
2440 }
2441
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002442 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002443 IDirect3DDevice9 *device = getDevice();
2444 D3DPRIMITIVETYPE primitiveType;
2445 int primitiveCount;
2446
2447 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2448 return error(GL_INVALID_ENUM);
2449
2450 if (primitiveCount <= 0)
2451 {
2452 return;
2453 }
2454
2455 if (!applyRenderTarget(false))
2456 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002457 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002458 }
2459
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002460 applyState(mode);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002461
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002462 TranslatedIndexData indexInfo;
2463 bool useIndexing;
2464 GLenum err = applyVertexBuffer(mode, first, count, &useIndexing, &indexInfo);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002465 if (err != GL_NO_ERROR)
2466 {
2467 return error(err);
2468 }
2469
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002470 applyShaders();
2471 applyTextures();
2472
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002473 if (!getCurrentProgram()->validateSamplers())
2474 {
2475 return error(GL_INVALID_OPERATION);
2476 }
2477
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002478 if (!cullSkipsDraw(mode))
2479 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002480 display->startScene();
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002481 if (useIndexing)
2482 {
2483 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
2484 }
2485 else
2486 {
2487 device->DrawPrimitive(primitiveType, 0, primitiveCount);
2488 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002489 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002490}
2491
2492void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2493{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002494 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002495 {
2496 return error(GL_INVALID_OPERATION);
2497 }
2498
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002499 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002500 {
2501 return error(GL_INVALID_OPERATION);
2502 }
2503
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002504 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002505 IDirect3DDevice9 *device = getDevice();
2506 D3DPRIMITIVETYPE primitiveType;
2507 int primitiveCount;
2508
2509 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2510 return error(GL_INVALID_ENUM);
2511
2512 if (primitiveCount <= 0)
2513 {
2514 return;
2515 }
2516
2517 if (!applyRenderTarget(false))
2518 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002519 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002520 }
2521
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002522 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002523
2524 TranslatedIndexData indexInfo;
2525 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2526 if (err != GL_NO_ERROR)
2527 {
2528 return error(err);
2529 }
2530
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002531 err = applyVertexBuffer(indexInfo);
2532 if (err != GL_NO_ERROR)
2533 {
2534 return error(err);
2535 }
2536
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002537 applyShaders();
2538 applyTextures();
2539
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002540 if (!getCurrentProgram()->validateSamplers())
2541 {
2542 return error(GL_INVALID_OPERATION);
2543 }
2544
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002545 if (!cullSkipsDraw(mode))
2546 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002547 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002548 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 +00002549 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002550}
2551
2552void Context::finish()
2553{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002554 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002555 IDirect3DDevice9 *device = getDevice();
2556 IDirect3DQuery9 *occlusionQuery = NULL;
2557
2558 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2559
2560 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2561 {
2562 return error(GL_OUT_OF_MEMORY);
2563 }
2564
2565 ASSERT(SUCCEEDED(result));
2566
2567 if (occlusionQuery)
2568 {
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002569 IDirect3DStateBlock9 *savedState = NULL;
2570 device->CreateStateBlock(D3DSBT_ALL, &savedState);
2571
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002572 occlusionQuery->Issue(D3DISSUE_BEGIN);
2573
2574 // Render something outside the render target
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002575 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002576 device->SetPixelShader(NULL);
2577 device->SetVertexShader(NULL);
2578 device->SetFVF(D3DFVF_XYZRHW);
2579 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002580 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002581 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002582
2583 occlusionQuery->Issue(D3DISSUE_END);
2584
2585 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2586 {
2587 // Keep polling, but allow other threads to do something useful first
2588 Sleep(0);
2589 }
2590
2591 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002592
2593 if (savedState)
2594 {
2595 savedState->Apply();
2596 savedState->Release();
2597 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002598 }
2599}
2600
2601void Context::flush()
2602{
2603 IDirect3DDevice9 *device = getDevice();
2604 IDirect3DQuery9 *eventQuery = NULL;
2605
2606 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2607
2608 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2609 {
2610 return error(GL_OUT_OF_MEMORY);
2611 }
2612
2613 ASSERT(SUCCEEDED(result));
2614
2615 if (eventQuery)
2616 {
2617 eventQuery->Issue(D3DISSUE_END);
2618
2619 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2620 {
2621 // Keep polling, but allow other threads to do something useful first
2622 Sleep(0);
2623 }
2624
2625 eventQuery->Release();
2626 }
2627}
2628
2629void Context::recordInvalidEnum()
2630{
2631 mInvalidEnum = true;
2632}
2633
2634void Context::recordInvalidValue()
2635{
2636 mInvalidValue = true;
2637}
2638
2639void Context::recordInvalidOperation()
2640{
2641 mInvalidOperation = true;
2642}
2643
2644void Context::recordOutOfMemory()
2645{
2646 mOutOfMemory = true;
2647}
2648
2649void Context::recordInvalidFramebufferOperation()
2650{
2651 mInvalidFramebufferOperation = true;
2652}
2653
2654// Get one of the recorded errors and clear its flag, if any.
2655// [OpenGL ES 2.0.24] section 2.5 page 13.
2656GLenum Context::getError()
2657{
2658 if (mInvalidEnum)
2659 {
2660 mInvalidEnum = false;
2661
2662 return GL_INVALID_ENUM;
2663 }
2664
2665 if (mInvalidValue)
2666 {
2667 mInvalidValue = false;
2668
2669 return GL_INVALID_VALUE;
2670 }
2671
2672 if (mInvalidOperation)
2673 {
2674 mInvalidOperation = false;
2675
2676 return GL_INVALID_OPERATION;
2677 }
2678
2679 if (mOutOfMemory)
2680 {
2681 mOutOfMemory = false;
2682
2683 return GL_OUT_OF_MEMORY;
2684 }
2685
2686 if (mInvalidFramebufferOperation)
2687 {
2688 mInvalidFramebufferOperation = false;
2689
2690 return GL_INVALID_FRAMEBUFFER_OPERATION;
2691 }
2692
2693 return GL_NO_ERROR;
2694}
2695
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002696const char *Context::getPixelShaderProfile()
2697{
2698 return mPsProfile;
2699}
2700
2701const char *Context::getVertexShaderProfile()
2702{
2703 return mVsProfile;
2704}
2705
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002706void Context::detachBuffer(GLuint buffer)
2707{
2708 // [OpenGL ES 2.0.24] section 2.9 page 22:
2709 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2710 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2711
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002712 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002713 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002714 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002715 }
2716
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002717 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002718 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002719 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002720 }
2721
2722 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2723 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002724 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002725 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002726 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002727 }
2728 }
2729}
2730
2731void Context::detachTexture(GLuint texture)
2732{
2733 // [OpenGL ES 2.0.24] section 3.8 page 84:
2734 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2735 // rebound to texture object zero
2736
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002737 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002738 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002739 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002740 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002741 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002742 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002743 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002744 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002745 }
2746 }
2747
2748 // [OpenGL ES 2.0.24] section 4.4 page 112:
2749 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2750 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2751 // image was attached in the currently bound framebuffer.
2752
2753 Framebuffer *framebuffer = getFramebuffer();
2754
2755 if (framebuffer)
2756 {
2757 framebuffer->detachTexture(texture);
2758 }
2759}
2760
2761void Context::detachFramebuffer(GLuint framebuffer)
2762{
2763 // [OpenGL ES 2.0.24] section 4.4 page 107:
2764 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2765 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2766
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002767 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002768 {
2769 bindFramebuffer(0);
2770 }
2771}
2772
2773void Context::detachRenderbuffer(GLuint renderbuffer)
2774{
2775 // [OpenGL ES 2.0.24] section 4.4 page 109:
2776 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2777 // had been executed with the target RENDERBUFFER and name of zero.
2778
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002779 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002780 {
2781 bindRenderbuffer(0);
2782 }
2783
2784 // [OpenGL ES 2.0.24] section 4.4 page 111:
2785 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2786 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2787 // point to which this image was attached in the currently bound framebuffer.
2788
2789 Framebuffer *framebuffer = getFramebuffer();
2790
2791 if (framebuffer)
2792 {
2793 framebuffer->detachRenderbuffer(renderbuffer);
2794 }
2795}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002796
2797Texture *Context::getIncompleteTexture(SamplerType type)
2798{
2799 Texture *t = mIncompleteTextures[type];
2800
2801 if (t == NULL)
2802 {
2803 static const GLubyte color[] = { 0, 0, 0, 255 };
2804
2805 switch (type)
2806 {
2807 default:
2808 UNREACHABLE();
2809 // default falls through to SAMPLER_2D
2810
2811 case SAMPLER_2D:
2812 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002813 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002814 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002815 t = incomplete2d;
2816 }
2817 break;
2818
2819 case SAMPLER_CUBE:
2820 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002821 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002822
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002823 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2824 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2825 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2826 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2827 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2828 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002829
2830 t = incompleteCube;
2831 }
2832 break;
2833 }
2834
2835 mIncompleteTextures[type] = t;
2836 }
2837
2838 return t;
2839}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002840
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002841bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002842{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002843 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002844}
2845
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002846bool Context::isTriangleMode(GLenum drawMode)
2847{
2848 switch (drawMode)
2849 {
2850 case GL_TRIANGLES:
2851 case GL_TRIANGLE_FAN:
2852 case GL_TRIANGLE_STRIP:
2853 return true;
2854 case GL_POINTS:
2855 case GL_LINES:
2856 case GL_LINE_LOOP:
2857 case GL_LINE_STRIP:
2858 return false;
2859 default: UNREACHABLE();
2860 }
2861
2862 return false;
2863}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002864
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002865bool Context::hasStencil()
2866{
2867 Framebuffer *framebufferObject = getFramebuffer();
2868
2869 if (framebufferObject)
2870 {
2871 Stencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
2872
2873 if (stencilbufferObject)
2874 {
2875 return stencilbufferObject->getStencilSize() > 0;
2876 }
2877 }
2878
2879 return false;
2880}
2881
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002882void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2883{
2884 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2885
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002886 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2887 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2888 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2889 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002890
2891 mVertexDataManager->dirtyCurrentValues();
2892}
2893
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002894void Context::initExtensionString()
2895{
2896 if (mBufferBackEnd->supportIntIndices())
2897 {
2898 mExtensionString += "GL_OES_element_index_uint ";
2899 }
2900
2901 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2902 if (end != std::string::npos)
2903 {
2904 mExtensionString.resize(end+1);
2905 }
2906}
2907
2908const char *Context::getExtensionString() const
2909{
2910 return mExtensionString.c_str();
2911}
2912
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002913}
2914
2915extern "C"
2916{
2917gl::Context *glCreateContext(const egl::Config *config)
2918{
2919 return new gl::Context(config);
2920}
2921
2922void glDestroyContext(gl::Context *context)
2923{
2924 delete context;
2925
2926 if (context == gl::getContext())
2927 {
2928 gl::makeCurrent(NULL, NULL, NULL);
2929 }
2930}
2931
2932void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2933{
2934 gl::makeCurrent(context, display, surface);
2935}
2936
2937gl::Context *glGetCurrentContext()
2938{
2939 return gl::getContext();
2940}
2941}