blob: 61ab25a8b079803b6d7c274ae3233de968b398ba [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);
40 depthClearValue = 1.0f;
41 stencilClearValue = 0;
42
43 cullFace = false;
44 cullMode = GL_BACK;
45 frontFace = GL_CCW;
46 depthTest = false;
47 depthFunc = GL_LESS;
48 blend = false;
49 sourceBlendRGB = GL_ONE;
50 sourceBlendAlpha = GL_ONE;
51 destBlendRGB = GL_ZERO;
52 destBlendAlpha = GL_ZERO;
53 blendEquationRGB = GL_FUNC_ADD;
54 blendEquationAlpha = GL_FUNC_ADD;
55 blendColor.red = 0;
56 blendColor.green = 0;
57 blendColor.blue = 0;
58 blendColor.alpha = 0;
59 stencilTest = false;
60 stencilFunc = GL_ALWAYS;
61 stencilRef = 0;
62 stencilMask = -1;
63 stencilWritemask = -1;
64 stencilBackFunc = GL_ALWAYS;
65 stencilBackRef = 0;
66 stencilBackMask = - 1;
67 stencilBackWritemask = -1;
68 stencilFail = GL_KEEP;
69 stencilPassDepthFail = GL_KEEP;
70 stencilPassDepthPass = GL_KEEP;
71 stencilBackFail = GL_KEEP;
72 stencilBackPassDepthFail = GL_KEEP;
73 stencilBackPassDepthPass = GL_KEEP;
74 polygonOffsetFill = false;
daniel@transgaming.com777f2672010-04-07 03:25:16 +000075 polygonOffsetFactor = 0.0f;
76 polygonOffsetUnits = 0.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000077 sampleAlphaToCoverage = false;
78 sampleCoverage = false;
79 sampleCoverageValue = 1.0f;
80 sampleCoverageInvert = GL_FALSE;
81 scissorTest = false;
82 dither = true;
daniel@transgaming.com5949aa12010-03-21 04:31:15 +000083 generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000085 lineWidth = 1.0f;
86
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087 viewportX = 0;
88 viewportY = 0;
89 viewportWidth = config->mDisplayMode.Width;
90 viewportHeight = config->mDisplayMode.Height;
91 zNear = 0.0f;
92 zFar = 1.0f;
93
94 scissorX = 0;
95 scissorY = 0;
96 scissorWidth = config->mDisplayMode.Width;
97 scissorHeight = config->mDisplayMode.Height;
98
99 colorMaskRed = true;
100 colorMaskGreen = true;
101 colorMaskBlue = true;
102 colorMaskAlpha = true;
103 depthMask = true;
104
105 // [OpenGL ES 2.0.24] section 3.7 page 83:
106 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
107 // and cube map texture state vectors respectively associated with them.
108 // In order that access to these initial textures not be lost, they are treated as texture
109 // objects all of whose names are 0.
110
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000111 mTexture2DZero = new Texture2D(this);
112 mTextureCubeMapZero = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113
114 mColorbufferZero = NULL;
115 mDepthbufferZero = NULL;
116 mStencilbufferZero = NULL;
117
118 activeSampler = 0;
119 arrayBuffer = 0;
120 elementArrayBuffer = 0;
121 bindTextureCubeMap(0);
122 bindTexture2D(0);
123 bindFramebuffer(0);
124 bindRenderbuffer(0);
125
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000126 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000128 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
129 {
130 samplerTexture[type][sampler] = 0;
131 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132 }
133
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000134 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
135 {
136 mIncompleteTextures[type] = NULL;
137 }
138
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139 currentProgram = 0;
140
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000141 packAlignment = 4;
142 unpackAlignment = 4;
143
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000144 mBufferBackEnd = NULL;
145 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000146 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000147 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000148
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149 mInvalidEnum = false;
150 mInvalidValue = false;
151 mInvalidOperation = false;
152 mOutOfMemory = false;
153 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000154
155 mHasBeenCurrent = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156}
157
158Context::~Context()
159{
160 currentProgram = 0;
161
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000162 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
163 {
164 delete mIncompleteTextures[type];
165 }
166
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167 delete mTexture2DZero;
168 delete mTextureCubeMapZero;
169
170 delete mColorbufferZero;
171 delete mDepthbufferZero;
172 delete mStencilbufferZero;
173
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000174 delete mBufferBackEnd;
175 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000176 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000177 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000178
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179 while (!mBufferMap.empty())
180 {
181 deleteBuffer(mBufferMap.begin()->first);
182 }
183
184 while (!mProgramMap.empty())
185 {
186 deleteProgram(mProgramMap.begin()->first);
187 }
188
189 while (!mShaderMap.empty())
190 {
191 deleteShader(mShaderMap.begin()->first);
192 }
193
194 while (!mFramebufferMap.empty())
195 {
196 deleteFramebuffer(mFramebufferMap.begin()->first);
197 }
198
199 while (!mRenderbufferMap.empty())
200 {
201 deleteRenderbuffer(mRenderbufferMap.begin()->first);
202 }
203
204 while (!mTextureMap.empty())
205 {
206 deleteTexture(mTextureMap.begin()->first);
207 }
208}
209
210void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
211{
212 IDirect3DDevice9 *device = display->getDevice();
213
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000214 if (!mBufferBackEnd)
215 {
216 mBufferBackEnd = new Dx9BackEnd(device);
217 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000218 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000219 mBlit = new Blit(this);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000220 }
221
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
223 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000224 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225
226 Framebuffer *framebufferZero = new Framebuffer();
227 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000228 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
229 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230
231 setFramebufferZero(framebufferZero);
232 setColorbufferZero(colorbufferZero);
233 setDepthbufferZero(depthbufferZero);
234 setStencilbufferZero(stencilbufferZero);
235
236 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
237 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
238 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
239
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000240 if(!mHasBeenCurrent)
241 {
242 viewportX = 0;
243 viewportY = 0;
244 viewportWidth = surface->getWidth();
245 viewportHeight = surface->getHeight();
246
247 scissorX = 0;
248 scissorY = 0;
249 scissorWidth = surface->getWidth();
250 scissorHeight = surface->getHeight();
251
252 mHasBeenCurrent = true;
253 }
254
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255 defaultRenderTarget->Release();
256
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000257 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000259 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000261
262 D3DCAPS9 capabilities;
263 device->GetDeviceCaps(&capabilities);
264
265 if (capabilities.PixelShaderVersion == D3DPS_VERSION(3, 0))
266 {
267 mPsProfile = "ps_3_0";
268 mVsProfile = "vs_3_0";
269 }
270 else // egl::Display guarantees support for at least 2.0
271 {
272 mPsProfile = "ps_2_0";
273 mVsProfile = "vs_2_0";
274 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275}
276
277void Context::setClearColor(float red, float green, float blue, float alpha)
278{
279 colorClearValue.red = red;
280 colorClearValue.green = green;
281 colorClearValue.blue = blue;
282 colorClearValue.alpha = alpha;
283}
284
285void Context::setClearDepth(float depth)
286{
287 depthClearValue = depth;
288}
289
290void Context::setClearStencil(int stencil)
291{
292 stencilClearValue = stencil;
293}
294
295// Returns an unused buffer name
296GLuint Context::createBuffer()
297{
298 unsigned int handle = 1;
299
300 while (mBufferMap.find(handle) != mBufferMap.end())
301 {
302 handle++;
303 }
304
305 mBufferMap[handle] = NULL;
306
307 return handle;
308}
309
310// Returns an unused shader/program name
311GLuint Context::createShader(GLenum type)
312{
313 unsigned int handle = 1;
314
315 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
316 {
317 handle++;
318 }
319
320 if (type == GL_VERTEX_SHADER)
321 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000322 mShaderMap[handle] = new VertexShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000323 }
324 else if (type == GL_FRAGMENT_SHADER)
325 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000326 mShaderMap[handle] = new FragmentShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327 }
328 else UNREACHABLE();
329
330 return handle;
331}
332
333// Returns an unused program/shader name
334GLuint Context::createProgram()
335{
336 unsigned int handle = 1;
337
338 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
339 {
340 handle++;
341 }
342
343 mProgramMap[handle] = new Program();
344
345 return handle;
346}
347
348// Returns an unused texture name
349GLuint Context::createTexture()
350{
351 unsigned int handle = 1;
352
353 while (mTextureMap.find(handle) != mTextureMap.end())
354 {
355 handle++;
356 }
357
358 mTextureMap[handle] = NULL;
359
360 return handle;
361}
362
363// Returns an unused framebuffer name
364GLuint Context::createFramebuffer()
365{
366 unsigned int handle = 1;
367
368 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
369 {
370 handle++;
371 }
372
373 mFramebufferMap[handle] = NULL;
374
375 return handle;
376}
377
378// Returns an unused renderbuffer name
379GLuint Context::createRenderbuffer()
380{
381 unsigned int handle = 1;
382
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000383 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384 {
385 handle++;
386 }
387
388 mRenderbufferMap[handle] = NULL;
389
390 return handle;
391}
392
393void Context::deleteBuffer(GLuint buffer)
394{
395 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
396
397 if (bufferObject != mBufferMap.end())
398 {
399 detachBuffer(buffer);
400
401 delete bufferObject->second;
402 mBufferMap.erase(bufferObject);
403 }
404}
405
406void Context::deleteShader(GLuint shader)
407{
408 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
409
410 if (shaderObject != mShaderMap.end())
411 {
412 if (!shaderObject->second->isAttached())
413 {
414 delete shaderObject->second;
415 mShaderMap.erase(shaderObject);
416 }
417 else
418 {
419 shaderObject->second->flagForDeletion();
420 }
421 }
422}
423
424void Context::deleteProgram(GLuint program)
425{
426 ProgramMap::iterator programObject = mProgramMap.find(program);
427
428 if (programObject != mProgramMap.end())
429 {
430 if (program != currentProgram)
431 {
432 delete programObject->second;
433 mProgramMap.erase(programObject);
434 }
435 else
436 {
437 programObject->second->flagForDeletion();
438 }
439 }
440}
441
442void Context::deleteTexture(GLuint texture)
443{
444 TextureMap::iterator textureObject = mTextureMap.find(texture);
445
446 if (textureObject != mTextureMap.end())
447 {
448 detachTexture(texture);
449
450 if (texture != 0)
451 {
452 delete textureObject->second;
453 }
454
455 mTextureMap.erase(textureObject);
456 }
457}
458
459void Context::deleteFramebuffer(GLuint framebuffer)
460{
461 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
462
463 if (framebufferObject != mFramebufferMap.end())
464 {
465 detachFramebuffer(framebuffer);
466
467 delete framebufferObject->second;
468 mFramebufferMap.erase(framebufferObject);
469 }
470}
471
472void Context::deleteRenderbuffer(GLuint renderbuffer)
473{
474 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
475
476 if (renderbufferObject != mRenderbufferMap.end())
477 {
478 detachRenderbuffer(renderbuffer);
479
480 delete renderbufferObject->second;
481 mRenderbufferMap.erase(renderbufferObject);
482 }
483}
484
485void Context::bindArrayBuffer(unsigned int buffer)
486{
487 if (buffer != 0 && !getBuffer(buffer))
488 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000489 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000490 }
491
492 arrayBuffer = buffer;
493}
494
495void Context::bindElementArrayBuffer(unsigned int buffer)
496{
497 if (buffer != 0 && !getBuffer(buffer))
498 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000499 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000500 }
501
502 elementArrayBuffer = buffer;
503}
504
505void Context::bindTexture2D(GLuint texture)
506{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000507 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000509 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000510 }
511
512 texture2D = texture;
513
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000514 samplerTexture[SAMPLER_2D][activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000515}
516
517void Context::bindTextureCubeMap(GLuint texture)
518{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000519 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000520 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000521 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000522 }
523
524 textureCubeMap = texture;
525
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000526 samplerTexture[SAMPLER_CUBE][activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000527}
528
529void Context::bindFramebuffer(GLuint framebuffer)
530{
531 if (!getFramebuffer(framebuffer))
532 {
533 mFramebufferMap[framebuffer] = new Framebuffer();
534 }
535
536 this->framebuffer = framebuffer;
537}
538
539void Context::bindRenderbuffer(GLuint renderbuffer)
540{
541 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
542 {
543 mRenderbufferMap[renderbuffer] = new Renderbuffer();
544 }
545
546 this->renderbuffer = renderbuffer;
547}
548
549void Context::useProgram(GLuint program)
550{
551 Program *programObject = getCurrentProgram();
552
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000553 GLuint priorProgram = currentProgram;
554 currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
555
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000556 if (programObject && programObject->isFlaggedForDeletion())
557 {
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000558 deleteProgram(priorProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000559 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000560}
561
562void Context::setFramebufferZero(Framebuffer *buffer)
563{
564 delete mFramebufferMap[0];
565 mFramebufferMap[0] = buffer;
566}
567
568void Context::setColorbufferZero(Colorbuffer *buffer)
569{
570 delete mColorbufferZero;
571 mColorbufferZero = buffer;
572}
573
574void Context::setDepthbufferZero(Depthbuffer *buffer)
575{
576 delete mDepthbufferZero;
577 mDepthbufferZero = buffer;
578}
579
580void Context::setStencilbufferZero(Stencilbuffer *buffer)
581{
582 delete mStencilbufferZero;
583 mStencilbufferZero = buffer;
584}
585
586void Context::setRenderbuffer(Renderbuffer *buffer)
587{
588 delete mRenderbufferMap[renderbuffer];
589 mRenderbufferMap[renderbuffer] = buffer;
590}
591
592Buffer *Context::getBuffer(unsigned int handle)
593{
594 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000595
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000596 if (buffer == mBufferMap.end())
597 {
598 return NULL;
599 }
600 else
601 {
602 return buffer->second;
603 }
604}
605
606Shader *Context::getShader(unsigned int handle)
607{
608 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000609
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000610 if (shader == mShaderMap.end())
611 {
612 return NULL;
613 }
614 else
615 {
616 return shader->second;
617 }
618}
619
620Program *Context::getProgram(unsigned int handle)
621{
622 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000623
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000624 if (program == mProgramMap.end())
625 {
626 return NULL;
627 }
628 else
629 {
630 return program->second;
631 }
632}
633
634Texture *Context::getTexture(unsigned int handle)
635{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000636 if (handle == 0) return NULL;
637
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000638 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000639
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000640 if (texture == mTextureMap.end())
641 {
642 return NULL;
643 }
644 else
645 {
646 return texture->second;
647 }
648}
649
650Framebuffer *Context::getFramebuffer(unsigned int handle)
651{
652 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000653
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000654 if (framebuffer == mFramebufferMap.end())
655 {
656 return NULL;
657 }
658 else
659 {
660 return framebuffer->second;
661 }
662}
663
664Renderbuffer *Context::getRenderbuffer(unsigned int handle)
665{
666 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000667
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668 if (renderbuffer == mRenderbufferMap.end())
669 {
670 return NULL;
671 }
672 else
673 {
674 return renderbuffer->second;
675 }
676}
677
678Colorbuffer *Context::getColorbuffer(GLuint handle)
679{
680 if (handle != 0)
681 {
682 Renderbuffer *renderbuffer = getRenderbuffer(handle);
683
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000684 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000685 {
686 return static_cast<Colorbuffer*>(renderbuffer);
687 }
688 }
689 else // Special case: 0 refers to different initial render targets based on the attachment type
690 {
691 return mColorbufferZero;
692 }
693
694 return NULL;
695}
696
697Depthbuffer *Context::getDepthbuffer(GLuint handle)
698{
699 if (handle != 0)
700 {
701 Renderbuffer *renderbuffer = getRenderbuffer(handle);
702
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000703 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000704 {
705 return static_cast<Depthbuffer*>(renderbuffer);
706 }
707 }
708 else // Special case: 0 refers to different initial render targets based on the attachment type
709 {
710 return mDepthbufferZero;
711 }
712
713 return NULL;
714}
715
716Stencilbuffer *Context::getStencilbuffer(GLuint handle)
717{
718 if (handle != 0)
719 {
720 Renderbuffer *renderbuffer = getRenderbuffer(handle);
721
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000722 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723 {
724 return static_cast<Stencilbuffer*>(renderbuffer);
725 }
726 }
727 else
728 {
729 return mStencilbufferZero;
730 }
731
732 return NULL;
733}
734
735Buffer *Context::getArrayBuffer()
736{
737 return getBuffer(arrayBuffer);
738}
739
740Buffer *Context::getElementArrayBuffer()
741{
742 return getBuffer(elementArrayBuffer);
743}
744
745Program *Context::getCurrentProgram()
746{
747 return getProgram(currentProgram);
748}
749
750Texture2D *Context::getTexture2D()
751{
752 if (texture2D == 0) // Special case: 0 refers to different initial textures based on the target
753 {
754 return mTexture2DZero;
755 }
756
757 return (Texture2D*)getTexture(texture2D);
758}
759
760TextureCubeMap *Context::getTextureCubeMap()
761{
762 if (textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
763 {
764 return mTextureCubeMapZero;
765 }
766
767 return (TextureCubeMap*)getTexture(textureCubeMap);
768}
769
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000770Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000771{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000772 GLuint texid = samplerTexture[type][sampler];
773
774 if (texid == 0)
775 {
776 switch (type)
777 {
778 default: UNREACHABLE();
779 case SAMPLER_2D: return mTexture2DZero;
780 case SAMPLER_CUBE: return mTextureCubeMapZero;
781 }
782 }
783
784 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000785}
786
787Framebuffer *Context::getFramebuffer()
788{
789 return getFramebuffer(framebuffer);
790}
791
daniel@transgaming.com777f2672010-04-07 03:25:16 +0000792bool Context::getBooleanv(GLenum pname, GLboolean *params)
793{
794 switch (pname)
795 {
796 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
797 case GL_SAMPLE_COVERAGE_INVERT: *params = sampleCoverageInvert; break;
798 case GL_DEPTH_WRITEMASK: *params = depthMask; break;
799 case GL_COLOR_WRITEMASK:
800 params[0] = colorMaskRed;
801 params[1] = colorMaskGreen;
802 params[2] = colorMaskBlue;
803 params[3] = colorMaskAlpha;
804 break;
daniel@transgaming.com79f66772010-04-13 03:26:09 +0000805 case GL_CULL_FACE: *params = cullFace;
806 case GL_POLYGON_OFFSET_FILL: *params = polygonOffsetFill;
807 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = sampleAlphaToCoverage;
808 case GL_SAMPLE_COVERAGE: *params = sampleCoverage;
809 case GL_SCISSOR_TEST: *params = scissorTest;
810 case GL_STENCIL_TEST: *params = stencilTest;
811 case GL_DEPTH_TEST: *params = depthTest;
812 case GL_BLEND: *params = blend;
813 case GL_DITHER: *params = dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +0000814 default:
815 return false;
816 }
817
818 return true;
819}
820
821bool Context::getFloatv(GLenum pname, GLfloat *params)
822{
823 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
824 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
825 // GetIntegerv as its native query function. As it would require conversion in any
826 // case, this should make no difference to the calling application.
827 switch (pname)
828 {
829 case GL_LINE_WIDTH: *params = lineWidth; break;
830 case GL_SAMPLE_COVERAGE_VALUE: *params = sampleCoverageValue; break;
831 case GL_DEPTH_CLEAR_VALUE: *params = depthClearValue; break;
832 case GL_POLYGON_OFFSET_FACTOR: *params = polygonOffsetFactor; break;
833 case GL_POLYGON_OFFSET_UNITS: *params = polygonOffsetUnits; break;
834 case GL_ALIASED_LINE_WIDTH_RANGE:
835 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
836 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
837 break;
838 case GL_ALIASED_POINT_SIZE_RANGE:
839 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
840 params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
841 break;
842 case GL_DEPTH_RANGE:
843 params[0] = zNear;
844 params[1] = zFar;
845 break;
846 case GL_COLOR_CLEAR_VALUE:
847 params[0] = colorClearValue.red;
848 params[1] = colorClearValue.green;
849 params[2] = colorClearValue.blue;
850 params[3] = colorClearValue.alpha;
851 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +0000852 case GL_BLEND_COLOR:
853 params[0] = blendColor.red;
854 params[1] = blendColor.green;
855 params[2] = blendColor.blue;
856 params[3] = blendColor.alpha;
857 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +0000858 default:
859 return false;
860 }
861
862 return true;
863}
864
865bool Context::getIntegerv(GLenum pname, GLint *params)
866{
867 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
868 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
869 // GetIntegerv as its native query function. As it would require conversion in any
870 // case, this should make no difference to the calling application. You may find it in
871 // Context::getFloatv.
872 switch (pname)
873 {
874 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
875 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
876 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
877 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
878 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
879 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
880 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
881 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
882 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
883 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
884 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
885 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
886 case GL_ARRAY_BUFFER_BINDING: *params = arrayBuffer; break;
887 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = elementArrayBuffer; break;
888 case GL_FRAMEBUFFER_BINDING: *params = framebuffer; break;
889 case GL_RENDERBUFFER_BINDING: *params = renderbuffer; break;
890 case GL_CURRENT_PROGRAM: *params = currentProgram; break;
891 case GL_PACK_ALIGNMENT: *params = packAlignment; break;
892 case GL_UNPACK_ALIGNMENT: *params = unpackAlignment; break;
893 case GL_GENERATE_MIPMAP_HINT: *params = generateMipmapHint; break;
894 case GL_ACTIVE_TEXTURE: *params = activeSampler; break;
895 case GL_STENCIL_FUNC: *params = stencilFunc; break;
896 case GL_STENCIL_REF: *params = stencilRef; break;
897 case GL_STENCIL_VALUE_MASK: *params = stencilMask; break;
898 case GL_STENCIL_BACK_FUNC: *params = stencilBackFunc; break;
899 case GL_STENCIL_BACK_REF: *params = stencilBackRef; break;
900 case GL_STENCIL_BACK_VALUE_MASK: *params = stencilBackMask; break;
901 case GL_STENCIL_FAIL: *params = stencilFail; break;
902 case GL_STENCIL_PASS_DEPTH_FAIL: *params = stencilPassDepthFail; break;
903 case GL_STENCIL_PASS_DEPTH_PASS: *params = stencilPassDepthPass; break;
904 case GL_STENCIL_BACK_FAIL: *params = stencilBackFail; break;
905 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = stencilBackPassDepthFail; break;
906 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = stencilBackPassDepthPass; break;
907 case GL_DEPTH_FUNC: *params = depthFunc; break;
908 case GL_BLEND_SRC_RGB: *params = sourceBlendRGB; break;
909 case GL_BLEND_SRC_ALPHA: *params = sourceBlendAlpha; break;
910 case GL_BLEND_DST_RGB: *params = destBlendRGB; break;
911 case GL_BLEND_DST_ALPHA: *params = destBlendAlpha; break;
912 case GL_BLEND_EQUATION_RGB: *params = blendEquationRGB; break;
913 case GL_BLEND_EQUATION_ALPHA: *params = blendEquationAlpha; break;
914 case GL_STENCIL_WRITEMASK: *params = stencilWritemask; break;
915 case GL_STENCIL_BACK_WRITEMASK: *params = stencilBackWritemask; break;
916 case GL_STENCIL_CLEAR_VALUE: *params = stencilClearValue; break;
917 case GL_SUBPIXEL_BITS: *params = 4; break;
918 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
919 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
920 case GL_SAMPLE_BUFFERS: *params = 0; break;
921 case GL_SAMPLES: *params = 0; break;
922 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
923 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
924 case GL_MAX_VIEWPORT_DIMS:
925 {
926 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
927 params[0] = maxDimension;
928 params[1] = maxDimension;
929 }
930 break;
931 case GL_VIEWPORT:
932 params[0] = viewportX;
933 params[1] = viewportY;
934 params[2] = viewportWidth;
935 params[3] = viewportHeight;
936 break;
937 case GL_SCISSOR_BOX:
938 params[0] = scissorX;
939 params[1] = scissorY;
940 params[2] = scissorWidth;
941 params[3] = scissorHeight;
942 break;
943 case GL_CULL_FACE_MODE: *params = cullMode; break;
944 case GL_FRONT_FACE: *params = frontFace; break;
945 case GL_RED_BITS:
946 case GL_GREEN_BITS:
947 case GL_BLUE_BITS:
948 case GL_ALPHA_BITS:
949 {
950 gl::Framebuffer *framebuffer = getFramebuffer();
951 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
952
953 if (colorbuffer)
954 {
955 switch (pname)
956 {
957 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
958 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
959 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
960 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
961 }
962 }
963 else
964 {
965 *params = 0;
966 }
967 }
968 break;
969 case GL_DEPTH_BITS:
970 {
971 gl::Framebuffer *framebuffer = getFramebuffer();
972 gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
973
974 if (depthbuffer)
975 {
976 *params = depthbuffer->getDepthSize();
977 }
978 else
979 {
980 *params = 0;
981 }
982 }
983 break;
984 case GL_STENCIL_BITS:
985 {
986 gl::Framebuffer *framebuffer = getFramebuffer();
987 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
988
989 if (stencilbuffer)
990 {
991 *params = stencilbuffer->getStencilSize();
992 }
993 else
994 {
995 *params = 0;
996 }
997 }
998 break;
999 case GL_TEXTURE_BINDING_2D:
1000 {
1001 if (activeSampler < 0 || activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
1002 {
1003 error(GL_INVALID_OPERATION);
1004 return false;
1005 }
1006
1007 *params = samplerTexture[SAMPLER_2D][activeSampler];
1008 }
1009 break;
1010 case GL_TEXTURE_BINDING_CUBE_MAP:
1011 {
1012 if (activeSampler < 0 || activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
1013 {
1014 error(GL_INVALID_OPERATION);
1015 return false;
1016 }
1017
1018 *params = samplerTexture[SAMPLER_CUBE][activeSampler];
1019 }
1020 break;
1021 default:
1022 return false;
1023 }
1024
1025 return true;
1026}
1027
1028bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1029{
1030 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1031 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1032 // to the fact that it is stored internally as a float, and so would require conversion
1033 // if returned from Context::getIntegerv. Since this conversion is already implemented
1034 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1035 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1036 // application.
1037 switch (pname)
1038 {
1039 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1040 case GL_SHADER_BINARY_FORMATS:
1041 {
1042 *type = GL_INT;
1043 *numParams = 0;
1044 }
1045 break;
1046 case GL_MAX_VERTEX_ATTRIBS:
1047 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1048 case GL_MAX_VARYING_VECTORS:
1049 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1050 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1051 case GL_MAX_TEXTURE_IMAGE_UNITS:
1052 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1053 case GL_MAX_RENDERBUFFER_SIZE:
1054 case GL_NUM_SHADER_BINARY_FORMATS:
1055 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1056 case GL_ARRAY_BUFFER_BINDING:
1057 case GL_FRAMEBUFFER_BINDING:
1058 case GL_RENDERBUFFER_BINDING:
1059 case GL_CURRENT_PROGRAM:
1060 case GL_PACK_ALIGNMENT:
1061 case GL_UNPACK_ALIGNMENT:
1062 case GL_GENERATE_MIPMAP_HINT:
1063 case GL_RED_BITS:
1064 case GL_GREEN_BITS:
1065 case GL_BLUE_BITS:
1066 case GL_ALPHA_BITS:
1067 case GL_DEPTH_BITS:
1068 case GL_STENCIL_BITS:
1069 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1070 case GL_CULL_FACE_MODE:
1071 case GL_FRONT_FACE:
1072 case GL_ACTIVE_TEXTURE:
1073 case GL_STENCIL_FUNC:
1074 case GL_STENCIL_VALUE_MASK:
1075 case GL_STENCIL_REF:
1076 case GL_STENCIL_FAIL:
1077 case GL_STENCIL_PASS_DEPTH_FAIL:
1078 case GL_STENCIL_PASS_DEPTH_PASS:
1079 case GL_STENCIL_BACK_FUNC:
1080 case GL_STENCIL_BACK_VALUE_MASK:
1081 case GL_STENCIL_BACK_REF:
1082 case GL_STENCIL_BACK_FAIL:
1083 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1084 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1085 case GL_DEPTH_FUNC:
1086 case GL_BLEND_SRC_RGB:
1087 case GL_BLEND_SRC_ALPHA:
1088 case GL_BLEND_DST_RGB:
1089 case GL_BLEND_DST_ALPHA:
1090 case GL_BLEND_EQUATION_RGB:
1091 case GL_BLEND_EQUATION_ALPHA:
1092 case GL_STENCIL_WRITEMASK:
1093 case GL_STENCIL_BACK_WRITEMASK:
1094 case GL_STENCIL_CLEAR_VALUE:
1095 case GL_SUBPIXEL_BITS:
1096 case GL_MAX_TEXTURE_SIZE:
1097 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1098 case GL_SAMPLE_BUFFERS:
1099 case GL_SAMPLES:
1100 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1101 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1102 case GL_TEXTURE_BINDING_2D:
1103 case GL_TEXTURE_BINDING_CUBE_MAP:
1104 {
1105 *type = GL_INT;
1106 *numParams = 1;
1107 }
1108 break;
1109 case GL_MAX_VIEWPORT_DIMS:
1110 {
1111 *type = GL_INT;
1112 *numParams = 2;
1113 }
1114 break;
1115 case GL_VIEWPORT:
1116 case GL_SCISSOR_BOX:
1117 {
1118 *type = GL_INT;
1119 *numParams = 4;
1120 }
1121 break;
1122 case GL_SHADER_COMPILER:
1123 case GL_SAMPLE_COVERAGE_INVERT:
1124 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001125 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1126 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1127 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1128 case GL_SAMPLE_COVERAGE:
1129 case GL_SCISSOR_TEST:
1130 case GL_STENCIL_TEST:
1131 case GL_DEPTH_TEST:
1132 case GL_BLEND:
1133 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001134 {
1135 *type = GL_BOOL;
1136 *numParams = 1;
1137 }
1138 break;
1139 case GL_COLOR_WRITEMASK:
1140 {
1141 *type = GL_BOOL;
1142 *numParams = 4;
1143 }
1144 break;
1145 case GL_POLYGON_OFFSET_FACTOR:
1146 case GL_POLYGON_OFFSET_UNITS:
1147 case GL_SAMPLE_COVERAGE_VALUE:
1148 case GL_DEPTH_CLEAR_VALUE:
1149 case GL_LINE_WIDTH:
1150 {
1151 *type = GL_FLOAT;
1152 *numParams = 1;
1153 }
1154 break;
1155 case GL_ALIASED_LINE_WIDTH_RANGE:
1156 case GL_ALIASED_POINT_SIZE_RANGE:
1157 case GL_DEPTH_RANGE:
1158 {
1159 *type = GL_FLOAT;
1160 *numParams = 2;
1161 }
1162 break;
1163 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001164 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001165 {
1166 *type = GL_FLOAT;
1167 *numParams = 4;
1168 }
1169 break;
1170 default:
1171 return false;
1172 }
1173
1174 return true;
1175}
1176
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001177// Applies the render target surface, depth stencil surface, viewport rectangle and
1178// scissor rectangle to the Direct3D 9 device
1179bool Context::applyRenderTarget(bool ignoreViewport)
1180{
1181 IDirect3DDevice9 *device = getDevice();
1182 Framebuffer *framebufferObject = getFramebuffer();
1183
1184 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1185 {
1186 return false;
1187 }
1188
1189 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1190 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1191
1192 device->SetRenderTarget(0, renderTarget);
1193 device->SetDepthStencilSurface(depthStencil);
1194
1195 D3DVIEWPORT9 viewport;
1196 D3DSURFACE_DESC desc;
1197 renderTarget->GetDesc(&desc);
1198
1199 if (ignoreViewport)
1200 {
1201 viewport.X = 0;
1202 viewport.Y = 0;
1203 viewport.Width = desc.Width;
1204 viewport.Height = desc.Height;
1205 viewport.MinZ = 0.0f;
1206 viewport.MaxZ = 1.0f;
1207 }
1208 else
1209 {
daniel@transgaming.com16973022010-03-11 19:22:19 +00001210 viewport.X = std::max(viewportX, 0);
1211 viewport.Y = std::max(viewportY, 0);
1212 viewport.Width = std::min(viewportWidth, (int)desc.Width - (int)viewport.X);
1213 viewport.Height = std::min(viewportHeight, (int)desc.Height - (int)viewport.Y);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001214 viewport.MinZ = clamp01(zNear);
1215 viewport.MaxZ = clamp01(zFar);
1216 }
1217
1218 device->SetViewport(&viewport);
1219
1220 if (scissorTest)
1221 {
1222 RECT rect = {scissorX,
1223 scissorY,
1224 scissorX + scissorWidth,
1225 scissorY + scissorHeight};
1226
1227 device->SetScissorRect(&rect);
1228 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1229 }
1230 else
1231 {
1232 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1233 }
1234
1235 if (currentProgram)
1236 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001237 Program *programObject = getCurrentProgram();
1238
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001239 GLint halfPixelSize = programObject->getUniformLocation("dx_HalfPixelSize");
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001240 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001241 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001242
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001243 GLint window = programObject->getUniformLocation("dx_Window");
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001244 GLfloat whxy[4] = {viewportWidth / 2.0f, viewportHeight / 2.0f, (float)viewportX + viewportWidth / 2.0f, (float)viewportY + viewportHeight / 2.0f};
1245 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1246
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001247 GLint depth = programObject->getUniformLocation("dx_Depth");
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001248 GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
1249 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1250
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001251 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001252 programObject->setUniform1fv(near, 1, &zNear);
1253
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001254 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001255 programObject->setUniform1fv(far, 1, &zFar);
1256
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001257 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001258 GLfloat zDiff = zFar - zNear;
1259 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001260 }
1261
1262 return true;
1263}
1264
1265// 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 +00001266void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001267{
1268 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001269 Program *programObject = getCurrentProgram();
1270
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001271 GLint frontCCW = programObject->getUniformLocation("dx_FrontCCW");
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001272 GLint ccw = (frontFace == GL_CCW);
1273 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001274
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001275 GLint pointsOrLines = programObject->getUniformLocation("dx_PointsOrLines");
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001276 GLint alwaysFront = !isTriangleMode(drawMode);
1277 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1278
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001279 if (cullFace)
1280 {
1281 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(cullMode, frontFace));
1282 }
1283 else
1284 {
1285 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1286 }
1287
1288 if (depthTest)
1289 {
1290 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1291 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(depthFunc));
1292 }
1293 else
1294 {
1295 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
1296 }
1297
1298 if (blend)
1299 {
1300 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1301
1302 if (sourceBlendRGB != GL_CONSTANT_ALPHA && sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1303 destBlendRGB != GL_CONSTANT_ALPHA && destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1304 {
1305 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(blendColor));
1306 }
1307 else
1308 {
1309 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(blendColor.alpha),
1310 unorm<8>(blendColor.alpha),
1311 unorm<8>(blendColor.alpha),
1312 unorm<8>(blendColor.alpha)));
1313 }
1314
1315 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(sourceBlendRGB));
1316 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(destBlendRGB));
1317 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(blendEquationRGB));
1318
1319 if (sourceBlendRGB != sourceBlendAlpha || destBlendRGB != destBlendAlpha || blendEquationRGB != blendEquationAlpha)
1320 {
1321 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1322
1323 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(sourceBlendAlpha));
1324 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(destBlendAlpha));
1325 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(blendEquationAlpha));
1326
1327 }
1328 else
1329 {
1330 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1331 }
1332 }
1333 else
1334 {
1335 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1336 }
1337
1338 if (stencilTest)
1339 {
1340 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1341 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1342
1343 // FIXME: Unsupported by D3D9
1344 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1345 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1346 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001347 if(stencilWritemask != stencilBackWritemask || stencilRef != stencilBackRef || stencilMask != stencilBackMask)
1348 {
1349 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1350 return error(GL_INVALID_OPERATION);
1351 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001352
1353 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWritemask);
1354 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilFunc));
1355
1356 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilRef); // FIXME: Clamp to range
1357 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
1358
1359 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilFail));
1360 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilPassDepthFail));
1361 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilPassDepthPass));
1362
1363 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWritemask);
1364 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilBackFunc));
1365
1366 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilBackRef); // FIXME: Clamp to range
1367 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilBackMask);
1368
1369 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilBackFail));
1370 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilBackPassDepthFail));
1371 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilBackPassDepthPass));
1372 }
1373 else
1374 {
1375 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1376 }
1377
1378 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(colorMaskRed, colorMaskGreen, colorMaskBlue, colorMaskAlpha));
1379 device->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
1380
1381 if (polygonOffsetFill)
1382 {
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001383 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1384 if (depthbuffer)
1385 {
1386 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&polygonOffsetFactor));
1387 float depthBias = ldexp(polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1388 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1389 }
1390 }
1391 else
1392 {
1393 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1394 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001395 }
1396
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001397 if (mConfig->mMultiSample != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001398 {
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001399 if (sampleAlphaToCoverage)
1400 {
1401 FIXME("Sample alpha to coverage is unimplemented.");
1402 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001403
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001404 if (sampleCoverage)
1405 {
1406 FIXME("Sample coverage is unimplemented.");
1407 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001408 }
1409
1410 device->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
1411}
1412
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001413// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001414void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001415{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001416 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001417 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001418 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001419 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001420 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001421 }
1422 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001423}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001424
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001425// The indices parameter to glDrawElements can have two interpretations:
1426// - as a pointer into client memory
1427// - as an offset into the current GL_ELEMENT_ARRAY_BUFFER buffer
1428// Handle these cases here and return a pointer to the index data.
1429const Index *Context::adjustIndexPointer(const void *indices)
1430{
1431 if (elementArrayBuffer)
1432 {
1433 Buffer *buffer = getBuffer(elementArrayBuffer);
1434 return reinterpret_cast<const Index*>(static_cast<unsigned char*>(buffer->data()) + reinterpret_cast<GLsizei>(indices));
1435 }
1436 else
1437 {
1438 return static_cast<const Index*>(indices);
1439 }
1440}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001441
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001442void Context::applyVertexBuffer(GLint first, GLsizei count)
1443{
1444 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1445
1446 mVertexDataManager->preRenderValidate(first, count, translated);
1447
1448 lookupAttributeMapping(translated);
1449
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001450 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001451}
1452
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001453void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001454{
1455 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1456
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001457 mVertexDataManager->preRenderValidate(indexInfo, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001458
1459 lookupAttributeMapping(translated);
1460
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001461 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001462}
1463
1464// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001465TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001466{
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001467 TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(elementArrayBuffer), indices);
1468 mBufferBackEnd->setupIndicesPreDraw(indexInfo);
1469 return indexInfo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001470}
1471
1472// Applies the shaders and shader constants to the Direct3D 9 device
1473void Context::applyShaders()
1474{
1475 IDirect3DDevice9 *device = getDevice();
1476 Program *programObject = getCurrentProgram();
1477 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1478 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1479
1480 device->SetVertexShader(vertexShader);
1481 device->SetPixelShader(pixelShader);
1482
1483 programObject->applyUniforms();
1484}
1485
1486// Applies the textures and sampler states to the Direct3D 9 device
1487void Context::applyTextures()
1488{
1489 IDirect3DDevice9 *device = getDevice();
1490 Program *programObject = getCurrentProgram();
1491
1492 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1493 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001494 int textureUnit = programObject->getSamplerMapping(sampler);
1495 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001496 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001497 SamplerType textureType = programObject->getSamplerType(sampler);
1498
1499 Texture *texture = getSamplerTexture(textureUnit, textureType);
1500
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001501 if (texture->isComplete())
1502 {
1503 GLenum wrapS = texture->getWrapS();
1504 GLenum wrapT = texture->getWrapT();
1505 GLenum minFilter = texture->getMinFilter();
1506 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001507
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001508 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1509 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001510
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001511 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1512 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1513 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1514 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1515 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001516
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001517 device->SetTexture(sampler, texture->getTexture());
1518 }
1519 else
1520 {
1521 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1522 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001523 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001524 else
1525 {
1526 device->SetTexture(sampler, NULL);
1527 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001528 }
1529}
1530
1531void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1532{
1533 Framebuffer *framebuffer = getFramebuffer();
1534 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1535 IDirect3DDevice9 *device = getDevice();
1536
1537 D3DSURFACE_DESC desc;
1538 renderTarget->GetDesc(&desc);
1539
1540 IDirect3DSurface9 *systemSurface;
1541 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1542
1543 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1544 {
1545 return error(GL_OUT_OF_MEMORY);
1546 }
1547
1548 ASSERT(SUCCEEDED(result));
1549
1550 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1551 {
1552 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1553 }
1554
1555 result = device->GetRenderTargetData(renderTarget, systemSurface);
1556
1557 if (result == D3DERR_DRIVERINTERNALERROR)
1558 {
1559 systemSurface->Release();
1560
1561 return error(GL_OUT_OF_MEMORY);
1562 }
1563
1564 if (FAILED(result))
1565 {
1566 UNREACHABLE();
1567 systemSurface->Release();
1568
1569 return; // No sensible error to generate
1570 }
1571
1572 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001573 RECT rect = {std::max(x, 0),
1574 std::max(y, 0),
1575 std::min(x + width, (int)desc.Width),
1576 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001577
1578 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1579
1580 if (FAILED(result))
1581 {
1582 UNREACHABLE();
1583 systemSurface->Release();
1584
1585 return; // No sensible error to generate
1586 }
1587
1588 unsigned char *source = (unsigned char*)lock.pBits;
1589 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001590 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001591
1592 for (int j = 0; j < rect.bottom - rect.top; j++)
1593 {
1594 for (int i = 0; i < rect.right - rect.left; i++)
1595 {
1596 float r;
1597 float g;
1598 float b;
1599 float a;
1600
1601 switch (desc.Format)
1602 {
1603 case D3DFMT_R5G6B5:
1604 {
1605 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1606
1607 a = 1.0f;
1608 b = (rgb & 0x001F) * (1.0f / 0x001F);
1609 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1610 r = (rgb & 0xF800) * (1.0f / 0xF800);
1611 }
1612 break;
1613 case D3DFMT_X1R5G5B5:
1614 {
1615 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1616
1617 a = 1.0f;
1618 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1619 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1620 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1621 }
1622 break;
1623 case D3DFMT_A1R5G5B5:
1624 {
1625 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1626
1627 a = (argb & 0x8000) ? 1.0f : 0.0f;
1628 b = (argb & 0x001F) * (1.0f / 0x001F);
1629 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1630 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1631 }
1632 break;
1633 case D3DFMT_A8R8G8B8:
1634 {
1635 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1636
1637 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1638 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1639 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1640 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1641 }
1642 break;
1643 case D3DFMT_X8R8G8B8:
1644 {
1645 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1646
1647 a = 1.0f;
1648 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
1649 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
1650 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
1651 }
1652 break;
1653 case D3DFMT_A2R10G10B10:
1654 {
1655 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1656
1657 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
1658 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
1659 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
1660 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
1661 }
1662 break;
1663 default:
1664 UNIMPLEMENTED(); // FIXME
1665 UNREACHABLE();
1666 }
1667
1668 switch (format)
1669 {
1670 case GL_RGBA:
1671 switch (type)
1672 {
1673 case GL_UNSIGNED_BYTE:
1674 dest[4 * (i + j * width) + 0] = (unsigned char)(255 * r + 0.5f);
1675 dest[4 * (i + j * width) + 1] = (unsigned char)(255 * g + 0.5f);
1676 dest[4 * (i + j * width) + 2] = (unsigned char)(255 * b + 0.5f);
1677 dest[4 * (i + j * width) + 3] = (unsigned char)(255 * a + 0.5f);
1678 break;
1679 default: UNREACHABLE();
1680 }
1681 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001682 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001683 switch (type)
1684 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001685 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
1686 dest16[i + j * width] = ((unsigned short)(31 * b + 0.5f) << 0) |
1687 ((unsigned short)(63 * g + 0.5f) << 5) |
1688 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001689 break;
1690 default: UNREACHABLE();
1691 }
1692 break;
1693 default: UNREACHABLE();
1694 }
1695 }
1696 }
1697
1698 systemSurface->UnlockRect();
1699
1700 systemSurface->Release();
1701}
1702
1703void Context::clear(GLbitfield mask)
1704{
1705 IDirect3DDevice9 *device = getDevice();
1706 DWORD flags = 0;
1707
1708 if (mask & GL_COLOR_BUFFER_BIT)
1709 {
1710 mask &= ~GL_COLOR_BUFFER_BIT;
1711 flags |= D3DCLEAR_TARGET;
1712 }
1713
1714 if (mask & GL_DEPTH_BUFFER_BIT)
1715 {
1716 mask &= ~GL_DEPTH_BUFFER_BIT;
1717 if (depthMask)
1718 {
1719 flags |= D3DCLEAR_ZBUFFER;
1720 }
1721 }
1722
1723 Framebuffer *framebufferObject = getFramebuffer();
1724 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1725
1726 GLuint stencilUnmasked = 0x0;
1727
1728 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
1729 {
1730 D3DSURFACE_DESC desc;
1731 depthStencil->GetDesc(&desc);
1732
1733 mask &= ~GL_STENCIL_BUFFER_BIT;
1734 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
1735 stencilUnmasked = (0x1 << stencilSize) - 1;
1736
1737 if (stencilUnmasked != 0x0)
1738 {
1739 flags |= D3DCLEAR_STENCIL;
1740 }
1741 }
1742
1743 if (mask != 0)
1744 {
1745 return error(GL_INVALID_VALUE);
1746 }
1747
1748 applyRenderTarget(true); // Clips the clear to the scissor rectangle but not the viewport
1749
1750 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(colorClearValue.alpha), unorm<8>(colorClearValue.red), unorm<8>(colorClearValue.green), unorm<8>(colorClearValue.blue));
1751 float depth = clamp01(depthClearValue);
1752 int stencil = stencilClearValue & 0x000000FF;
1753
1754 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1755
1756 D3DSURFACE_DESC desc;
1757 renderTarget->GetDesc(&desc);
1758
1759 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || colorMaskAlpha;
1760
1761 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
1762 (stencilWritemask & stencilUnmasked) != stencilUnmasked;
1763 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001764 !(colorMaskRed && colorMaskGreen &&
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001765 colorMaskBlue && alphaUnmasked);
1766
1767 if (needMaskedColorClear || needMaskedStencilClear)
1768 {
1769 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
1770 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1771 device->SetRenderState(D3DRS_ZENABLE, FALSE);
1772 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1773 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
1774 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
1775 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1776 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
1777
1778 if (flags & D3DCLEAR_TARGET)
1779 {
1780 device->SetRenderState(D3DRS_COLORWRITEENABLE, (colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
1781 (colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
1782 (colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
1783 (colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
1784 }
1785 else
1786 {
1787 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1788 }
1789
1790 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
1791 {
1792 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1793 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
1794 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
1795 device->SetRenderState(D3DRS_STENCILREF, stencil);
1796 device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001797 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001798 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
1799 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
1800 }
1801 else
1802 {
1803 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1804 }
1805
1806 device->SetPixelShader(NULL);
1807 device->SetVertexShader(NULL);
1808 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1809
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001810 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001811 {
1812 float x, y, z, w;
1813 D3DCOLOR diffuse;
1814 };
1815
1816 Vertex quad[4];
1817 quad[0].x = 0.0f;
1818 quad[0].y = (float)desc.Height;
1819 quad[0].z = 0.0f;
1820 quad[0].w = 1.0f;
1821 quad[0].diffuse = color;
1822
1823 quad[1].x = (float)desc.Width;
1824 quad[1].y = (float)desc.Height;
1825 quad[1].z = 0.0f;
1826 quad[1].w = 1.0f;
1827 quad[1].diffuse = color;
1828
1829 quad[2].x = 0.0f;
1830 quad[2].y = 0.0f;
1831 quad[2].z = 0.0f;
1832 quad[2].w = 1.0f;
1833 quad[2].diffuse = color;
1834
1835 quad[3].x = (float)desc.Width;
1836 quad[3].y = 0.0f;
1837 quad[3].z = 0.0f;
1838 quad[3].w = 1.0f;
1839 quad[3].diffuse = color;
1840
1841 device->BeginScene();
1842 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
1843 device->EndScene();
1844
1845 if (flags & D3DCLEAR_ZBUFFER)
1846 {
1847 device->SetRenderState(D3DRS_ZENABLE, TRUE);
1848 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
1849 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
1850 }
1851 }
1852 else
1853 {
1854 device->Clear(0, NULL, flags, color, depth, stencil);
1855 }
1856}
1857
1858void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
1859{
1860 if (!currentProgram)
1861 {
1862 return error(GL_INVALID_OPERATION);
1863 }
1864
1865 IDirect3DDevice9 *device = getDevice();
1866 D3DPRIMITIVETYPE primitiveType;
1867 int primitiveCount;
1868
1869 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1870 return error(GL_INVALID_ENUM);
1871
1872 if (primitiveCount <= 0)
1873 {
1874 return;
1875 }
1876
1877 if (!applyRenderTarget(false))
1878 {
1879 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1880 }
1881
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001882 applyState(mode);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001883 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001884 applyShaders();
1885 applyTextures();
1886
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00001887 if (!getCurrentProgram()->validateSamplers())
1888 {
1889 return error(GL_INVALID_OPERATION);
1890 }
1891
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001892 if (!cullSkipsDraw(mode))
1893 {
1894 device->BeginScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001895 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001896 device->EndScene();
1897 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001898}
1899
1900void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
1901{
1902 if (!currentProgram)
1903 {
1904 return error(GL_INVALID_OPERATION);
1905 }
1906
1907 if (!indices && !elementArrayBuffer)
1908 {
1909 return error(GL_INVALID_OPERATION);
1910 }
1911
1912 IDirect3DDevice9 *device = getDevice();
1913 D3DPRIMITIVETYPE primitiveType;
1914 int primitiveCount;
1915
1916 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1917 return error(GL_INVALID_ENUM);
1918
1919 if (primitiveCount <= 0)
1920 {
1921 return;
1922 }
1923
1924 if (!applyRenderTarget(false))
1925 {
1926 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1927 }
1928
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001929 applyState(mode);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001930 TranslatedIndexData indexInfo = applyIndexBuffer(indices, count, mode, type);
1931 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001932 applyShaders();
1933 applyTextures();
1934
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00001935 if (!getCurrentProgram()->validateSamplers())
1936 {
1937 return error(GL_INVALID_OPERATION);
1938 }
1939
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001940 if (!cullSkipsDraw(mode))
1941 {
1942 device->BeginScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001943 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/sizeof(Index), primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001944 device->EndScene();
1945 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001946}
1947
1948void Context::finish()
1949{
1950 IDirect3DDevice9 *device = getDevice();
1951 IDirect3DQuery9 *occlusionQuery = NULL;
1952
1953 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
1954
1955 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1956 {
1957 return error(GL_OUT_OF_MEMORY);
1958 }
1959
1960 ASSERT(SUCCEEDED(result));
1961
1962 if (occlusionQuery)
1963 {
1964 occlusionQuery->Issue(D3DISSUE_BEGIN);
1965
1966 // Render something outside the render target
1967 device->SetPixelShader(NULL);
1968 device->SetVertexShader(NULL);
1969 device->SetFVF(D3DFVF_XYZRHW);
1970 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
1971 device->BeginScene();
1972 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
1973 device->EndScene();
1974
1975 occlusionQuery->Issue(D3DISSUE_END);
1976
1977 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1978 {
1979 // Keep polling, but allow other threads to do something useful first
1980 Sleep(0);
1981 }
1982
1983 occlusionQuery->Release();
1984 }
1985}
1986
1987void Context::flush()
1988{
1989 IDirect3DDevice9 *device = getDevice();
1990 IDirect3DQuery9 *eventQuery = NULL;
1991
1992 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
1993
1994 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1995 {
1996 return error(GL_OUT_OF_MEMORY);
1997 }
1998
1999 ASSERT(SUCCEEDED(result));
2000
2001 if (eventQuery)
2002 {
2003 eventQuery->Issue(D3DISSUE_END);
2004
2005 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2006 {
2007 // Keep polling, but allow other threads to do something useful first
2008 Sleep(0);
2009 }
2010
2011 eventQuery->Release();
2012 }
2013}
2014
2015void Context::recordInvalidEnum()
2016{
2017 mInvalidEnum = true;
2018}
2019
2020void Context::recordInvalidValue()
2021{
2022 mInvalidValue = true;
2023}
2024
2025void Context::recordInvalidOperation()
2026{
2027 mInvalidOperation = true;
2028}
2029
2030void Context::recordOutOfMemory()
2031{
2032 mOutOfMemory = true;
2033}
2034
2035void Context::recordInvalidFramebufferOperation()
2036{
2037 mInvalidFramebufferOperation = true;
2038}
2039
2040// Get one of the recorded errors and clear its flag, if any.
2041// [OpenGL ES 2.0.24] section 2.5 page 13.
2042GLenum Context::getError()
2043{
2044 if (mInvalidEnum)
2045 {
2046 mInvalidEnum = false;
2047
2048 return GL_INVALID_ENUM;
2049 }
2050
2051 if (mInvalidValue)
2052 {
2053 mInvalidValue = false;
2054
2055 return GL_INVALID_VALUE;
2056 }
2057
2058 if (mInvalidOperation)
2059 {
2060 mInvalidOperation = false;
2061
2062 return GL_INVALID_OPERATION;
2063 }
2064
2065 if (mOutOfMemory)
2066 {
2067 mOutOfMemory = false;
2068
2069 return GL_OUT_OF_MEMORY;
2070 }
2071
2072 if (mInvalidFramebufferOperation)
2073 {
2074 mInvalidFramebufferOperation = false;
2075
2076 return GL_INVALID_FRAMEBUFFER_OPERATION;
2077 }
2078
2079 return GL_NO_ERROR;
2080}
2081
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002082const char *Context::getPixelShaderProfile()
2083{
2084 return mPsProfile;
2085}
2086
2087const char *Context::getVertexShaderProfile()
2088{
2089 return mVsProfile;
2090}
2091
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002092void Context::detachBuffer(GLuint buffer)
2093{
2094 // [OpenGL ES 2.0.24] section 2.9 page 22:
2095 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2096 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2097
2098 if (arrayBuffer == buffer)
2099 {
2100 arrayBuffer = 0;
2101 }
2102
2103 if (elementArrayBuffer == buffer)
2104 {
2105 elementArrayBuffer = 0;
2106 }
2107
2108 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2109 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002110 if (vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002111 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002112 vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002113 }
2114 }
2115}
2116
2117void Context::detachTexture(GLuint texture)
2118{
2119 // [OpenGL ES 2.0.24] section 3.8 page 84:
2120 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2121 // rebound to texture object zero
2122
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002123 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002124 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002125 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002126 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002127 if (samplerTexture[type][sampler] == texture)
2128 {
2129 samplerTexture[type][sampler] = 0;
2130 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002131 }
2132 }
2133
2134 // [OpenGL ES 2.0.24] section 4.4 page 112:
2135 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2136 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2137 // image was attached in the currently bound framebuffer.
2138
2139 Framebuffer *framebuffer = getFramebuffer();
2140
2141 if (framebuffer)
2142 {
2143 framebuffer->detachTexture(texture);
2144 }
2145}
2146
2147void Context::detachFramebuffer(GLuint framebuffer)
2148{
2149 // [OpenGL ES 2.0.24] section 4.4 page 107:
2150 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2151 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2152
2153 if (this->framebuffer == framebuffer)
2154 {
2155 bindFramebuffer(0);
2156 }
2157}
2158
2159void Context::detachRenderbuffer(GLuint renderbuffer)
2160{
2161 // [OpenGL ES 2.0.24] section 4.4 page 109:
2162 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2163 // had been executed with the target RENDERBUFFER and name of zero.
2164
2165 if (this->renderbuffer == renderbuffer)
2166 {
2167 bindRenderbuffer(0);
2168 }
2169
2170 // [OpenGL ES 2.0.24] section 4.4 page 111:
2171 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2172 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2173 // point to which this image was attached in the currently bound framebuffer.
2174
2175 Framebuffer *framebuffer = getFramebuffer();
2176
2177 if (framebuffer)
2178 {
2179 framebuffer->detachRenderbuffer(renderbuffer);
2180 }
2181}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002182
2183Texture *Context::getIncompleteTexture(SamplerType type)
2184{
2185 Texture *t = mIncompleteTextures[type];
2186
2187 if (t == NULL)
2188 {
2189 static const GLubyte color[] = { 0, 0, 0, 255 };
2190
2191 switch (type)
2192 {
2193 default:
2194 UNREACHABLE();
2195 // default falls through to SAMPLER_2D
2196
2197 case SAMPLER_2D:
2198 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002199 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002200 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002201 t = incomplete2d;
2202 }
2203 break;
2204
2205 case SAMPLER_CUBE:
2206 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002207 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002208
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002209 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2210 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2211 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2212 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2213 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2214 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002215
2216 t = incompleteCube;
2217 }
2218 break;
2219 }
2220
2221 mIncompleteTextures[type] = t;
2222 }
2223
2224 return t;
2225}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002226
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002227bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002228{
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002229 return cullFace && cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002230}
2231
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002232bool Context::isTriangleMode(GLenum drawMode)
2233{
2234 switch (drawMode)
2235 {
2236 case GL_TRIANGLES:
2237 case GL_TRIANGLE_FAN:
2238 case GL_TRIANGLE_STRIP:
2239 return true;
2240 case GL_POINTS:
2241 case GL_LINES:
2242 case GL_LINE_LOOP:
2243 case GL_LINE_STRIP:
2244 return false;
2245 default: UNREACHABLE();
2246 }
2247
2248 return false;
2249}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002250
2251void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2252{
2253 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2254
2255 vertexAttribute[index].mCurrentValue[0] = values[0];
2256 vertexAttribute[index].mCurrentValue[1] = values[1];
2257 vertexAttribute[index].mCurrentValue[2] = values[2];
2258 vertexAttribute[index].mCurrentValue[3] = values[3];
2259
2260 mVertexDataManager->dirtyCurrentValues();
2261}
2262
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002263}
2264
2265extern "C"
2266{
2267gl::Context *glCreateContext(const egl::Config *config)
2268{
2269 return new gl::Context(config);
2270}
2271
2272void glDestroyContext(gl::Context *context)
2273{
2274 delete context;
2275
2276 if (context == gl::getContext())
2277 {
2278 gl::makeCurrent(NULL, NULL, NULL);
2279 }
2280}
2281
2282void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2283{
2284 gl::makeCurrent(context, display, surface);
2285}
2286
2287gl::Context *glGetCurrentContext()
2288{
2289 return gl::getContext();
2290}
2291}