blob: 42cef6359a3dd76445fe99a5351cd042895cca70 [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.comb8c28ed2010-04-13 03:26:32 +000028#include "Blit.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000029
daniel@transgaming.com86487c22010-03-11 19:41:43 +000030#undef near
31#undef far
32
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033namespace gl
34{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000035Context::Context(const egl::Config *config)
36 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000037{
38 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
39 depthClearValue = 1.0f;
40 stencilClearValue = 0;
41
42 cullFace = false;
43 cullMode = GL_BACK;
44 frontFace = GL_CCW;
45 depthTest = false;
46 depthFunc = GL_LESS;
47 blend = false;
48 sourceBlendRGB = GL_ONE;
49 sourceBlendAlpha = GL_ONE;
50 destBlendRGB = GL_ZERO;
51 destBlendAlpha = GL_ZERO;
52 blendEquationRGB = GL_FUNC_ADD;
53 blendEquationAlpha = GL_FUNC_ADD;
54 blendColor.red = 0;
55 blendColor.green = 0;
56 blendColor.blue = 0;
57 blendColor.alpha = 0;
58 stencilTest = false;
59 stencilFunc = GL_ALWAYS;
60 stencilRef = 0;
61 stencilMask = -1;
62 stencilWritemask = -1;
63 stencilBackFunc = GL_ALWAYS;
64 stencilBackRef = 0;
65 stencilBackMask = - 1;
66 stencilBackWritemask = -1;
67 stencilFail = GL_KEEP;
68 stencilPassDepthFail = GL_KEEP;
69 stencilPassDepthPass = GL_KEEP;
70 stencilBackFail = GL_KEEP;
71 stencilBackPassDepthFail = GL_KEEP;
72 stencilBackPassDepthPass = GL_KEEP;
73 polygonOffsetFill = false;
daniel@transgaming.com777f2672010-04-07 03:25:16 +000074 polygonOffsetFactor = 0.0f;
75 polygonOffsetUnits = 0.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000076 sampleAlphaToCoverage = false;
77 sampleCoverage = false;
78 sampleCoverageValue = 1.0f;
79 sampleCoverageInvert = GL_FALSE;
80 scissorTest = false;
81 dither = true;
daniel@transgaming.com5949aa12010-03-21 04:31:15 +000082 generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000084 lineWidth = 1.0f;
85
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000086 viewportX = 0;
87 viewportY = 0;
88 viewportWidth = config->mDisplayMode.Width;
89 viewportHeight = config->mDisplayMode.Height;
90 zNear = 0.0f;
91 zFar = 1.0f;
92
93 scissorX = 0;
94 scissorY = 0;
95 scissorWidth = config->mDisplayMode.Width;
96 scissorHeight = config->mDisplayMode.Height;
97
98 colorMaskRed = true;
99 colorMaskGreen = true;
100 colorMaskBlue = true;
101 colorMaskAlpha = true;
102 depthMask = true;
103
104 // [OpenGL ES 2.0.24] section 3.7 page 83:
105 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
106 // and cube map texture state vectors respectively associated with them.
107 // In order that access to these initial textures not be lost, they are treated as texture
108 // objects all of whose names are 0.
109
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000110 mTexture2DZero = new Texture2D(this);
111 mTextureCubeMapZero = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112
113 mColorbufferZero = NULL;
114 mDepthbufferZero = NULL;
115 mStencilbufferZero = NULL;
116
117 activeSampler = 0;
118 arrayBuffer = 0;
119 elementArrayBuffer = 0;
120 bindTextureCubeMap(0);
121 bindTexture2D(0);
122 bindFramebuffer(0);
123 bindRenderbuffer(0);
124
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000125 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000127 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
128 {
129 samplerTexture[type][sampler] = 0;
130 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131 }
132
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000133 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
134 {
135 mIncompleteTextures[type] = NULL;
136 }
137
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138 currentProgram = 0;
139
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000140 packAlignment = 4;
141 unpackAlignment = 4;
142
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000143 mBufferBackEnd = NULL;
144 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000145 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000146 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000147
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000148 mInvalidEnum = false;
149 mInvalidValue = false;
150 mInvalidOperation = false;
151 mOutOfMemory = false;
152 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000153
154 mHasBeenCurrent = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155}
156
157Context::~Context()
158{
159 currentProgram = 0;
160
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000161 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
162 {
163 delete mIncompleteTextures[type];
164 }
165
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166 delete mTexture2DZero;
167 delete mTextureCubeMapZero;
168
169 delete mColorbufferZero;
170 delete mDepthbufferZero;
171 delete mStencilbufferZero;
172
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000173 delete mBufferBackEnd;
174 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000175 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000176 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000177
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178 while (!mBufferMap.empty())
179 {
180 deleteBuffer(mBufferMap.begin()->first);
181 }
182
183 while (!mProgramMap.empty())
184 {
185 deleteProgram(mProgramMap.begin()->first);
186 }
187
188 while (!mShaderMap.empty())
189 {
190 deleteShader(mShaderMap.begin()->first);
191 }
192
193 while (!mFramebufferMap.empty())
194 {
195 deleteFramebuffer(mFramebufferMap.begin()->first);
196 }
197
198 while (!mRenderbufferMap.empty())
199 {
200 deleteRenderbuffer(mRenderbufferMap.begin()->first);
201 }
202
203 while (!mTextureMap.empty())
204 {
205 deleteTexture(mTextureMap.begin()->first);
206 }
207}
208
209void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
210{
211 IDirect3DDevice9 *device = display->getDevice();
212
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000213 if (!mBufferBackEnd)
214 {
215 mBufferBackEnd = new Dx9BackEnd(device);
216 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000217 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000218 mBlit = new Blit(this);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000219 }
220
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
222 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000223 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224
225 Framebuffer *framebufferZero = new Framebuffer();
226 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000227 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
228 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229
230 setFramebufferZero(framebufferZero);
231 setColorbufferZero(colorbufferZero);
232 setDepthbufferZero(depthbufferZero);
233 setStencilbufferZero(stencilbufferZero);
234
235 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
236 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
237 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
238
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000239 if(!mHasBeenCurrent)
240 {
241 viewportX = 0;
242 viewportY = 0;
243 viewportWidth = surface->getWidth();
244 viewportHeight = surface->getHeight();
245
246 scissorX = 0;
247 scissorY = 0;
248 scissorWidth = surface->getWidth();
249 scissorHeight = surface->getHeight();
250
251 mHasBeenCurrent = true;
252 }
253
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000254 defaultRenderTarget->Release();
255
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000256 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000258 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000260
261 D3DCAPS9 capabilities;
262 device->GetDeviceCaps(&capabilities);
263
264 if (capabilities.PixelShaderVersion == D3DPS_VERSION(3, 0))
265 {
266 mPsProfile = "ps_3_0";
267 mVsProfile = "vs_3_0";
268 }
269 else // egl::Display guarantees support for at least 2.0
270 {
271 mPsProfile = "ps_2_0";
272 mVsProfile = "vs_2_0";
273 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274}
275
276void Context::setClearColor(float red, float green, float blue, float alpha)
277{
278 colorClearValue.red = red;
279 colorClearValue.green = green;
280 colorClearValue.blue = blue;
281 colorClearValue.alpha = alpha;
282}
283
284void Context::setClearDepth(float depth)
285{
286 depthClearValue = depth;
287}
288
289void Context::setClearStencil(int stencil)
290{
291 stencilClearValue = stencil;
292}
293
294// Returns an unused buffer name
295GLuint Context::createBuffer()
296{
297 unsigned int handle = 1;
298
299 while (mBufferMap.find(handle) != mBufferMap.end())
300 {
301 handle++;
302 }
303
304 mBufferMap[handle] = NULL;
305
306 return handle;
307}
308
309// Returns an unused shader/program name
310GLuint Context::createShader(GLenum type)
311{
312 unsigned int handle = 1;
313
314 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
315 {
316 handle++;
317 }
318
319 if (type == GL_VERTEX_SHADER)
320 {
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000321 mShaderMap[handle] = new VertexShader(handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000322 }
323 else if (type == GL_FRAGMENT_SHADER)
324 {
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000325 mShaderMap[handle] = new FragmentShader(handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326 }
327 else UNREACHABLE();
328
329 return handle;
330}
331
332// Returns an unused program/shader name
333GLuint Context::createProgram()
334{
335 unsigned int handle = 1;
336
337 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
338 {
339 handle++;
340 }
341
342 mProgramMap[handle] = new Program();
343
344 return handle;
345}
346
347// Returns an unused texture name
348GLuint Context::createTexture()
349{
350 unsigned int handle = 1;
351
352 while (mTextureMap.find(handle) != mTextureMap.end())
353 {
354 handle++;
355 }
356
357 mTextureMap[handle] = NULL;
358
359 return handle;
360}
361
362// Returns an unused framebuffer name
363GLuint Context::createFramebuffer()
364{
365 unsigned int handle = 1;
366
367 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
368 {
369 handle++;
370 }
371
372 mFramebufferMap[handle] = NULL;
373
374 return handle;
375}
376
377// Returns an unused renderbuffer name
378GLuint Context::createRenderbuffer()
379{
380 unsigned int handle = 1;
381
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000382 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000383 {
384 handle++;
385 }
386
387 mRenderbufferMap[handle] = NULL;
388
389 return handle;
390}
391
392void Context::deleteBuffer(GLuint buffer)
393{
394 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
395
396 if (bufferObject != mBufferMap.end())
397 {
398 detachBuffer(buffer);
399
400 delete bufferObject->second;
401 mBufferMap.erase(bufferObject);
402 }
403}
404
405void Context::deleteShader(GLuint shader)
406{
407 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
408
409 if (shaderObject != mShaderMap.end())
410 {
411 if (!shaderObject->second->isAttached())
412 {
413 delete shaderObject->second;
414 mShaderMap.erase(shaderObject);
415 }
416 else
417 {
418 shaderObject->second->flagForDeletion();
419 }
420 }
421}
422
423void Context::deleteProgram(GLuint program)
424{
425 ProgramMap::iterator programObject = mProgramMap.find(program);
426
427 if (programObject != mProgramMap.end())
428 {
429 if (program != currentProgram)
430 {
431 delete programObject->second;
432 mProgramMap.erase(programObject);
433 }
434 else
435 {
436 programObject->second->flagForDeletion();
437 }
438 }
439}
440
441void Context::deleteTexture(GLuint texture)
442{
443 TextureMap::iterator textureObject = mTextureMap.find(texture);
444
445 if (textureObject != mTextureMap.end())
446 {
447 detachTexture(texture);
448
449 if (texture != 0)
450 {
451 delete textureObject->second;
452 }
453
454 mTextureMap.erase(textureObject);
455 }
456}
457
458void Context::deleteFramebuffer(GLuint framebuffer)
459{
460 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
461
462 if (framebufferObject != mFramebufferMap.end())
463 {
464 detachFramebuffer(framebuffer);
465
466 delete framebufferObject->second;
467 mFramebufferMap.erase(framebufferObject);
468 }
469}
470
471void Context::deleteRenderbuffer(GLuint renderbuffer)
472{
473 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
474
475 if (renderbufferObject != mRenderbufferMap.end())
476 {
477 detachRenderbuffer(renderbuffer);
478
479 delete renderbufferObject->second;
480 mRenderbufferMap.erase(renderbufferObject);
481 }
482}
483
484void Context::bindArrayBuffer(unsigned int buffer)
485{
486 if (buffer != 0 && !getBuffer(buffer))
487 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000488 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000489 }
490
491 arrayBuffer = buffer;
492}
493
494void Context::bindElementArrayBuffer(unsigned int buffer)
495{
496 if (buffer != 0 && !getBuffer(buffer))
497 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000498 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000499 }
500
501 elementArrayBuffer = buffer;
502}
503
504void Context::bindTexture2D(GLuint texture)
505{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000506 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000507 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000508 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000509 }
510
511 texture2D = texture;
512
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000513 samplerTexture[SAMPLER_2D][activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000514}
515
516void Context::bindTextureCubeMap(GLuint texture)
517{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000518 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000519 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000520 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000521 }
522
523 textureCubeMap = texture;
524
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000525 samplerTexture[SAMPLER_CUBE][activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000526}
527
528void Context::bindFramebuffer(GLuint framebuffer)
529{
530 if (!getFramebuffer(framebuffer))
531 {
532 mFramebufferMap[framebuffer] = new Framebuffer();
533 }
534
535 this->framebuffer = framebuffer;
536}
537
538void Context::bindRenderbuffer(GLuint renderbuffer)
539{
540 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
541 {
542 mRenderbufferMap[renderbuffer] = new Renderbuffer();
543 }
544
545 this->renderbuffer = renderbuffer;
546}
547
548void Context::useProgram(GLuint program)
549{
550 Program *programObject = getCurrentProgram();
551
552 if (programObject && programObject->isFlaggedForDeletion())
553 {
554 deleteProgram(currentProgram);
555 }
556
557 currentProgram = program;
558}
559
560void Context::setFramebufferZero(Framebuffer *buffer)
561{
562 delete mFramebufferMap[0];
563 mFramebufferMap[0] = buffer;
564}
565
566void Context::setColorbufferZero(Colorbuffer *buffer)
567{
568 delete mColorbufferZero;
569 mColorbufferZero = buffer;
570}
571
572void Context::setDepthbufferZero(Depthbuffer *buffer)
573{
574 delete mDepthbufferZero;
575 mDepthbufferZero = buffer;
576}
577
578void Context::setStencilbufferZero(Stencilbuffer *buffer)
579{
580 delete mStencilbufferZero;
581 mStencilbufferZero = buffer;
582}
583
584void Context::setRenderbuffer(Renderbuffer *buffer)
585{
586 delete mRenderbufferMap[renderbuffer];
587 mRenderbufferMap[renderbuffer] = buffer;
588}
589
590Buffer *Context::getBuffer(unsigned int handle)
591{
592 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000593
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000594 if (buffer == mBufferMap.end())
595 {
596 return NULL;
597 }
598 else
599 {
600 return buffer->second;
601 }
602}
603
604Shader *Context::getShader(unsigned int handle)
605{
606 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000607
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000608 if (shader == mShaderMap.end())
609 {
610 return NULL;
611 }
612 else
613 {
614 return shader->second;
615 }
616}
617
618Program *Context::getProgram(unsigned int handle)
619{
620 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000621
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000622 if (program == mProgramMap.end())
623 {
624 return NULL;
625 }
626 else
627 {
628 return program->second;
629 }
630}
631
632Texture *Context::getTexture(unsigned int handle)
633{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000634 if (handle == 0) return NULL;
635
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000636 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000637
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000638 if (texture == mTextureMap.end())
639 {
640 return NULL;
641 }
642 else
643 {
644 return texture->second;
645 }
646}
647
648Framebuffer *Context::getFramebuffer(unsigned int handle)
649{
650 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000651
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652 if (framebuffer == mFramebufferMap.end())
653 {
654 return NULL;
655 }
656 else
657 {
658 return framebuffer->second;
659 }
660}
661
662Renderbuffer *Context::getRenderbuffer(unsigned int handle)
663{
664 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000665
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000666 if (renderbuffer == mRenderbufferMap.end())
667 {
668 return NULL;
669 }
670 else
671 {
672 return renderbuffer->second;
673 }
674}
675
676Colorbuffer *Context::getColorbuffer(GLuint handle)
677{
678 if (handle != 0)
679 {
680 Renderbuffer *renderbuffer = getRenderbuffer(handle);
681
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000682 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000683 {
684 return static_cast<Colorbuffer*>(renderbuffer);
685 }
686 }
687 else // Special case: 0 refers to different initial render targets based on the attachment type
688 {
689 return mColorbufferZero;
690 }
691
692 return NULL;
693}
694
695Depthbuffer *Context::getDepthbuffer(GLuint handle)
696{
697 if (handle != 0)
698 {
699 Renderbuffer *renderbuffer = getRenderbuffer(handle);
700
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000701 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000702 {
703 return static_cast<Depthbuffer*>(renderbuffer);
704 }
705 }
706 else // Special case: 0 refers to different initial render targets based on the attachment type
707 {
708 return mDepthbufferZero;
709 }
710
711 return NULL;
712}
713
714Stencilbuffer *Context::getStencilbuffer(GLuint handle)
715{
716 if (handle != 0)
717 {
718 Renderbuffer *renderbuffer = getRenderbuffer(handle);
719
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000720 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000721 {
722 return static_cast<Stencilbuffer*>(renderbuffer);
723 }
724 }
725 else
726 {
727 return mStencilbufferZero;
728 }
729
730 return NULL;
731}
732
733Buffer *Context::getArrayBuffer()
734{
735 return getBuffer(arrayBuffer);
736}
737
738Buffer *Context::getElementArrayBuffer()
739{
740 return getBuffer(elementArrayBuffer);
741}
742
743Program *Context::getCurrentProgram()
744{
745 return getProgram(currentProgram);
746}
747
748Texture2D *Context::getTexture2D()
749{
750 if (texture2D == 0) // Special case: 0 refers to different initial textures based on the target
751 {
752 return mTexture2DZero;
753 }
754
755 return (Texture2D*)getTexture(texture2D);
756}
757
758TextureCubeMap *Context::getTextureCubeMap()
759{
760 if (textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
761 {
762 return mTextureCubeMapZero;
763 }
764
765 return (TextureCubeMap*)getTexture(textureCubeMap);
766}
767
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000768Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000769{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000770 GLuint texid = samplerTexture[type][sampler];
771
772 if (texid == 0)
773 {
774 switch (type)
775 {
776 default: UNREACHABLE();
777 case SAMPLER_2D: return mTexture2DZero;
778 case SAMPLER_CUBE: return mTextureCubeMapZero;
779 }
780 }
781
782 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000783}
784
785Framebuffer *Context::getFramebuffer()
786{
787 return getFramebuffer(framebuffer);
788}
789
daniel@transgaming.com777f2672010-04-07 03:25:16 +0000790bool Context::getBooleanv(GLenum pname, GLboolean *params)
791{
792 switch (pname)
793 {
794 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
795 case GL_SAMPLE_COVERAGE_INVERT: *params = sampleCoverageInvert; break;
796 case GL_DEPTH_WRITEMASK: *params = depthMask; break;
797 case GL_COLOR_WRITEMASK:
798 params[0] = colorMaskRed;
799 params[1] = colorMaskGreen;
800 params[2] = colorMaskBlue;
801 params[3] = colorMaskAlpha;
802 break;
daniel@transgaming.com79f66772010-04-13 03:26:09 +0000803 case GL_CULL_FACE: *params = cullFace;
804 case GL_POLYGON_OFFSET_FILL: *params = polygonOffsetFill;
805 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = sampleAlphaToCoverage;
806 case GL_SAMPLE_COVERAGE: *params = sampleCoverage;
807 case GL_SCISSOR_TEST: *params = scissorTest;
808 case GL_STENCIL_TEST: *params = stencilTest;
809 case GL_DEPTH_TEST: *params = depthTest;
810 case GL_BLEND: *params = blend;
811 case GL_DITHER: *params = dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +0000812 default:
813 return false;
814 }
815
816 return true;
817}
818
819bool Context::getFloatv(GLenum pname, GLfloat *params)
820{
821 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
822 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
823 // GetIntegerv as its native query function. As it would require conversion in any
824 // case, this should make no difference to the calling application.
825 switch (pname)
826 {
827 case GL_LINE_WIDTH: *params = lineWidth; break;
828 case GL_SAMPLE_COVERAGE_VALUE: *params = sampleCoverageValue; break;
829 case GL_DEPTH_CLEAR_VALUE: *params = depthClearValue; break;
830 case GL_POLYGON_OFFSET_FACTOR: *params = polygonOffsetFactor; break;
831 case GL_POLYGON_OFFSET_UNITS: *params = polygonOffsetUnits; break;
832 case GL_ALIASED_LINE_WIDTH_RANGE:
833 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
834 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
835 break;
836 case GL_ALIASED_POINT_SIZE_RANGE:
837 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
838 params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
839 break;
840 case GL_DEPTH_RANGE:
841 params[0] = zNear;
842 params[1] = zFar;
843 break;
844 case GL_COLOR_CLEAR_VALUE:
845 params[0] = colorClearValue.red;
846 params[1] = colorClearValue.green;
847 params[2] = colorClearValue.blue;
848 params[3] = colorClearValue.alpha;
849 break;
850 default:
851 return false;
852 }
853
854 return true;
855}
856
857bool Context::getIntegerv(GLenum pname, GLint *params)
858{
859 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
860 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
861 // GetIntegerv as its native query function. As it would require conversion in any
862 // case, this should make no difference to the calling application. You may find it in
863 // Context::getFloatv.
864 switch (pname)
865 {
866 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
867 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
868 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
869 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
870 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
871 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
872 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
873 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
874 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
875 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
876 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
877 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
878 case GL_ARRAY_BUFFER_BINDING: *params = arrayBuffer; break;
879 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = elementArrayBuffer; break;
880 case GL_FRAMEBUFFER_BINDING: *params = framebuffer; break;
881 case GL_RENDERBUFFER_BINDING: *params = renderbuffer; break;
882 case GL_CURRENT_PROGRAM: *params = currentProgram; break;
883 case GL_PACK_ALIGNMENT: *params = packAlignment; break;
884 case GL_UNPACK_ALIGNMENT: *params = unpackAlignment; break;
885 case GL_GENERATE_MIPMAP_HINT: *params = generateMipmapHint; break;
886 case GL_ACTIVE_TEXTURE: *params = activeSampler; break;
887 case GL_STENCIL_FUNC: *params = stencilFunc; break;
888 case GL_STENCIL_REF: *params = stencilRef; break;
889 case GL_STENCIL_VALUE_MASK: *params = stencilMask; break;
890 case GL_STENCIL_BACK_FUNC: *params = stencilBackFunc; break;
891 case GL_STENCIL_BACK_REF: *params = stencilBackRef; break;
892 case GL_STENCIL_BACK_VALUE_MASK: *params = stencilBackMask; break;
893 case GL_STENCIL_FAIL: *params = stencilFail; break;
894 case GL_STENCIL_PASS_DEPTH_FAIL: *params = stencilPassDepthFail; break;
895 case GL_STENCIL_PASS_DEPTH_PASS: *params = stencilPassDepthPass; break;
896 case GL_STENCIL_BACK_FAIL: *params = stencilBackFail; break;
897 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = stencilBackPassDepthFail; break;
898 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = stencilBackPassDepthPass; break;
899 case GL_DEPTH_FUNC: *params = depthFunc; break;
900 case GL_BLEND_SRC_RGB: *params = sourceBlendRGB; break;
901 case GL_BLEND_SRC_ALPHA: *params = sourceBlendAlpha; break;
902 case GL_BLEND_DST_RGB: *params = destBlendRGB; break;
903 case GL_BLEND_DST_ALPHA: *params = destBlendAlpha; break;
904 case GL_BLEND_EQUATION_RGB: *params = blendEquationRGB; break;
905 case GL_BLEND_EQUATION_ALPHA: *params = blendEquationAlpha; break;
906 case GL_STENCIL_WRITEMASK: *params = stencilWritemask; break;
907 case GL_STENCIL_BACK_WRITEMASK: *params = stencilBackWritemask; break;
908 case GL_STENCIL_CLEAR_VALUE: *params = stencilClearValue; break;
909 case GL_SUBPIXEL_BITS: *params = 4; break;
910 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
911 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
912 case GL_SAMPLE_BUFFERS: *params = 0; break;
913 case GL_SAMPLES: *params = 0; break;
914 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
915 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
916 case GL_MAX_VIEWPORT_DIMS:
917 {
918 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
919 params[0] = maxDimension;
920 params[1] = maxDimension;
921 }
922 break;
923 case GL_VIEWPORT:
924 params[0] = viewportX;
925 params[1] = viewportY;
926 params[2] = viewportWidth;
927 params[3] = viewportHeight;
928 break;
929 case GL_SCISSOR_BOX:
930 params[0] = scissorX;
931 params[1] = scissorY;
932 params[2] = scissorWidth;
933 params[3] = scissorHeight;
934 break;
935 case GL_CULL_FACE_MODE: *params = cullMode; break;
936 case GL_FRONT_FACE: *params = frontFace; break;
937 case GL_RED_BITS:
938 case GL_GREEN_BITS:
939 case GL_BLUE_BITS:
940 case GL_ALPHA_BITS:
941 {
942 gl::Framebuffer *framebuffer = getFramebuffer();
943 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
944
945 if (colorbuffer)
946 {
947 switch (pname)
948 {
949 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
950 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
951 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
952 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
953 }
954 }
955 else
956 {
957 *params = 0;
958 }
959 }
960 break;
961 case GL_DEPTH_BITS:
962 {
963 gl::Framebuffer *framebuffer = getFramebuffer();
964 gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
965
966 if (depthbuffer)
967 {
968 *params = depthbuffer->getDepthSize();
969 }
970 else
971 {
972 *params = 0;
973 }
974 }
975 break;
976 case GL_STENCIL_BITS:
977 {
978 gl::Framebuffer *framebuffer = getFramebuffer();
979 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
980
981 if (stencilbuffer)
982 {
983 *params = stencilbuffer->getStencilSize();
984 }
985 else
986 {
987 *params = 0;
988 }
989 }
990 break;
991 case GL_TEXTURE_BINDING_2D:
992 {
993 if (activeSampler < 0 || activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
994 {
995 error(GL_INVALID_OPERATION);
996 return false;
997 }
998
999 *params = samplerTexture[SAMPLER_2D][activeSampler];
1000 }
1001 break;
1002 case GL_TEXTURE_BINDING_CUBE_MAP:
1003 {
1004 if (activeSampler < 0 || activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
1005 {
1006 error(GL_INVALID_OPERATION);
1007 return false;
1008 }
1009
1010 *params = samplerTexture[SAMPLER_CUBE][activeSampler];
1011 }
1012 break;
1013 default:
1014 return false;
1015 }
1016
1017 return true;
1018}
1019
1020bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1021{
1022 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1023 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1024 // to the fact that it is stored internally as a float, and so would require conversion
1025 // if returned from Context::getIntegerv. Since this conversion is already implemented
1026 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1027 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1028 // application.
1029 switch (pname)
1030 {
1031 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1032 case GL_SHADER_BINARY_FORMATS:
1033 {
1034 *type = GL_INT;
1035 *numParams = 0;
1036 }
1037 break;
1038 case GL_MAX_VERTEX_ATTRIBS:
1039 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1040 case GL_MAX_VARYING_VECTORS:
1041 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1042 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1043 case GL_MAX_TEXTURE_IMAGE_UNITS:
1044 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1045 case GL_MAX_RENDERBUFFER_SIZE:
1046 case GL_NUM_SHADER_BINARY_FORMATS:
1047 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1048 case GL_ARRAY_BUFFER_BINDING:
1049 case GL_FRAMEBUFFER_BINDING:
1050 case GL_RENDERBUFFER_BINDING:
1051 case GL_CURRENT_PROGRAM:
1052 case GL_PACK_ALIGNMENT:
1053 case GL_UNPACK_ALIGNMENT:
1054 case GL_GENERATE_MIPMAP_HINT:
1055 case GL_RED_BITS:
1056 case GL_GREEN_BITS:
1057 case GL_BLUE_BITS:
1058 case GL_ALPHA_BITS:
1059 case GL_DEPTH_BITS:
1060 case GL_STENCIL_BITS:
1061 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1062 case GL_CULL_FACE_MODE:
1063 case GL_FRONT_FACE:
1064 case GL_ACTIVE_TEXTURE:
1065 case GL_STENCIL_FUNC:
1066 case GL_STENCIL_VALUE_MASK:
1067 case GL_STENCIL_REF:
1068 case GL_STENCIL_FAIL:
1069 case GL_STENCIL_PASS_DEPTH_FAIL:
1070 case GL_STENCIL_PASS_DEPTH_PASS:
1071 case GL_STENCIL_BACK_FUNC:
1072 case GL_STENCIL_BACK_VALUE_MASK:
1073 case GL_STENCIL_BACK_REF:
1074 case GL_STENCIL_BACK_FAIL:
1075 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1076 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1077 case GL_DEPTH_FUNC:
1078 case GL_BLEND_SRC_RGB:
1079 case GL_BLEND_SRC_ALPHA:
1080 case GL_BLEND_DST_RGB:
1081 case GL_BLEND_DST_ALPHA:
1082 case GL_BLEND_EQUATION_RGB:
1083 case GL_BLEND_EQUATION_ALPHA:
1084 case GL_STENCIL_WRITEMASK:
1085 case GL_STENCIL_BACK_WRITEMASK:
1086 case GL_STENCIL_CLEAR_VALUE:
1087 case GL_SUBPIXEL_BITS:
1088 case GL_MAX_TEXTURE_SIZE:
1089 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1090 case GL_SAMPLE_BUFFERS:
1091 case GL_SAMPLES:
1092 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1093 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1094 case GL_TEXTURE_BINDING_2D:
1095 case GL_TEXTURE_BINDING_CUBE_MAP:
1096 {
1097 *type = GL_INT;
1098 *numParams = 1;
1099 }
1100 break;
1101 case GL_MAX_VIEWPORT_DIMS:
1102 {
1103 *type = GL_INT;
1104 *numParams = 2;
1105 }
1106 break;
1107 case GL_VIEWPORT:
1108 case GL_SCISSOR_BOX:
1109 {
1110 *type = GL_INT;
1111 *numParams = 4;
1112 }
1113 break;
1114 case GL_SHADER_COMPILER:
1115 case GL_SAMPLE_COVERAGE_INVERT:
1116 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001117 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1118 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1119 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1120 case GL_SAMPLE_COVERAGE:
1121 case GL_SCISSOR_TEST:
1122 case GL_STENCIL_TEST:
1123 case GL_DEPTH_TEST:
1124 case GL_BLEND:
1125 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001126 {
1127 *type = GL_BOOL;
1128 *numParams = 1;
1129 }
1130 break;
1131 case GL_COLOR_WRITEMASK:
1132 {
1133 *type = GL_BOOL;
1134 *numParams = 4;
1135 }
1136 break;
1137 case GL_POLYGON_OFFSET_FACTOR:
1138 case GL_POLYGON_OFFSET_UNITS:
1139 case GL_SAMPLE_COVERAGE_VALUE:
1140 case GL_DEPTH_CLEAR_VALUE:
1141 case GL_LINE_WIDTH:
1142 {
1143 *type = GL_FLOAT;
1144 *numParams = 1;
1145 }
1146 break;
1147 case GL_ALIASED_LINE_WIDTH_RANGE:
1148 case GL_ALIASED_POINT_SIZE_RANGE:
1149 case GL_DEPTH_RANGE:
1150 {
1151 *type = GL_FLOAT;
1152 *numParams = 2;
1153 }
1154 break;
1155 case GL_COLOR_CLEAR_VALUE:
1156 {
1157 *type = GL_FLOAT;
1158 *numParams = 4;
1159 }
1160 break;
1161 default:
1162 return false;
1163 }
1164
1165 return true;
1166}
1167
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001168// Applies the render target surface, depth stencil surface, viewport rectangle and
1169// scissor rectangle to the Direct3D 9 device
1170bool Context::applyRenderTarget(bool ignoreViewport)
1171{
1172 IDirect3DDevice9 *device = getDevice();
1173 Framebuffer *framebufferObject = getFramebuffer();
1174
1175 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1176 {
1177 return false;
1178 }
1179
1180 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1181 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1182
1183 device->SetRenderTarget(0, renderTarget);
1184 device->SetDepthStencilSurface(depthStencil);
1185
1186 D3DVIEWPORT9 viewport;
1187 D3DSURFACE_DESC desc;
1188 renderTarget->GetDesc(&desc);
1189
1190 if (ignoreViewport)
1191 {
1192 viewport.X = 0;
1193 viewport.Y = 0;
1194 viewport.Width = desc.Width;
1195 viewport.Height = desc.Height;
1196 viewport.MinZ = 0.0f;
1197 viewport.MaxZ = 1.0f;
1198 }
1199 else
1200 {
daniel@transgaming.com16973022010-03-11 19:22:19 +00001201 viewport.X = std::max(viewportX, 0);
1202 viewport.Y = std::max(viewportY, 0);
1203 viewport.Width = std::min(viewportWidth, (int)desc.Width - (int)viewport.X);
1204 viewport.Height = std::min(viewportHeight, (int)desc.Height - (int)viewport.Y);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001205 viewport.MinZ = clamp01(zNear);
1206 viewport.MaxZ = clamp01(zFar);
1207 }
1208
1209 device->SetViewport(&viewport);
1210
1211 if (scissorTest)
1212 {
1213 RECT rect = {scissorX,
1214 scissorY,
1215 scissorX + scissorWidth,
1216 scissorY + scissorHeight};
1217
1218 device->SetScissorRect(&rect);
1219 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1220 }
1221 else
1222 {
1223 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1224 }
1225
1226 if (currentProgram)
1227 {
1228 D3DSURFACE_DESC description;
1229 renderTarget->GetDesc(&description);
1230 Program *programObject = getCurrentProgram();
1231
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001232 GLint halfPixelSize = programObject->getUniformLocation("gl_HalfPixelSize");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001233 GLfloat xy[2] = {1.0f / description.Width, 1.0f / description.Height};
1234 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001235
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001236 GLint window = programObject->getUniformLocation("gl_Window");
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001237 GLfloat whxy[4] = {viewportWidth / 2.0f, viewportHeight / 2.0f, (float)viewportX + viewportWidth / 2.0f, (float)viewportY + viewportHeight / 2.0f};
1238 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1239
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001240 GLint depth = programObject->getUniformLocation("gl_Depth");
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001241 GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
1242 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1243
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001244 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001245 programObject->setUniform1fv(near, 1, &zNear);
1246
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001247 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001248 programObject->setUniform1fv(far, 1, &zFar);
1249
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001250 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001251 GLfloat zDiff = zFar - zNear;
1252 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001253 }
1254
1255 return true;
1256}
1257
1258// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
1259void Context::applyState()
1260{
1261 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001262 Program *programObject = getCurrentProgram();
1263
1264 GLint frontCCW = programObject->getUniformLocation("__frontCCW");
1265 GLint ccw = (frontFace == GL_CCW);
1266 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001267
1268 if (cullFace)
1269 {
1270 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(cullMode, frontFace));
1271 }
1272 else
1273 {
1274 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1275 }
1276
1277 if (depthTest)
1278 {
1279 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1280 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(depthFunc));
1281 }
1282 else
1283 {
1284 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
1285 }
1286
1287 if (blend)
1288 {
1289 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1290
1291 if (sourceBlendRGB != GL_CONSTANT_ALPHA && sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1292 destBlendRGB != GL_CONSTANT_ALPHA && destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1293 {
1294 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(blendColor));
1295 }
1296 else
1297 {
1298 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(blendColor.alpha),
1299 unorm<8>(blendColor.alpha),
1300 unorm<8>(blendColor.alpha),
1301 unorm<8>(blendColor.alpha)));
1302 }
1303
1304 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(sourceBlendRGB));
1305 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(destBlendRGB));
1306 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(blendEquationRGB));
1307
1308 if (sourceBlendRGB != sourceBlendAlpha || destBlendRGB != destBlendAlpha || blendEquationRGB != blendEquationAlpha)
1309 {
1310 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1311
1312 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(sourceBlendAlpha));
1313 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(destBlendAlpha));
1314 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(blendEquationAlpha));
1315
1316 }
1317 else
1318 {
1319 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1320 }
1321 }
1322 else
1323 {
1324 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1325 }
1326
1327 if (stencilTest)
1328 {
1329 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1330 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1331
1332 // FIXME: Unsupported by D3D9
1333 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1334 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1335 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001336 if(stencilWritemask != stencilBackWritemask || stencilRef != stencilBackRef || stencilMask != stencilBackMask)
1337 {
1338 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1339 return error(GL_INVALID_OPERATION);
1340 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001341
1342 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWritemask);
1343 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilFunc));
1344
1345 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilRef); // FIXME: Clamp to range
1346 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
1347
1348 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilFail));
1349 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilPassDepthFail));
1350 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilPassDepthPass));
1351
1352 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWritemask);
1353 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilBackFunc));
1354
1355 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilBackRef); // FIXME: Clamp to range
1356 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilBackMask);
1357
1358 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilBackFail));
1359 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilBackPassDepthFail));
1360 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilBackPassDepthPass));
1361 }
1362 else
1363 {
1364 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1365 }
1366
1367 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(colorMaskRed, colorMaskGreen, colorMaskBlue, colorMaskAlpha));
1368 device->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
1369
1370 if (polygonOffsetFill)
1371 {
1372 UNIMPLEMENTED(); // FIXME
1373 }
1374
1375 if (sampleAlphaToCoverage)
1376 {
1377 UNIMPLEMENTED(); // FIXME
1378 }
1379
1380 if (sampleCoverage)
1381 {
1382 UNIMPLEMENTED(); // FIXME: Ignore when SAMPLE_BUFFERS is not one
1383 }
1384
1385 device->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
1386}
1387
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001388// Fill in the programAttribute field of the array of TranslatedAttributes based on the active GLSL program.
1389void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001390{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001391 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001392 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001393 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001394 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001395 attributes[i].programAttribute = getCurrentProgram()->getInputMapping(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001396 }
1397 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001398}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001399
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001400// The indices parameter to glDrawElements can have two interpretations:
1401// - as a pointer into client memory
1402// - as an offset into the current GL_ELEMENT_ARRAY_BUFFER buffer
1403// Handle these cases here and return a pointer to the index data.
1404const Index *Context::adjustIndexPointer(const void *indices)
1405{
1406 if (elementArrayBuffer)
1407 {
1408 Buffer *buffer = getBuffer(elementArrayBuffer);
1409 return reinterpret_cast<const Index*>(static_cast<unsigned char*>(buffer->data()) + reinterpret_cast<GLsizei>(indices));
1410 }
1411 else
1412 {
1413 return static_cast<const Index*>(indices);
1414 }
1415}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001416
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001417void Context::applyVertexBuffer(GLint first, GLsizei count)
1418{
1419 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1420
1421 mVertexDataManager->preRenderValidate(first, count, translated);
1422
1423 lookupAttributeMapping(translated);
1424
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001425 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001426}
1427
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001428void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001429{
1430 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1431
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001432 mVertexDataManager->preRenderValidate(indexInfo, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001433
1434 lookupAttributeMapping(translated);
1435
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001436 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001437}
1438
1439// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001440TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001441{
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001442 TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(elementArrayBuffer), indices);
1443 mBufferBackEnd->setupIndicesPreDraw(indexInfo);
1444 return indexInfo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001445}
1446
1447// Applies the shaders and shader constants to the Direct3D 9 device
1448void Context::applyShaders()
1449{
1450 IDirect3DDevice9 *device = getDevice();
1451 Program *programObject = getCurrentProgram();
1452 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1453 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1454
1455 device->SetVertexShader(vertexShader);
1456 device->SetPixelShader(pixelShader);
1457
1458 programObject->applyUniforms();
1459}
1460
1461// Applies the textures and sampler states to the Direct3D 9 device
1462void Context::applyTextures()
1463{
1464 IDirect3DDevice9 *device = getDevice();
1465 Program *programObject = getCurrentProgram();
1466
1467 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1468 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001469 int textureUnit = programObject->getSamplerMapping(sampler);
1470 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001471 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001472 SamplerType textureType = programObject->getSamplerType(sampler);
1473
1474 Texture *texture = getSamplerTexture(textureUnit, textureType);
1475
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001476 if (texture->isComplete())
1477 {
1478 GLenum wrapS = texture->getWrapS();
1479 GLenum wrapT = texture->getWrapT();
1480 GLenum minFilter = texture->getMinFilter();
1481 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001482
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001483 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1484 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001485
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001486 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1487 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1488 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1489 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1490 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001491
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001492 device->SetTexture(sampler, texture->getTexture());
1493 }
1494 else
1495 {
1496 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1497 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001498 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001499 else
1500 {
1501 device->SetTexture(sampler, NULL);
1502 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001503 }
1504}
1505
1506void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1507{
1508 Framebuffer *framebuffer = getFramebuffer();
1509 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1510 IDirect3DDevice9 *device = getDevice();
1511
1512 D3DSURFACE_DESC desc;
1513 renderTarget->GetDesc(&desc);
1514
1515 IDirect3DSurface9 *systemSurface;
1516 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1517
1518 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1519 {
1520 return error(GL_OUT_OF_MEMORY);
1521 }
1522
1523 ASSERT(SUCCEEDED(result));
1524
1525 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1526 {
1527 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1528 }
1529
1530 result = device->GetRenderTargetData(renderTarget, systemSurface);
1531
1532 if (result == D3DERR_DRIVERINTERNALERROR)
1533 {
1534 systemSurface->Release();
1535
1536 return error(GL_OUT_OF_MEMORY);
1537 }
1538
1539 if (FAILED(result))
1540 {
1541 UNREACHABLE();
1542 systemSurface->Release();
1543
1544 return; // No sensible error to generate
1545 }
1546
1547 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001548 RECT rect = {std::max(x, 0),
1549 std::max(y, 0),
1550 std::min(x + width, (int)desc.Width),
1551 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001552
1553 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1554
1555 if (FAILED(result))
1556 {
1557 UNREACHABLE();
1558 systemSurface->Release();
1559
1560 return; // No sensible error to generate
1561 }
1562
1563 unsigned char *source = (unsigned char*)lock.pBits;
1564 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001565 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001566
1567 for (int j = 0; j < rect.bottom - rect.top; j++)
1568 {
1569 for (int i = 0; i < rect.right - rect.left; i++)
1570 {
1571 float r;
1572 float g;
1573 float b;
1574 float a;
1575
1576 switch (desc.Format)
1577 {
1578 case D3DFMT_R5G6B5:
1579 {
1580 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1581
1582 a = 1.0f;
1583 b = (rgb & 0x001F) * (1.0f / 0x001F);
1584 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1585 r = (rgb & 0xF800) * (1.0f / 0xF800);
1586 }
1587 break;
1588 case D3DFMT_X1R5G5B5:
1589 {
1590 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1591
1592 a = 1.0f;
1593 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1594 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1595 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1596 }
1597 break;
1598 case D3DFMT_A1R5G5B5:
1599 {
1600 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1601
1602 a = (argb & 0x8000) ? 1.0f : 0.0f;
1603 b = (argb & 0x001F) * (1.0f / 0x001F);
1604 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1605 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1606 }
1607 break;
1608 case D3DFMT_A8R8G8B8:
1609 {
1610 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1611
1612 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1613 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1614 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1615 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1616 }
1617 break;
1618 case D3DFMT_X8R8G8B8:
1619 {
1620 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1621
1622 a = 1.0f;
1623 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
1624 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
1625 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
1626 }
1627 break;
1628 case D3DFMT_A2R10G10B10:
1629 {
1630 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1631
1632 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
1633 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
1634 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
1635 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
1636 }
1637 break;
1638 default:
1639 UNIMPLEMENTED(); // FIXME
1640 UNREACHABLE();
1641 }
1642
1643 switch (format)
1644 {
1645 case GL_RGBA:
1646 switch (type)
1647 {
1648 case GL_UNSIGNED_BYTE:
1649 dest[4 * (i + j * width) + 0] = (unsigned char)(255 * r + 0.5f);
1650 dest[4 * (i + j * width) + 1] = (unsigned char)(255 * g + 0.5f);
1651 dest[4 * (i + j * width) + 2] = (unsigned char)(255 * b + 0.5f);
1652 dest[4 * (i + j * width) + 3] = (unsigned char)(255 * a + 0.5f);
1653 break;
1654 default: UNREACHABLE();
1655 }
1656 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001657 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001658 switch (type)
1659 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001660 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
1661 dest16[i + j * width] = ((unsigned short)(31 * b + 0.5f) << 0) |
1662 ((unsigned short)(63 * g + 0.5f) << 5) |
1663 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001664 break;
1665 default: UNREACHABLE();
1666 }
1667 break;
1668 default: UNREACHABLE();
1669 }
1670 }
1671 }
1672
1673 systemSurface->UnlockRect();
1674
1675 systemSurface->Release();
1676}
1677
1678void Context::clear(GLbitfield mask)
1679{
1680 IDirect3DDevice9 *device = getDevice();
1681 DWORD flags = 0;
1682
1683 if (mask & GL_COLOR_BUFFER_BIT)
1684 {
1685 mask &= ~GL_COLOR_BUFFER_BIT;
1686 flags |= D3DCLEAR_TARGET;
1687 }
1688
1689 if (mask & GL_DEPTH_BUFFER_BIT)
1690 {
1691 mask &= ~GL_DEPTH_BUFFER_BIT;
1692 if (depthMask)
1693 {
1694 flags |= D3DCLEAR_ZBUFFER;
1695 }
1696 }
1697
1698 Framebuffer *framebufferObject = getFramebuffer();
1699 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1700
1701 GLuint stencilUnmasked = 0x0;
1702
1703 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
1704 {
1705 D3DSURFACE_DESC desc;
1706 depthStencil->GetDesc(&desc);
1707
1708 mask &= ~GL_STENCIL_BUFFER_BIT;
1709 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
1710 stencilUnmasked = (0x1 << stencilSize) - 1;
1711
1712 if (stencilUnmasked != 0x0)
1713 {
1714 flags |= D3DCLEAR_STENCIL;
1715 }
1716 }
1717
1718 if (mask != 0)
1719 {
1720 return error(GL_INVALID_VALUE);
1721 }
1722
1723 applyRenderTarget(true); // Clips the clear to the scissor rectangle but not the viewport
1724
1725 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(colorClearValue.alpha), unorm<8>(colorClearValue.red), unorm<8>(colorClearValue.green), unorm<8>(colorClearValue.blue));
1726 float depth = clamp01(depthClearValue);
1727 int stencil = stencilClearValue & 0x000000FF;
1728
1729 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1730
1731 D3DSURFACE_DESC desc;
1732 renderTarget->GetDesc(&desc);
1733
1734 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || colorMaskAlpha;
1735
1736 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
1737 (stencilWritemask & stencilUnmasked) != stencilUnmasked;
1738 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001739 !(colorMaskRed && colorMaskGreen &&
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001740 colorMaskBlue && alphaUnmasked);
1741
1742 if (needMaskedColorClear || needMaskedStencilClear)
1743 {
1744 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
1745 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1746 device->SetRenderState(D3DRS_ZENABLE, FALSE);
1747 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1748 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
1749 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
1750 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1751 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
1752
1753 if (flags & D3DCLEAR_TARGET)
1754 {
1755 device->SetRenderState(D3DRS_COLORWRITEENABLE, (colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
1756 (colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
1757 (colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
1758 (colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
1759 }
1760 else
1761 {
1762 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1763 }
1764
1765 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
1766 {
1767 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1768 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
1769 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
1770 device->SetRenderState(D3DRS_STENCILREF, stencil);
1771 device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001772 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001773 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
1774 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
1775 }
1776 else
1777 {
1778 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1779 }
1780
1781 device->SetPixelShader(NULL);
1782 device->SetVertexShader(NULL);
1783 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1784
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001785 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001786 {
1787 float x, y, z, w;
1788 D3DCOLOR diffuse;
1789 };
1790
1791 Vertex quad[4];
1792 quad[0].x = 0.0f;
1793 quad[0].y = (float)desc.Height;
1794 quad[0].z = 0.0f;
1795 quad[0].w = 1.0f;
1796 quad[0].diffuse = color;
1797
1798 quad[1].x = (float)desc.Width;
1799 quad[1].y = (float)desc.Height;
1800 quad[1].z = 0.0f;
1801 quad[1].w = 1.0f;
1802 quad[1].diffuse = color;
1803
1804 quad[2].x = 0.0f;
1805 quad[2].y = 0.0f;
1806 quad[2].z = 0.0f;
1807 quad[2].w = 1.0f;
1808 quad[2].diffuse = color;
1809
1810 quad[3].x = (float)desc.Width;
1811 quad[3].y = 0.0f;
1812 quad[3].z = 0.0f;
1813 quad[3].w = 1.0f;
1814 quad[3].diffuse = color;
1815
1816 device->BeginScene();
1817 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
1818 device->EndScene();
1819
1820 if (flags & D3DCLEAR_ZBUFFER)
1821 {
1822 device->SetRenderState(D3DRS_ZENABLE, TRUE);
1823 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
1824 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
1825 }
1826 }
1827 else
1828 {
1829 device->Clear(0, NULL, flags, color, depth, stencil);
1830 }
1831}
1832
1833void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
1834{
1835 if (!currentProgram)
1836 {
1837 return error(GL_INVALID_OPERATION);
1838 }
1839
1840 IDirect3DDevice9 *device = getDevice();
1841 D3DPRIMITIVETYPE primitiveType;
1842 int primitiveCount;
1843
1844 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1845 return error(GL_INVALID_ENUM);
1846
1847 if (primitiveCount <= 0)
1848 {
1849 return;
1850 }
1851
1852 if (!applyRenderTarget(false))
1853 {
1854 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1855 }
1856
1857 applyState();
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001858 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001859 applyShaders();
1860 applyTextures();
1861
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001862 if (!cullSkipsDraw(mode))
1863 {
1864 device->BeginScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001865 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001866 device->EndScene();
1867 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001868}
1869
1870void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
1871{
1872 if (!currentProgram)
1873 {
1874 return error(GL_INVALID_OPERATION);
1875 }
1876
1877 if (!indices && !elementArrayBuffer)
1878 {
1879 return error(GL_INVALID_OPERATION);
1880 }
1881
1882 IDirect3DDevice9 *device = getDevice();
1883 D3DPRIMITIVETYPE primitiveType;
1884 int primitiveCount;
1885
1886 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1887 return error(GL_INVALID_ENUM);
1888
1889 if (primitiveCount <= 0)
1890 {
1891 return;
1892 }
1893
1894 if (!applyRenderTarget(false))
1895 {
1896 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1897 }
1898
1899 applyState();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001900 TranslatedIndexData indexInfo = applyIndexBuffer(indices, count, mode, type);
1901 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001902 applyShaders();
1903 applyTextures();
1904
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001905 if (!cullSkipsDraw(mode))
1906 {
1907 device->BeginScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001908 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 +00001909 device->EndScene();
1910 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001911}
1912
1913void Context::finish()
1914{
1915 IDirect3DDevice9 *device = getDevice();
1916 IDirect3DQuery9 *occlusionQuery = NULL;
1917
1918 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
1919
1920 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1921 {
1922 return error(GL_OUT_OF_MEMORY);
1923 }
1924
1925 ASSERT(SUCCEEDED(result));
1926
1927 if (occlusionQuery)
1928 {
1929 occlusionQuery->Issue(D3DISSUE_BEGIN);
1930
1931 // Render something outside the render target
1932 device->SetPixelShader(NULL);
1933 device->SetVertexShader(NULL);
1934 device->SetFVF(D3DFVF_XYZRHW);
1935 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
1936 device->BeginScene();
1937 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
1938 device->EndScene();
1939
1940 occlusionQuery->Issue(D3DISSUE_END);
1941
1942 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1943 {
1944 // Keep polling, but allow other threads to do something useful first
1945 Sleep(0);
1946 }
1947
1948 occlusionQuery->Release();
1949 }
1950}
1951
1952void Context::flush()
1953{
1954 IDirect3DDevice9 *device = getDevice();
1955 IDirect3DQuery9 *eventQuery = NULL;
1956
1957 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
1958
1959 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1960 {
1961 return error(GL_OUT_OF_MEMORY);
1962 }
1963
1964 ASSERT(SUCCEEDED(result));
1965
1966 if (eventQuery)
1967 {
1968 eventQuery->Issue(D3DISSUE_END);
1969
1970 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1971 {
1972 // Keep polling, but allow other threads to do something useful first
1973 Sleep(0);
1974 }
1975
1976 eventQuery->Release();
1977 }
1978}
1979
1980void Context::recordInvalidEnum()
1981{
1982 mInvalidEnum = true;
1983}
1984
1985void Context::recordInvalidValue()
1986{
1987 mInvalidValue = true;
1988}
1989
1990void Context::recordInvalidOperation()
1991{
1992 mInvalidOperation = true;
1993}
1994
1995void Context::recordOutOfMemory()
1996{
1997 mOutOfMemory = true;
1998}
1999
2000void Context::recordInvalidFramebufferOperation()
2001{
2002 mInvalidFramebufferOperation = true;
2003}
2004
2005// Get one of the recorded errors and clear its flag, if any.
2006// [OpenGL ES 2.0.24] section 2.5 page 13.
2007GLenum Context::getError()
2008{
2009 if (mInvalidEnum)
2010 {
2011 mInvalidEnum = false;
2012
2013 return GL_INVALID_ENUM;
2014 }
2015
2016 if (mInvalidValue)
2017 {
2018 mInvalidValue = false;
2019
2020 return GL_INVALID_VALUE;
2021 }
2022
2023 if (mInvalidOperation)
2024 {
2025 mInvalidOperation = false;
2026
2027 return GL_INVALID_OPERATION;
2028 }
2029
2030 if (mOutOfMemory)
2031 {
2032 mOutOfMemory = false;
2033
2034 return GL_OUT_OF_MEMORY;
2035 }
2036
2037 if (mInvalidFramebufferOperation)
2038 {
2039 mInvalidFramebufferOperation = false;
2040
2041 return GL_INVALID_FRAMEBUFFER_OPERATION;
2042 }
2043
2044 return GL_NO_ERROR;
2045}
2046
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002047const char *Context::getPixelShaderProfile()
2048{
2049 return mPsProfile;
2050}
2051
2052const char *Context::getVertexShaderProfile()
2053{
2054 return mVsProfile;
2055}
2056
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002057void Context::detachBuffer(GLuint buffer)
2058{
2059 // [OpenGL ES 2.0.24] section 2.9 page 22:
2060 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2061 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2062
2063 if (arrayBuffer == buffer)
2064 {
2065 arrayBuffer = 0;
2066 }
2067
2068 if (elementArrayBuffer == buffer)
2069 {
2070 elementArrayBuffer = 0;
2071 }
2072
2073 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2074 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002075 if (vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002076 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002077 vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002078 }
2079 }
2080}
2081
2082void Context::detachTexture(GLuint texture)
2083{
2084 // [OpenGL ES 2.0.24] section 3.8 page 84:
2085 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2086 // rebound to texture object zero
2087
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002088 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002089 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002090 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002091 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002092 if (samplerTexture[type][sampler] == texture)
2093 {
2094 samplerTexture[type][sampler] = 0;
2095 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002096 }
2097 }
2098
2099 // [OpenGL ES 2.0.24] section 4.4 page 112:
2100 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2101 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2102 // image was attached in the currently bound framebuffer.
2103
2104 Framebuffer *framebuffer = getFramebuffer();
2105
2106 if (framebuffer)
2107 {
2108 framebuffer->detachTexture(texture);
2109 }
2110}
2111
2112void Context::detachFramebuffer(GLuint framebuffer)
2113{
2114 // [OpenGL ES 2.0.24] section 4.4 page 107:
2115 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2116 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2117
2118 if (this->framebuffer == framebuffer)
2119 {
2120 bindFramebuffer(0);
2121 }
2122}
2123
2124void Context::detachRenderbuffer(GLuint renderbuffer)
2125{
2126 // [OpenGL ES 2.0.24] section 4.4 page 109:
2127 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2128 // had been executed with the target RENDERBUFFER and name of zero.
2129
2130 if (this->renderbuffer == renderbuffer)
2131 {
2132 bindRenderbuffer(0);
2133 }
2134
2135 // [OpenGL ES 2.0.24] section 4.4 page 111:
2136 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2137 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2138 // point to which this image was attached in the currently bound framebuffer.
2139
2140 Framebuffer *framebuffer = getFramebuffer();
2141
2142 if (framebuffer)
2143 {
2144 framebuffer->detachRenderbuffer(renderbuffer);
2145 }
2146}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002147
2148Texture *Context::getIncompleteTexture(SamplerType type)
2149{
2150 Texture *t = mIncompleteTextures[type];
2151
2152 if (t == NULL)
2153 {
2154 static const GLubyte color[] = { 0, 0, 0, 255 };
2155
2156 switch (type)
2157 {
2158 default:
2159 UNREACHABLE();
2160 // default falls through to SAMPLER_2D
2161
2162 case SAMPLER_2D:
2163 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002164 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002165 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002166 t = incomplete2d;
2167 }
2168 break;
2169
2170 case SAMPLER_CUBE:
2171 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002172 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002173
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002174 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2175 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2176 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2177 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2178 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2179 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002180
2181 t = incompleteCube;
2182 }
2183 break;
2184 }
2185
2186 mIncompleteTextures[type] = t;
2187 }
2188
2189 return t;
2190}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002191
2192bool Context::cullSkipsDraw(GLenum primitiveType)
2193{
2194 if (cullFace && cullMode == GL_FRONT_AND_BACK &&
2195 (primitiveType == GL_TRIANGLES || primitiveType == GL_TRIANGLE_FAN || primitiveType == GL_TRIANGLE_STRIP))
2196 {
2197 return true;
2198 }
2199 else
2200 {
2201 return false;
2202 }
2203}
2204
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002205}
2206
2207extern "C"
2208{
2209gl::Context *glCreateContext(const egl::Config *config)
2210{
2211 return new gl::Context(config);
2212}
2213
2214void glDestroyContext(gl::Context *context)
2215{
2216 delete context;
2217
2218 if (context == gl::getContext())
2219 {
2220 gl::makeCurrent(NULL, NULL, NULL);
2221 }
2222}
2223
2224void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2225{
2226 gl::makeCurrent(context, display, surface);
2227}
2228
2229gl::Context *glGetCurrentContext()
2230{
2231 return gl::getContext();
2232}
2233}