blob: 282d874183166c031ff97f7f9f8fa595a2cbe487 [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.comfab5a1a2010-03-11 19:22:30 +000010#include "Context.h"
daniel@transgaming.com16973022010-03-11 19:22:19 +000011
12#include <algorithm>
13
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000014#include "main.h"
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000015#include "libEGL/Display.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000016#include "Buffer.h"
17#include "Shader.h"
18#include "Program.h"
19#include "Texture.h"
20#include "FrameBuffer.h"
21#include "RenderBuffer.h"
22#include "mathutil.h"
23#include "utilities.h"
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000024#include "geometry/backend.h"
25#include "geometry/VertexDataManager.h"
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000026#include "geometry/IndexDataManager.h"
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000027#include "geometry/dx9.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000028
daniel@transgaming.com86487c22010-03-11 19:41:43 +000029#undef near
30#undef far
31
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032namespace gl
33{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000034Context::Context(const egl::Config *config)
35 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036{
37 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
38 depthClearValue = 1.0f;
39 stencilClearValue = 0;
40
41 cullFace = false;
42 cullMode = GL_BACK;
43 frontFace = GL_CCW;
44 depthTest = false;
45 depthFunc = GL_LESS;
46 blend = false;
47 sourceBlendRGB = GL_ONE;
48 sourceBlendAlpha = GL_ONE;
49 destBlendRGB = GL_ZERO;
50 destBlendAlpha = GL_ZERO;
51 blendEquationRGB = GL_FUNC_ADD;
52 blendEquationAlpha = GL_FUNC_ADD;
53 blendColor.red = 0;
54 blendColor.green = 0;
55 blendColor.blue = 0;
56 blendColor.alpha = 0;
57 stencilTest = false;
58 stencilFunc = GL_ALWAYS;
59 stencilRef = 0;
60 stencilMask = -1;
61 stencilWritemask = -1;
62 stencilBackFunc = GL_ALWAYS;
63 stencilBackRef = 0;
64 stencilBackMask = - 1;
65 stencilBackWritemask = -1;
66 stencilFail = GL_KEEP;
67 stencilPassDepthFail = GL_KEEP;
68 stencilPassDepthPass = GL_KEEP;
69 stencilBackFail = GL_KEEP;
70 stencilBackPassDepthFail = GL_KEEP;
71 stencilBackPassDepthPass = GL_KEEP;
72 polygonOffsetFill = false;
73 sampleAlphaToCoverage = false;
74 sampleCoverage = false;
75 sampleCoverageValue = 1.0f;
76 sampleCoverageInvert = GL_FALSE;
77 scissorTest = false;
78 dither = true;
daniel@transgaming.com5949aa12010-03-21 04:31:15 +000079 generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000080
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000081 lineWidth = 1.0f;
82
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083 viewportX = 0;
84 viewportY = 0;
85 viewportWidth = config->mDisplayMode.Width;
86 viewportHeight = config->mDisplayMode.Height;
87 zNear = 0.0f;
88 zFar = 1.0f;
89
90 scissorX = 0;
91 scissorY = 0;
92 scissorWidth = config->mDisplayMode.Width;
93 scissorHeight = config->mDisplayMode.Height;
94
95 colorMaskRed = true;
96 colorMaskGreen = true;
97 colorMaskBlue = true;
98 colorMaskAlpha = true;
99 depthMask = true;
100
101 // [OpenGL ES 2.0.24] section 3.7 page 83:
102 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
103 // and cube map texture state vectors respectively associated with them.
104 // In order that access to these initial textures not be lost, they are treated as texture
105 // objects all of whose names are 0.
106
107 mTexture2DZero = new Texture2D();
108 mTextureCubeMapZero = new TextureCubeMap();
109
110 mColorbufferZero = NULL;
111 mDepthbufferZero = NULL;
112 mStencilbufferZero = NULL;
113
114 activeSampler = 0;
115 arrayBuffer = 0;
116 elementArrayBuffer = 0;
117 bindTextureCubeMap(0);
118 bindTexture2D(0);
119 bindFramebuffer(0);
120 bindRenderbuffer(0);
121
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000122 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000124 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
125 {
126 samplerTexture[type][sampler] = 0;
127 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128 }
129
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000130 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
131 {
132 mIncompleteTextures[type] = NULL;
133 }
134
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135 currentProgram = 0;
136
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000137 packAlignment = 4;
138 unpackAlignment = 4;
139
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000140 mBufferBackEnd = NULL;
141 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000142 mIndexDataManager = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000143
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144 mInvalidEnum = false;
145 mInvalidValue = false;
146 mInvalidOperation = false;
147 mOutOfMemory = false;
148 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000149
150 mHasBeenCurrent = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151}
152
153Context::~Context()
154{
155 currentProgram = 0;
156
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000157 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
158 {
159 delete mIncompleteTextures[type];
160 }
161
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162 delete mTexture2DZero;
163 delete mTextureCubeMapZero;
164
165 delete mColorbufferZero;
166 delete mDepthbufferZero;
167 delete mStencilbufferZero;
168
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000169 delete mBufferBackEnd;
170 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000171 delete mIndexDataManager;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000172
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173 while (!mBufferMap.empty())
174 {
175 deleteBuffer(mBufferMap.begin()->first);
176 }
177
178 while (!mProgramMap.empty())
179 {
180 deleteProgram(mProgramMap.begin()->first);
181 }
182
183 while (!mShaderMap.empty())
184 {
185 deleteShader(mShaderMap.begin()->first);
186 }
187
188 while (!mFramebufferMap.empty())
189 {
190 deleteFramebuffer(mFramebufferMap.begin()->first);
191 }
192
193 while (!mRenderbufferMap.empty())
194 {
195 deleteRenderbuffer(mRenderbufferMap.begin()->first);
196 }
197
198 while (!mTextureMap.empty())
199 {
200 deleteTexture(mTextureMap.begin()->first);
201 }
202}
203
204void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
205{
206 IDirect3DDevice9 *device = display->getDevice();
207
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000208 if (!mBufferBackEnd)
209 {
210 mBufferBackEnd = new Dx9BackEnd(device);
211 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000212 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000213 }
214
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
216 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000217 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218
219 Framebuffer *framebufferZero = new Framebuffer();
220 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000221 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
222 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223
224 setFramebufferZero(framebufferZero);
225 setColorbufferZero(colorbufferZero);
226 setDepthbufferZero(depthbufferZero);
227 setStencilbufferZero(stencilbufferZero);
228
229 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
230 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
231 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
232
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000233 if(!mHasBeenCurrent)
234 {
235 viewportX = 0;
236 viewportY = 0;
237 viewportWidth = surface->getWidth();
238 viewportHeight = surface->getHeight();
239
240 scissorX = 0;
241 scissorY = 0;
242 scissorWidth = surface->getWidth();
243 scissorHeight = surface->getHeight();
244
245 mHasBeenCurrent = true;
246 }
247
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248 defaultRenderTarget->Release();
249
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000250 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000252 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000254
255 D3DCAPS9 capabilities;
256 device->GetDeviceCaps(&capabilities);
257
258 if (capabilities.PixelShaderVersion == D3DPS_VERSION(3, 0))
259 {
260 mPsProfile = "ps_3_0";
261 mVsProfile = "vs_3_0";
262 }
263 else // egl::Display guarantees support for at least 2.0
264 {
265 mPsProfile = "ps_2_0";
266 mVsProfile = "vs_2_0";
267 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268}
269
270void Context::setClearColor(float red, float green, float blue, float alpha)
271{
272 colorClearValue.red = red;
273 colorClearValue.green = green;
274 colorClearValue.blue = blue;
275 colorClearValue.alpha = alpha;
276}
277
278void Context::setClearDepth(float depth)
279{
280 depthClearValue = depth;
281}
282
283void Context::setClearStencil(int stencil)
284{
285 stencilClearValue = stencil;
286}
287
288// Returns an unused buffer name
289GLuint Context::createBuffer()
290{
291 unsigned int handle = 1;
292
293 while (mBufferMap.find(handle) != mBufferMap.end())
294 {
295 handle++;
296 }
297
298 mBufferMap[handle] = NULL;
299
300 return handle;
301}
302
303// Returns an unused shader/program name
304GLuint Context::createShader(GLenum type)
305{
306 unsigned int handle = 1;
307
308 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
309 {
310 handle++;
311 }
312
313 if (type == GL_VERTEX_SHADER)
314 {
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000315 mShaderMap[handle] = new VertexShader(handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000316 }
317 else if (type == GL_FRAGMENT_SHADER)
318 {
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000319 mShaderMap[handle] = new FragmentShader(handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320 }
321 else UNREACHABLE();
322
323 return handle;
324}
325
326// Returns an unused program/shader name
327GLuint Context::createProgram()
328{
329 unsigned int handle = 1;
330
331 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
332 {
333 handle++;
334 }
335
336 mProgramMap[handle] = new Program();
337
338 return handle;
339}
340
341// Returns an unused texture name
342GLuint Context::createTexture()
343{
344 unsigned int handle = 1;
345
346 while (mTextureMap.find(handle) != mTextureMap.end())
347 {
348 handle++;
349 }
350
351 mTextureMap[handle] = NULL;
352
353 return handle;
354}
355
356// Returns an unused framebuffer name
357GLuint Context::createFramebuffer()
358{
359 unsigned int handle = 1;
360
361 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
362 {
363 handle++;
364 }
365
366 mFramebufferMap[handle] = NULL;
367
368 return handle;
369}
370
371// Returns an unused renderbuffer name
372GLuint Context::createRenderbuffer()
373{
374 unsigned int handle = 1;
375
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000376 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000377 {
378 handle++;
379 }
380
381 mRenderbufferMap[handle] = NULL;
382
383 return handle;
384}
385
386void Context::deleteBuffer(GLuint buffer)
387{
388 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
389
390 if (bufferObject != mBufferMap.end())
391 {
392 detachBuffer(buffer);
393
394 delete bufferObject->second;
395 mBufferMap.erase(bufferObject);
396 }
397}
398
399void Context::deleteShader(GLuint shader)
400{
401 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
402
403 if (shaderObject != mShaderMap.end())
404 {
405 if (!shaderObject->second->isAttached())
406 {
407 delete shaderObject->second;
408 mShaderMap.erase(shaderObject);
409 }
410 else
411 {
412 shaderObject->second->flagForDeletion();
413 }
414 }
415}
416
417void Context::deleteProgram(GLuint program)
418{
419 ProgramMap::iterator programObject = mProgramMap.find(program);
420
421 if (programObject != mProgramMap.end())
422 {
423 if (program != currentProgram)
424 {
425 delete programObject->second;
426 mProgramMap.erase(programObject);
427 }
428 else
429 {
430 programObject->second->flagForDeletion();
431 }
432 }
433}
434
435void Context::deleteTexture(GLuint texture)
436{
437 TextureMap::iterator textureObject = mTextureMap.find(texture);
438
439 if (textureObject != mTextureMap.end())
440 {
441 detachTexture(texture);
442
443 if (texture != 0)
444 {
445 delete textureObject->second;
446 }
447
448 mTextureMap.erase(textureObject);
449 }
450}
451
452void Context::deleteFramebuffer(GLuint framebuffer)
453{
454 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
455
456 if (framebufferObject != mFramebufferMap.end())
457 {
458 detachFramebuffer(framebuffer);
459
460 delete framebufferObject->second;
461 mFramebufferMap.erase(framebufferObject);
462 }
463}
464
465void Context::deleteRenderbuffer(GLuint renderbuffer)
466{
467 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
468
469 if (renderbufferObject != mRenderbufferMap.end())
470 {
471 detachRenderbuffer(renderbuffer);
472
473 delete renderbufferObject->second;
474 mRenderbufferMap.erase(renderbufferObject);
475 }
476}
477
478void Context::bindArrayBuffer(unsigned int buffer)
479{
480 if (buffer != 0 && !getBuffer(buffer))
481 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000482 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000483 }
484
485 arrayBuffer = buffer;
486}
487
488void Context::bindElementArrayBuffer(unsigned int buffer)
489{
490 if (buffer != 0 && !getBuffer(buffer))
491 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000492 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000493 }
494
495 elementArrayBuffer = buffer;
496}
497
498void Context::bindTexture2D(GLuint texture)
499{
500 if (!getTexture(texture) || texture == 0)
501 {
502 if (texture != 0)
503 {
504 mTextureMap[texture] = new Texture2D();
505 }
506 else // Special case: 0 refers to different initial textures based on the target
507 {
508 mTextureMap[0] = mTexture2DZero;
509 }
510 }
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{
519 if (!getTexture(texture) || texture == 0)
520 {
521 if (texture != 0)
522 {
523 mTextureMap[texture] = new TextureCubeMap();
524 }
525 else // Special case: 0 refers to different initial textures based on the target
526 {
527 mTextureMap[0] = mTextureCubeMapZero;
528 }
529 }
530
531 textureCubeMap = texture;
532
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000533 samplerTexture[SAMPLER_CUBE][activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000534}
535
536void Context::bindFramebuffer(GLuint framebuffer)
537{
538 if (!getFramebuffer(framebuffer))
539 {
540 mFramebufferMap[framebuffer] = new Framebuffer();
541 }
542
543 this->framebuffer = framebuffer;
544}
545
546void Context::bindRenderbuffer(GLuint renderbuffer)
547{
548 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
549 {
550 mRenderbufferMap[renderbuffer] = new Renderbuffer();
551 }
552
553 this->renderbuffer = renderbuffer;
554}
555
556void Context::useProgram(GLuint program)
557{
558 Program *programObject = getCurrentProgram();
559
560 if (programObject && programObject->isFlaggedForDeletion())
561 {
562 deleteProgram(currentProgram);
563 }
564
565 currentProgram = program;
566}
567
568void Context::setFramebufferZero(Framebuffer *buffer)
569{
570 delete mFramebufferMap[0];
571 mFramebufferMap[0] = buffer;
572}
573
574void Context::setColorbufferZero(Colorbuffer *buffer)
575{
576 delete mColorbufferZero;
577 mColorbufferZero = buffer;
578}
579
580void Context::setDepthbufferZero(Depthbuffer *buffer)
581{
582 delete mDepthbufferZero;
583 mDepthbufferZero = buffer;
584}
585
586void Context::setStencilbufferZero(Stencilbuffer *buffer)
587{
588 delete mStencilbufferZero;
589 mStencilbufferZero = buffer;
590}
591
592void Context::setRenderbuffer(Renderbuffer *buffer)
593{
594 delete mRenderbufferMap[renderbuffer];
595 mRenderbufferMap[renderbuffer] = buffer;
596}
597
598Buffer *Context::getBuffer(unsigned int handle)
599{
600 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000601
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000602 if (buffer == mBufferMap.end())
603 {
604 return NULL;
605 }
606 else
607 {
608 return buffer->second;
609 }
610}
611
612Shader *Context::getShader(unsigned int handle)
613{
614 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000615
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000616 if (shader == mShaderMap.end())
617 {
618 return NULL;
619 }
620 else
621 {
622 return shader->second;
623 }
624}
625
626Program *Context::getProgram(unsigned int handle)
627{
628 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000629
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000630 if (program == mProgramMap.end())
631 {
632 return NULL;
633 }
634 else
635 {
636 return program->second;
637 }
638}
639
640Texture *Context::getTexture(unsigned int handle)
641{
642 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000643
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000644 if (texture == mTextureMap.end())
645 {
646 return NULL;
647 }
648 else
649 {
650 return texture->second;
651 }
652}
653
654Framebuffer *Context::getFramebuffer(unsigned int handle)
655{
656 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000657
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000658 if (framebuffer == mFramebufferMap.end())
659 {
660 return NULL;
661 }
662 else
663 {
664 return framebuffer->second;
665 }
666}
667
668Renderbuffer *Context::getRenderbuffer(unsigned int handle)
669{
670 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000671
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000672 if (renderbuffer == mRenderbufferMap.end())
673 {
674 return NULL;
675 }
676 else
677 {
678 return renderbuffer->second;
679 }
680}
681
682Colorbuffer *Context::getColorbuffer(GLuint handle)
683{
684 if (handle != 0)
685 {
686 Renderbuffer *renderbuffer = getRenderbuffer(handle);
687
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000688 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000689 {
690 return static_cast<Colorbuffer*>(renderbuffer);
691 }
692 }
693 else // Special case: 0 refers to different initial render targets based on the attachment type
694 {
695 return mColorbufferZero;
696 }
697
698 return NULL;
699}
700
701Depthbuffer *Context::getDepthbuffer(GLuint handle)
702{
703 if (handle != 0)
704 {
705 Renderbuffer *renderbuffer = getRenderbuffer(handle);
706
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000707 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000708 {
709 return static_cast<Depthbuffer*>(renderbuffer);
710 }
711 }
712 else // Special case: 0 refers to different initial render targets based on the attachment type
713 {
714 return mDepthbufferZero;
715 }
716
717 return NULL;
718}
719
720Stencilbuffer *Context::getStencilbuffer(GLuint handle)
721{
722 if (handle != 0)
723 {
724 Renderbuffer *renderbuffer = getRenderbuffer(handle);
725
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000726 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000727 {
728 return static_cast<Stencilbuffer*>(renderbuffer);
729 }
730 }
731 else
732 {
733 return mStencilbufferZero;
734 }
735
736 return NULL;
737}
738
739Buffer *Context::getArrayBuffer()
740{
741 return getBuffer(arrayBuffer);
742}
743
744Buffer *Context::getElementArrayBuffer()
745{
746 return getBuffer(elementArrayBuffer);
747}
748
749Program *Context::getCurrentProgram()
750{
751 return getProgram(currentProgram);
752}
753
754Texture2D *Context::getTexture2D()
755{
756 if (texture2D == 0) // Special case: 0 refers to different initial textures based on the target
757 {
758 return mTexture2DZero;
759 }
760
761 return (Texture2D*)getTexture(texture2D);
762}
763
764TextureCubeMap *Context::getTextureCubeMap()
765{
766 if (textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
767 {
768 return mTextureCubeMapZero;
769 }
770
771 return (TextureCubeMap*)getTexture(textureCubeMap);
772}
773
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000774Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000775{
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000776 return getTexture(samplerTexture[type][sampler]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000777}
778
779Framebuffer *Context::getFramebuffer()
780{
781 return getFramebuffer(framebuffer);
782}
783
784// Applies the render target surface, depth stencil surface, viewport rectangle and
785// scissor rectangle to the Direct3D 9 device
786bool Context::applyRenderTarget(bool ignoreViewport)
787{
788 IDirect3DDevice9 *device = getDevice();
789 Framebuffer *framebufferObject = getFramebuffer();
790
791 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
792 {
793 return false;
794 }
795
796 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
797 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
798
799 device->SetRenderTarget(0, renderTarget);
800 device->SetDepthStencilSurface(depthStencil);
801
802 D3DVIEWPORT9 viewport;
803 D3DSURFACE_DESC desc;
804 renderTarget->GetDesc(&desc);
805
806 if (ignoreViewport)
807 {
808 viewport.X = 0;
809 viewport.Y = 0;
810 viewport.Width = desc.Width;
811 viewport.Height = desc.Height;
812 viewport.MinZ = 0.0f;
813 viewport.MaxZ = 1.0f;
814 }
815 else
816 {
daniel@transgaming.com16973022010-03-11 19:22:19 +0000817 viewport.X = std::max(viewportX, 0);
818 viewport.Y = std::max(viewportY, 0);
819 viewport.Width = std::min(viewportWidth, (int)desc.Width - (int)viewport.X);
820 viewport.Height = std::min(viewportHeight, (int)desc.Height - (int)viewport.Y);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000821 viewport.MinZ = clamp01(zNear);
822 viewport.MaxZ = clamp01(zFar);
823 }
824
825 device->SetViewport(&viewport);
826
827 if (scissorTest)
828 {
829 RECT rect = {scissorX,
830 scissorY,
831 scissorX + scissorWidth,
832 scissorY + scissorHeight};
833
834 device->SetScissorRect(&rect);
835 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
836 }
837 else
838 {
839 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
840 }
841
842 if (currentProgram)
843 {
844 D3DSURFACE_DESC description;
845 renderTarget->GetDesc(&description);
846 Program *programObject = getCurrentProgram();
847
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000848 GLint halfPixelSize = programObject->getUniformLocation("gl_HalfPixelSize");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000849 GLfloat xy[2] = {1.0f / description.Width, 1.0f / description.Height};
850 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000851
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000852 GLint window = programObject->getUniformLocation("gl_Window");
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000853 GLfloat whxy[4] = {viewportWidth / 2.0f, viewportHeight / 2.0f, (float)viewportX + viewportWidth / 2.0f, (float)viewportY + viewportHeight / 2.0f};
854 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
855
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000856 GLint depth = programObject->getUniformLocation("gl_Depth");
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000857 GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
858 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
859
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000860 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000861 programObject->setUniform1fv(near, 1, &zNear);
862
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000863 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000864 programObject->setUniform1fv(far, 1, &zFar);
865
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000866 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000867 GLfloat zDiff = zFar - zNear;
868 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000869 }
870
871 return true;
872}
873
874// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
875void Context::applyState()
876{
877 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000878 Program *programObject = getCurrentProgram();
879
880 GLint frontCCW = programObject->getUniformLocation("__frontCCW");
881 GLint ccw = (frontFace == GL_CCW);
882 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000883
884 if (cullFace)
885 {
886 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(cullMode, frontFace));
887 }
888 else
889 {
890 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
891 }
892
893 if (depthTest)
894 {
895 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
896 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(depthFunc));
897 }
898 else
899 {
900 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
901 }
902
903 if (blend)
904 {
905 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
906
907 if (sourceBlendRGB != GL_CONSTANT_ALPHA && sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
908 destBlendRGB != GL_CONSTANT_ALPHA && destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
909 {
910 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(blendColor));
911 }
912 else
913 {
914 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(blendColor.alpha),
915 unorm<8>(blendColor.alpha),
916 unorm<8>(blendColor.alpha),
917 unorm<8>(blendColor.alpha)));
918 }
919
920 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(sourceBlendRGB));
921 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(destBlendRGB));
922 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(blendEquationRGB));
923
924 if (sourceBlendRGB != sourceBlendAlpha || destBlendRGB != destBlendAlpha || blendEquationRGB != blendEquationAlpha)
925 {
926 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
927
928 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(sourceBlendAlpha));
929 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(destBlendAlpha));
930 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(blendEquationAlpha));
931
932 }
933 else
934 {
935 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
936 }
937 }
938 else
939 {
940 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
941 }
942
943 if (stencilTest)
944 {
945 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
946 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
947
948 // FIXME: Unsupported by D3D9
949 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
950 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
951 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
daniel@transgaming.com1436e262010-03-17 03:58:56 +0000952 if(stencilWritemask != stencilBackWritemask || stencilRef != stencilBackRef || stencilMask != stencilBackMask)
953 {
954 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
955 return error(GL_INVALID_OPERATION);
956 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000957
958 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWritemask);
959 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilFunc));
960
961 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilRef); // FIXME: Clamp to range
962 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
963
964 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilFail));
965 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilPassDepthFail));
966 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilPassDepthPass));
967
968 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWritemask);
969 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilBackFunc));
970
971 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilBackRef); // FIXME: Clamp to range
972 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilBackMask);
973
974 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilBackFail));
975 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilBackPassDepthFail));
976 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilBackPassDepthPass));
977 }
978 else
979 {
980 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
981 }
982
983 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(colorMaskRed, colorMaskGreen, colorMaskBlue, colorMaskAlpha));
984 device->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
985
986 if (polygonOffsetFill)
987 {
988 UNIMPLEMENTED(); // FIXME
989 }
990
991 if (sampleAlphaToCoverage)
992 {
993 UNIMPLEMENTED(); // FIXME
994 }
995
996 if (sampleCoverage)
997 {
998 UNIMPLEMENTED(); // FIXME: Ignore when SAMPLE_BUFFERS is not one
999 }
1000
1001 device->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
1002}
1003
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001004// Fill in the programAttribute field of the array of TranslatedAttributes based on the active GLSL program.
1005void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001006{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001007 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001008 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001009 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001010 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001011 attributes[i].programAttribute = getCurrentProgram()->getInputMapping(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001012 }
1013 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001014}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001015
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001016// The indices parameter to glDrawElements can have two interpretations:
1017// - as a pointer into client memory
1018// - as an offset into the current GL_ELEMENT_ARRAY_BUFFER buffer
1019// Handle these cases here and return a pointer to the index data.
1020const Index *Context::adjustIndexPointer(const void *indices)
1021{
1022 if (elementArrayBuffer)
1023 {
1024 Buffer *buffer = getBuffer(elementArrayBuffer);
1025 return reinterpret_cast<const Index*>(static_cast<unsigned char*>(buffer->data()) + reinterpret_cast<GLsizei>(indices));
1026 }
1027 else
1028 {
1029 return static_cast<const Index*>(indices);
1030 }
1031}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001032
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001033void Context::applyVertexBuffer(GLint first, GLsizei count)
1034{
1035 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1036
1037 mVertexDataManager->preRenderValidate(first, count, translated);
1038
1039 lookupAttributeMapping(translated);
1040
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001041 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001042}
1043
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001044void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001045{
1046 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1047
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001048 mVertexDataManager->preRenderValidate(indexInfo, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001049
1050 lookupAttributeMapping(translated);
1051
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001052 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001053}
1054
1055// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001056TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001057{
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001058 TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(elementArrayBuffer), indices);
1059 mBufferBackEnd->setupIndicesPreDraw(indexInfo);
1060 return indexInfo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001061}
1062
1063// Applies the shaders and shader constants to the Direct3D 9 device
1064void Context::applyShaders()
1065{
1066 IDirect3DDevice9 *device = getDevice();
1067 Program *programObject = getCurrentProgram();
1068 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1069 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1070
1071 device->SetVertexShader(vertexShader);
1072 device->SetPixelShader(pixelShader);
1073
1074 programObject->applyUniforms();
1075}
1076
1077// Applies the textures and sampler states to the Direct3D 9 device
1078void Context::applyTextures()
1079{
1080 IDirect3DDevice9 *device = getDevice();
1081 Program *programObject = getCurrentProgram();
1082
1083 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1084 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001085 int textureUnit = programObject->getSamplerMapping(sampler);
1086 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001087 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001088 SamplerType textureType = programObject->getSamplerType(sampler);
1089
1090 Texture *texture = getSamplerTexture(textureUnit, textureType);
1091
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001092 if (texture->isComplete())
1093 {
1094 GLenum wrapS = texture->getWrapS();
1095 GLenum wrapT = texture->getWrapT();
1096 GLenum minFilter = texture->getMinFilter();
1097 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001098
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001099 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1100 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001101
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001102 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1103 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1104 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1105 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1106 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001107
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001108 device->SetTexture(sampler, texture->getTexture());
1109 }
1110 else
1111 {
1112 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1113 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001114 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001115 else
1116 {
1117 device->SetTexture(sampler, NULL);
1118 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001119 }
1120}
1121
1122void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1123{
1124 Framebuffer *framebuffer = getFramebuffer();
1125 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1126 IDirect3DDevice9 *device = getDevice();
1127
1128 D3DSURFACE_DESC desc;
1129 renderTarget->GetDesc(&desc);
1130
1131 IDirect3DSurface9 *systemSurface;
1132 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1133
1134 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1135 {
1136 return error(GL_OUT_OF_MEMORY);
1137 }
1138
1139 ASSERT(SUCCEEDED(result));
1140
1141 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1142 {
1143 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1144 }
1145
1146 result = device->GetRenderTargetData(renderTarget, systemSurface);
1147
1148 if (result == D3DERR_DRIVERINTERNALERROR)
1149 {
1150 systemSurface->Release();
1151
1152 return error(GL_OUT_OF_MEMORY);
1153 }
1154
1155 if (FAILED(result))
1156 {
1157 UNREACHABLE();
1158 systemSurface->Release();
1159
1160 return; // No sensible error to generate
1161 }
1162
1163 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001164 RECT rect = {std::max(x, 0),
1165 std::max(y, 0),
1166 std::min(x + width, (int)desc.Width),
1167 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001168
1169 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1170
1171 if (FAILED(result))
1172 {
1173 UNREACHABLE();
1174 systemSurface->Release();
1175
1176 return; // No sensible error to generate
1177 }
1178
1179 unsigned char *source = (unsigned char*)lock.pBits;
1180 unsigned char *dest = (unsigned char*)pixels;
1181
1182 for (int j = 0; j < rect.bottom - rect.top; j++)
1183 {
1184 for (int i = 0; i < rect.right - rect.left; i++)
1185 {
1186 float r;
1187 float g;
1188 float b;
1189 float a;
1190
1191 switch (desc.Format)
1192 {
1193 case D3DFMT_R5G6B5:
1194 {
1195 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1196
1197 a = 1.0f;
1198 b = (rgb & 0x001F) * (1.0f / 0x001F);
1199 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1200 r = (rgb & 0xF800) * (1.0f / 0xF800);
1201 }
1202 break;
1203 case D3DFMT_X1R5G5B5:
1204 {
1205 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1206
1207 a = 1.0f;
1208 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1209 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1210 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1211 }
1212 break;
1213 case D3DFMT_A1R5G5B5:
1214 {
1215 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1216
1217 a = (argb & 0x8000) ? 1.0f : 0.0f;
1218 b = (argb & 0x001F) * (1.0f / 0x001F);
1219 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1220 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1221 }
1222 break;
1223 case D3DFMT_A8R8G8B8:
1224 {
1225 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1226
1227 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1228 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1229 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1230 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1231 }
1232 break;
1233 case D3DFMT_X8R8G8B8:
1234 {
1235 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1236
1237 a = 1.0f;
1238 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
1239 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
1240 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
1241 }
1242 break;
1243 case D3DFMT_A2R10G10B10:
1244 {
1245 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1246
1247 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
1248 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
1249 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
1250 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
1251 }
1252 break;
1253 default:
1254 UNIMPLEMENTED(); // FIXME
1255 UNREACHABLE();
1256 }
1257
1258 switch (format)
1259 {
1260 case GL_RGBA:
1261 switch (type)
1262 {
1263 case GL_UNSIGNED_BYTE:
1264 dest[4 * (i + j * width) + 0] = (unsigned char)(255 * r + 0.5f);
1265 dest[4 * (i + j * width) + 1] = (unsigned char)(255 * g + 0.5f);
1266 dest[4 * (i + j * width) + 2] = (unsigned char)(255 * b + 0.5f);
1267 dest[4 * (i + j * width) + 3] = (unsigned char)(255 * a + 0.5f);
1268 break;
1269 default: UNREACHABLE();
1270 }
1271 break;
1272 case IMPLEMENTATION_COLOR_READ_FORMAT:
1273 switch (type)
1274 {
1275 case IMPLEMENTATION_COLOR_READ_TYPE:
1276 break;
1277 default: UNREACHABLE();
1278 }
1279 break;
1280 default: UNREACHABLE();
1281 }
1282 }
1283 }
1284
1285 systemSurface->UnlockRect();
1286
1287 systemSurface->Release();
1288}
1289
1290void Context::clear(GLbitfield mask)
1291{
1292 IDirect3DDevice9 *device = getDevice();
1293 DWORD flags = 0;
1294
1295 if (mask & GL_COLOR_BUFFER_BIT)
1296 {
1297 mask &= ~GL_COLOR_BUFFER_BIT;
1298 flags |= D3DCLEAR_TARGET;
1299 }
1300
1301 if (mask & GL_DEPTH_BUFFER_BIT)
1302 {
1303 mask &= ~GL_DEPTH_BUFFER_BIT;
1304 if (depthMask)
1305 {
1306 flags |= D3DCLEAR_ZBUFFER;
1307 }
1308 }
1309
1310 Framebuffer *framebufferObject = getFramebuffer();
1311 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1312
1313 GLuint stencilUnmasked = 0x0;
1314
1315 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
1316 {
1317 D3DSURFACE_DESC desc;
1318 depthStencil->GetDesc(&desc);
1319
1320 mask &= ~GL_STENCIL_BUFFER_BIT;
1321 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
1322 stencilUnmasked = (0x1 << stencilSize) - 1;
1323
1324 if (stencilUnmasked != 0x0)
1325 {
1326 flags |= D3DCLEAR_STENCIL;
1327 }
1328 }
1329
1330 if (mask != 0)
1331 {
1332 return error(GL_INVALID_VALUE);
1333 }
1334
1335 applyRenderTarget(true); // Clips the clear to the scissor rectangle but not the viewport
1336
1337 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(colorClearValue.alpha), unorm<8>(colorClearValue.red), unorm<8>(colorClearValue.green), unorm<8>(colorClearValue.blue));
1338 float depth = clamp01(depthClearValue);
1339 int stencil = stencilClearValue & 0x000000FF;
1340
1341 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1342
1343 D3DSURFACE_DESC desc;
1344 renderTarget->GetDesc(&desc);
1345
1346 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || colorMaskAlpha;
1347
1348 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
1349 (stencilWritemask & stencilUnmasked) != stencilUnmasked;
1350 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001351 !(colorMaskRed && colorMaskGreen &&
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001352 colorMaskBlue && alphaUnmasked);
1353
1354 if (needMaskedColorClear || needMaskedStencilClear)
1355 {
1356 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
1357 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1358 device->SetRenderState(D3DRS_ZENABLE, FALSE);
1359 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1360 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
1361 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
1362 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1363 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
1364
1365 if (flags & D3DCLEAR_TARGET)
1366 {
1367 device->SetRenderState(D3DRS_COLORWRITEENABLE, (colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
1368 (colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
1369 (colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
1370 (colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
1371 }
1372 else
1373 {
1374 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1375 }
1376
1377 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
1378 {
1379 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1380 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
1381 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
1382 device->SetRenderState(D3DRS_STENCILREF, stencil);
1383 device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001384 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001385 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
1386 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
1387 }
1388 else
1389 {
1390 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1391 }
1392
1393 device->SetPixelShader(NULL);
1394 device->SetVertexShader(NULL);
1395 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1396
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001397 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001398 {
1399 float x, y, z, w;
1400 D3DCOLOR diffuse;
1401 };
1402
1403 Vertex quad[4];
1404 quad[0].x = 0.0f;
1405 quad[0].y = (float)desc.Height;
1406 quad[0].z = 0.0f;
1407 quad[0].w = 1.0f;
1408 quad[0].diffuse = color;
1409
1410 quad[1].x = (float)desc.Width;
1411 quad[1].y = (float)desc.Height;
1412 quad[1].z = 0.0f;
1413 quad[1].w = 1.0f;
1414 quad[1].diffuse = color;
1415
1416 quad[2].x = 0.0f;
1417 quad[2].y = 0.0f;
1418 quad[2].z = 0.0f;
1419 quad[2].w = 1.0f;
1420 quad[2].diffuse = color;
1421
1422 quad[3].x = (float)desc.Width;
1423 quad[3].y = 0.0f;
1424 quad[3].z = 0.0f;
1425 quad[3].w = 1.0f;
1426 quad[3].diffuse = color;
1427
1428 device->BeginScene();
1429 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
1430 device->EndScene();
1431
1432 if (flags & D3DCLEAR_ZBUFFER)
1433 {
1434 device->SetRenderState(D3DRS_ZENABLE, TRUE);
1435 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
1436 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
1437 }
1438 }
1439 else
1440 {
1441 device->Clear(0, NULL, flags, color, depth, stencil);
1442 }
1443}
1444
1445void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
1446{
1447 if (!currentProgram)
1448 {
1449 return error(GL_INVALID_OPERATION);
1450 }
1451
1452 IDirect3DDevice9 *device = getDevice();
1453 D3DPRIMITIVETYPE primitiveType;
1454 int primitiveCount;
1455
1456 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1457 return error(GL_INVALID_ENUM);
1458
1459 if (primitiveCount <= 0)
1460 {
1461 return;
1462 }
1463
1464 if (!applyRenderTarget(false))
1465 {
1466 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1467 }
1468
1469 applyState();
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001470 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001471 applyShaders();
1472 applyTextures();
1473
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001474 if (!cullSkipsDraw(mode))
1475 {
1476 device->BeginScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001477 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001478 device->EndScene();
1479 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001480}
1481
1482void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
1483{
1484 if (!currentProgram)
1485 {
1486 return error(GL_INVALID_OPERATION);
1487 }
1488
1489 if (!indices && !elementArrayBuffer)
1490 {
1491 return error(GL_INVALID_OPERATION);
1492 }
1493
1494 IDirect3DDevice9 *device = getDevice();
1495 D3DPRIMITIVETYPE primitiveType;
1496 int primitiveCount;
1497
1498 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1499 return error(GL_INVALID_ENUM);
1500
1501 if (primitiveCount <= 0)
1502 {
1503 return;
1504 }
1505
1506 if (!applyRenderTarget(false))
1507 {
1508 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1509 }
1510
1511 applyState();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001512 TranslatedIndexData indexInfo = applyIndexBuffer(indices, count, mode, type);
1513 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001514 applyShaders();
1515 applyTextures();
1516
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001517 if (!cullSkipsDraw(mode))
1518 {
1519 device->BeginScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001520 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 +00001521 device->EndScene();
1522 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001523}
1524
1525void Context::finish()
1526{
1527 IDirect3DDevice9 *device = getDevice();
1528 IDirect3DQuery9 *occlusionQuery = NULL;
1529
1530 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
1531
1532 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1533 {
1534 return error(GL_OUT_OF_MEMORY);
1535 }
1536
1537 ASSERT(SUCCEEDED(result));
1538
1539 if (occlusionQuery)
1540 {
1541 occlusionQuery->Issue(D3DISSUE_BEGIN);
1542
1543 // Render something outside the render target
1544 device->SetPixelShader(NULL);
1545 device->SetVertexShader(NULL);
1546 device->SetFVF(D3DFVF_XYZRHW);
1547 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
1548 device->BeginScene();
1549 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
1550 device->EndScene();
1551
1552 occlusionQuery->Issue(D3DISSUE_END);
1553
1554 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1555 {
1556 // Keep polling, but allow other threads to do something useful first
1557 Sleep(0);
1558 }
1559
1560 occlusionQuery->Release();
1561 }
1562}
1563
1564void Context::flush()
1565{
1566 IDirect3DDevice9 *device = getDevice();
1567 IDirect3DQuery9 *eventQuery = NULL;
1568
1569 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
1570
1571 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1572 {
1573 return error(GL_OUT_OF_MEMORY);
1574 }
1575
1576 ASSERT(SUCCEEDED(result));
1577
1578 if (eventQuery)
1579 {
1580 eventQuery->Issue(D3DISSUE_END);
1581
1582 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1583 {
1584 // Keep polling, but allow other threads to do something useful first
1585 Sleep(0);
1586 }
1587
1588 eventQuery->Release();
1589 }
1590}
1591
1592void Context::recordInvalidEnum()
1593{
1594 mInvalidEnum = true;
1595}
1596
1597void Context::recordInvalidValue()
1598{
1599 mInvalidValue = true;
1600}
1601
1602void Context::recordInvalidOperation()
1603{
1604 mInvalidOperation = true;
1605}
1606
1607void Context::recordOutOfMemory()
1608{
1609 mOutOfMemory = true;
1610}
1611
1612void Context::recordInvalidFramebufferOperation()
1613{
1614 mInvalidFramebufferOperation = true;
1615}
1616
1617// Get one of the recorded errors and clear its flag, if any.
1618// [OpenGL ES 2.0.24] section 2.5 page 13.
1619GLenum Context::getError()
1620{
1621 if (mInvalidEnum)
1622 {
1623 mInvalidEnum = false;
1624
1625 return GL_INVALID_ENUM;
1626 }
1627
1628 if (mInvalidValue)
1629 {
1630 mInvalidValue = false;
1631
1632 return GL_INVALID_VALUE;
1633 }
1634
1635 if (mInvalidOperation)
1636 {
1637 mInvalidOperation = false;
1638
1639 return GL_INVALID_OPERATION;
1640 }
1641
1642 if (mOutOfMemory)
1643 {
1644 mOutOfMemory = false;
1645
1646 return GL_OUT_OF_MEMORY;
1647 }
1648
1649 if (mInvalidFramebufferOperation)
1650 {
1651 mInvalidFramebufferOperation = false;
1652
1653 return GL_INVALID_FRAMEBUFFER_OPERATION;
1654 }
1655
1656 return GL_NO_ERROR;
1657}
1658
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00001659const char *Context::getPixelShaderProfile()
1660{
1661 return mPsProfile;
1662}
1663
1664const char *Context::getVertexShaderProfile()
1665{
1666 return mVsProfile;
1667}
1668
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001669void Context::detachBuffer(GLuint buffer)
1670{
1671 // [OpenGL ES 2.0.24] section 2.9 page 22:
1672 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
1673 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
1674
1675 if (arrayBuffer == buffer)
1676 {
1677 arrayBuffer = 0;
1678 }
1679
1680 if (elementArrayBuffer == buffer)
1681 {
1682 elementArrayBuffer = 0;
1683 }
1684
1685 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
1686 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001687 if (vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001688 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001689 vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001690 }
1691 }
1692}
1693
1694void Context::detachTexture(GLuint texture)
1695{
1696 // [OpenGL ES 2.0.24] section 3.8 page 84:
1697 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
1698 // rebound to texture object zero
1699
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001700 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001701 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001702 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001703 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001704 if (samplerTexture[type][sampler] == texture)
1705 {
1706 samplerTexture[type][sampler] = 0;
1707 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001708 }
1709 }
1710
1711 // [OpenGL ES 2.0.24] section 4.4 page 112:
1712 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
1713 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
1714 // image was attached in the currently bound framebuffer.
1715
1716 Framebuffer *framebuffer = getFramebuffer();
1717
1718 if (framebuffer)
1719 {
1720 framebuffer->detachTexture(texture);
1721 }
1722}
1723
1724void Context::detachFramebuffer(GLuint framebuffer)
1725{
1726 // [OpenGL ES 2.0.24] section 4.4 page 107:
1727 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
1728 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
1729
1730 if (this->framebuffer == framebuffer)
1731 {
1732 bindFramebuffer(0);
1733 }
1734}
1735
1736void Context::detachRenderbuffer(GLuint renderbuffer)
1737{
1738 // [OpenGL ES 2.0.24] section 4.4 page 109:
1739 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
1740 // had been executed with the target RENDERBUFFER and name of zero.
1741
1742 if (this->renderbuffer == renderbuffer)
1743 {
1744 bindRenderbuffer(0);
1745 }
1746
1747 // [OpenGL ES 2.0.24] section 4.4 page 111:
1748 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
1749 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
1750 // point to which this image was attached in the currently bound framebuffer.
1751
1752 Framebuffer *framebuffer = getFramebuffer();
1753
1754 if (framebuffer)
1755 {
1756 framebuffer->detachRenderbuffer(renderbuffer);
1757 }
1758}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001759
1760Texture *Context::getIncompleteTexture(SamplerType type)
1761{
1762 Texture *t = mIncompleteTextures[type];
1763
1764 if (t == NULL)
1765 {
1766 static const GLubyte color[] = { 0, 0, 0, 255 };
1767
1768 switch (type)
1769 {
1770 default:
1771 UNREACHABLE();
1772 // default falls through to SAMPLER_2D
1773
1774 case SAMPLER_2D:
1775 {
1776 Texture2D *incomplete2d = new Texture2D;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001777 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001778 t = incomplete2d;
1779 }
1780 break;
1781
1782 case SAMPLER_CUBE:
1783 {
1784 TextureCubeMap *incompleteCube = new TextureCubeMap;
1785
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001786 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1787 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1788 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1789 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1790 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1791 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001792
1793 t = incompleteCube;
1794 }
1795 break;
1796 }
1797
1798 mIncompleteTextures[type] = t;
1799 }
1800
1801 return t;
1802}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001803
1804bool Context::cullSkipsDraw(GLenum primitiveType)
1805{
1806 if (cullFace && cullMode == GL_FRONT_AND_BACK &&
1807 (primitiveType == GL_TRIANGLES || primitiveType == GL_TRIANGLE_FAN || primitiveType == GL_TRIANGLE_STRIP))
1808 {
1809 return true;
1810 }
1811 else
1812 {
1813 return false;
1814 }
1815}
1816
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001817}
1818
1819extern "C"
1820{
1821gl::Context *glCreateContext(const egl::Config *config)
1822{
1823 return new gl::Context(config);
1824}
1825
1826void glDestroyContext(gl::Context *context)
1827{
1828 delete context;
1829
1830 if (context == gl::getContext())
1831 {
1832 gl::makeCurrent(NULL, NULL, NULL);
1833 }
1834}
1835
1836void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
1837{
1838 gl::makeCurrent(context, display, surface);
1839}
1840
1841gl::Context *glGetCurrentContext()
1842{
1843 return gl::getContext();
1844}
1845}