blob: fed65d42f2c076cdb2c22cfe67e6ca2c038b552e [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
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001259void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001260{
1261 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001262 Program *programObject = getCurrentProgram();
1263
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001264 GLint frontCCW = programObject->getUniformLocation("gl_FrontCCW");
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001265 GLint ccw = (frontFace == GL_CCW);
1266 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001267
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001268 GLint pointsOrLines = programObject->getUniformLocation("gl_PointsOrLines");
1269 GLint alwaysFront = !isTriangleMode(drawMode);
1270 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1271
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001272 if (cullFace)
1273 {
1274 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(cullMode, frontFace));
1275 }
1276 else
1277 {
1278 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1279 }
1280
1281 if (depthTest)
1282 {
1283 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1284 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(depthFunc));
1285 }
1286 else
1287 {
1288 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
1289 }
1290
1291 if (blend)
1292 {
1293 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1294
1295 if (sourceBlendRGB != GL_CONSTANT_ALPHA && sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1296 destBlendRGB != GL_CONSTANT_ALPHA && destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1297 {
1298 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(blendColor));
1299 }
1300 else
1301 {
1302 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(blendColor.alpha),
1303 unorm<8>(blendColor.alpha),
1304 unorm<8>(blendColor.alpha),
1305 unorm<8>(blendColor.alpha)));
1306 }
1307
1308 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(sourceBlendRGB));
1309 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(destBlendRGB));
1310 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(blendEquationRGB));
1311
1312 if (sourceBlendRGB != sourceBlendAlpha || destBlendRGB != destBlendAlpha || blendEquationRGB != blendEquationAlpha)
1313 {
1314 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1315
1316 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(sourceBlendAlpha));
1317 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(destBlendAlpha));
1318 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(blendEquationAlpha));
1319
1320 }
1321 else
1322 {
1323 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1324 }
1325 }
1326 else
1327 {
1328 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1329 }
1330
1331 if (stencilTest)
1332 {
1333 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1334 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1335
1336 // FIXME: Unsupported by D3D9
1337 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1338 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1339 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001340 if(stencilWritemask != stencilBackWritemask || stencilRef != stencilBackRef || stencilMask != stencilBackMask)
1341 {
1342 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1343 return error(GL_INVALID_OPERATION);
1344 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001345
1346 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWritemask);
1347 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilFunc));
1348
1349 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilRef); // FIXME: Clamp to range
1350 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
1351
1352 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilFail));
1353 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilPassDepthFail));
1354 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilPassDepthPass));
1355
1356 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWritemask);
1357 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilBackFunc));
1358
1359 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilBackRef); // FIXME: Clamp to range
1360 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilBackMask);
1361
1362 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilBackFail));
1363 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilBackPassDepthFail));
1364 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilBackPassDepthPass));
1365 }
1366 else
1367 {
1368 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1369 }
1370
1371 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(colorMaskRed, colorMaskGreen, colorMaskBlue, colorMaskAlpha));
1372 device->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
1373
1374 if (polygonOffsetFill)
1375 {
1376 UNIMPLEMENTED(); // FIXME
1377 }
1378
1379 if (sampleAlphaToCoverage)
1380 {
1381 UNIMPLEMENTED(); // FIXME
1382 }
1383
1384 if (sampleCoverage)
1385 {
1386 UNIMPLEMENTED(); // FIXME: Ignore when SAMPLE_BUFFERS is not one
1387 }
1388
1389 device->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
1390}
1391
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001392// Fill in the programAttribute field of the array of TranslatedAttributes based on the active GLSL program.
1393void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001394{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001395 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001396 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001397 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001398 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001399 attributes[i].programAttribute = getCurrentProgram()->getInputMapping(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001400 }
1401 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001402}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001403
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001404// The indices parameter to glDrawElements can have two interpretations:
1405// - as a pointer into client memory
1406// - as an offset into the current GL_ELEMENT_ARRAY_BUFFER buffer
1407// Handle these cases here and return a pointer to the index data.
1408const Index *Context::adjustIndexPointer(const void *indices)
1409{
1410 if (elementArrayBuffer)
1411 {
1412 Buffer *buffer = getBuffer(elementArrayBuffer);
1413 return reinterpret_cast<const Index*>(static_cast<unsigned char*>(buffer->data()) + reinterpret_cast<GLsizei>(indices));
1414 }
1415 else
1416 {
1417 return static_cast<const Index*>(indices);
1418 }
1419}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001420
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001421void Context::applyVertexBuffer(GLint first, GLsizei count)
1422{
1423 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1424
1425 mVertexDataManager->preRenderValidate(first, count, translated);
1426
1427 lookupAttributeMapping(translated);
1428
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001429 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001430}
1431
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001432void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001433{
1434 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1435
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001436 mVertexDataManager->preRenderValidate(indexInfo, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001437
1438 lookupAttributeMapping(translated);
1439
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001440 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001441}
1442
1443// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001444TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001445{
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001446 TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(elementArrayBuffer), indices);
1447 mBufferBackEnd->setupIndicesPreDraw(indexInfo);
1448 return indexInfo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001449}
1450
1451// Applies the shaders and shader constants to the Direct3D 9 device
1452void Context::applyShaders()
1453{
1454 IDirect3DDevice9 *device = getDevice();
1455 Program *programObject = getCurrentProgram();
1456 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1457 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1458
1459 device->SetVertexShader(vertexShader);
1460 device->SetPixelShader(pixelShader);
1461
1462 programObject->applyUniforms();
1463}
1464
1465// Applies the textures and sampler states to the Direct3D 9 device
1466void Context::applyTextures()
1467{
1468 IDirect3DDevice9 *device = getDevice();
1469 Program *programObject = getCurrentProgram();
1470
1471 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1472 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001473 int textureUnit = programObject->getSamplerMapping(sampler);
1474 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001475 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001476 SamplerType textureType = programObject->getSamplerType(sampler);
1477
1478 Texture *texture = getSamplerTexture(textureUnit, textureType);
1479
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001480 if (texture->isComplete())
1481 {
1482 GLenum wrapS = texture->getWrapS();
1483 GLenum wrapT = texture->getWrapT();
1484 GLenum minFilter = texture->getMinFilter();
1485 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001486
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001487 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1488 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001489
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001490 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1491 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1492 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1493 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1494 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001495
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001496 device->SetTexture(sampler, texture->getTexture());
1497 }
1498 else
1499 {
1500 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1501 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001502 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001503 else
1504 {
1505 device->SetTexture(sampler, NULL);
1506 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001507 }
1508}
1509
1510void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1511{
1512 Framebuffer *framebuffer = getFramebuffer();
1513 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1514 IDirect3DDevice9 *device = getDevice();
1515
1516 D3DSURFACE_DESC desc;
1517 renderTarget->GetDesc(&desc);
1518
1519 IDirect3DSurface9 *systemSurface;
1520 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1521
1522 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1523 {
1524 return error(GL_OUT_OF_MEMORY);
1525 }
1526
1527 ASSERT(SUCCEEDED(result));
1528
1529 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1530 {
1531 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1532 }
1533
1534 result = device->GetRenderTargetData(renderTarget, systemSurface);
1535
1536 if (result == D3DERR_DRIVERINTERNALERROR)
1537 {
1538 systemSurface->Release();
1539
1540 return error(GL_OUT_OF_MEMORY);
1541 }
1542
1543 if (FAILED(result))
1544 {
1545 UNREACHABLE();
1546 systemSurface->Release();
1547
1548 return; // No sensible error to generate
1549 }
1550
1551 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001552 RECT rect = {std::max(x, 0),
1553 std::max(y, 0),
1554 std::min(x + width, (int)desc.Width),
1555 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001556
1557 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1558
1559 if (FAILED(result))
1560 {
1561 UNREACHABLE();
1562 systemSurface->Release();
1563
1564 return; // No sensible error to generate
1565 }
1566
1567 unsigned char *source = (unsigned char*)lock.pBits;
1568 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001569 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001570
1571 for (int j = 0; j < rect.bottom - rect.top; j++)
1572 {
1573 for (int i = 0; i < rect.right - rect.left; i++)
1574 {
1575 float r;
1576 float g;
1577 float b;
1578 float a;
1579
1580 switch (desc.Format)
1581 {
1582 case D3DFMT_R5G6B5:
1583 {
1584 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1585
1586 a = 1.0f;
1587 b = (rgb & 0x001F) * (1.0f / 0x001F);
1588 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1589 r = (rgb & 0xF800) * (1.0f / 0xF800);
1590 }
1591 break;
1592 case D3DFMT_X1R5G5B5:
1593 {
1594 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1595
1596 a = 1.0f;
1597 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1598 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1599 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1600 }
1601 break;
1602 case D3DFMT_A1R5G5B5:
1603 {
1604 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1605
1606 a = (argb & 0x8000) ? 1.0f : 0.0f;
1607 b = (argb & 0x001F) * (1.0f / 0x001F);
1608 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1609 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1610 }
1611 break;
1612 case D3DFMT_A8R8G8B8:
1613 {
1614 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1615
1616 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1617 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1618 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1619 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1620 }
1621 break;
1622 case D3DFMT_X8R8G8B8:
1623 {
1624 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1625
1626 a = 1.0f;
1627 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
1628 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
1629 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
1630 }
1631 break;
1632 case D3DFMT_A2R10G10B10:
1633 {
1634 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1635
1636 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
1637 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
1638 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
1639 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
1640 }
1641 break;
1642 default:
1643 UNIMPLEMENTED(); // FIXME
1644 UNREACHABLE();
1645 }
1646
1647 switch (format)
1648 {
1649 case GL_RGBA:
1650 switch (type)
1651 {
1652 case GL_UNSIGNED_BYTE:
1653 dest[4 * (i + j * width) + 0] = (unsigned char)(255 * r + 0.5f);
1654 dest[4 * (i + j * width) + 1] = (unsigned char)(255 * g + 0.5f);
1655 dest[4 * (i + j * width) + 2] = (unsigned char)(255 * b + 0.5f);
1656 dest[4 * (i + j * width) + 3] = (unsigned char)(255 * a + 0.5f);
1657 break;
1658 default: UNREACHABLE();
1659 }
1660 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001661 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001662 switch (type)
1663 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001664 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
1665 dest16[i + j * width] = ((unsigned short)(31 * b + 0.5f) << 0) |
1666 ((unsigned short)(63 * g + 0.5f) << 5) |
1667 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001668 break;
1669 default: UNREACHABLE();
1670 }
1671 break;
1672 default: UNREACHABLE();
1673 }
1674 }
1675 }
1676
1677 systemSurface->UnlockRect();
1678
1679 systemSurface->Release();
1680}
1681
1682void Context::clear(GLbitfield mask)
1683{
1684 IDirect3DDevice9 *device = getDevice();
1685 DWORD flags = 0;
1686
1687 if (mask & GL_COLOR_BUFFER_BIT)
1688 {
1689 mask &= ~GL_COLOR_BUFFER_BIT;
1690 flags |= D3DCLEAR_TARGET;
1691 }
1692
1693 if (mask & GL_DEPTH_BUFFER_BIT)
1694 {
1695 mask &= ~GL_DEPTH_BUFFER_BIT;
1696 if (depthMask)
1697 {
1698 flags |= D3DCLEAR_ZBUFFER;
1699 }
1700 }
1701
1702 Framebuffer *framebufferObject = getFramebuffer();
1703 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1704
1705 GLuint stencilUnmasked = 0x0;
1706
1707 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
1708 {
1709 D3DSURFACE_DESC desc;
1710 depthStencil->GetDesc(&desc);
1711
1712 mask &= ~GL_STENCIL_BUFFER_BIT;
1713 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
1714 stencilUnmasked = (0x1 << stencilSize) - 1;
1715
1716 if (stencilUnmasked != 0x0)
1717 {
1718 flags |= D3DCLEAR_STENCIL;
1719 }
1720 }
1721
1722 if (mask != 0)
1723 {
1724 return error(GL_INVALID_VALUE);
1725 }
1726
1727 applyRenderTarget(true); // Clips the clear to the scissor rectangle but not the viewport
1728
1729 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(colorClearValue.alpha), unorm<8>(colorClearValue.red), unorm<8>(colorClearValue.green), unorm<8>(colorClearValue.blue));
1730 float depth = clamp01(depthClearValue);
1731 int stencil = stencilClearValue & 0x000000FF;
1732
1733 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1734
1735 D3DSURFACE_DESC desc;
1736 renderTarget->GetDesc(&desc);
1737
1738 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || colorMaskAlpha;
1739
1740 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
1741 (stencilWritemask & stencilUnmasked) != stencilUnmasked;
1742 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001743 !(colorMaskRed && colorMaskGreen &&
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001744 colorMaskBlue && alphaUnmasked);
1745
1746 if (needMaskedColorClear || needMaskedStencilClear)
1747 {
1748 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
1749 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1750 device->SetRenderState(D3DRS_ZENABLE, FALSE);
1751 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1752 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
1753 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
1754 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1755 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
1756
1757 if (flags & D3DCLEAR_TARGET)
1758 {
1759 device->SetRenderState(D3DRS_COLORWRITEENABLE, (colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
1760 (colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
1761 (colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
1762 (colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
1763 }
1764 else
1765 {
1766 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1767 }
1768
1769 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
1770 {
1771 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1772 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
1773 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
1774 device->SetRenderState(D3DRS_STENCILREF, stencil);
1775 device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001776 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001777 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
1778 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
1779 }
1780 else
1781 {
1782 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1783 }
1784
1785 device->SetPixelShader(NULL);
1786 device->SetVertexShader(NULL);
1787 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1788
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001789 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001790 {
1791 float x, y, z, w;
1792 D3DCOLOR diffuse;
1793 };
1794
1795 Vertex quad[4];
1796 quad[0].x = 0.0f;
1797 quad[0].y = (float)desc.Height;
1798 quad[0].z = 0.0f;
1799 quad[0].w = 1.0f;
1800 quad[0].diffuse = color;
1801
1802 quad[1].x = (float)desc.Width;
1803 quad[1].y = (float)desc.Height;
1804 quad[1].z = 0.0f;
1805 quad[1].w = 1.0f;
1806 quad[1].diffuse = color;
1807
1808 quad[2].x = 0.0f;
1809 quad[2].y = 0.0f;
1810 quad[2].z = 0.0f;
1811 quad[2].w = 1.0f;
1812 quad[2].diffuse = color;
1813
1814 quad[3].x = (float)desc.Width;
1815 quad[3].y = 0.0f;
1816 quad[3].z = 0.0f;
1817 quad[3].w = 1.0f;
1818 quad[3].diffuse = color;
1819
1820 device->BeginScene();
1821 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
1822 device->EndScene();
1823
1824 if (flags & D3DCLEAR_ZBUFFER)
1825 {
1826 device->SetRenderState(D3DRS_ZENABLE, TRUE);
1827 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
1828 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
1829 }
1830 }
1831 else
1832 {
1833 device->Clear(0, NULL, flags, color, depth, stencil);
1834 }
1835}
1836
1837void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
1838{
1839 if (!currentProgram)
1840 {
1841 return error(GL_INVALID_OPERATION);
1842 }
1843
1844 IDirect3DDevice9 *device = getDevice();
1845 D3DPRIMITIVETYPE primitiveType;
1846 int primitiveCount;
1847
1848 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1849 return error(GL_INVALID_ENUM);
1850
1851 if (primitiveCount <= 0)
1852 {
1853 return;
1854 }
1855
1856 if (!applyRenderTarget(false))
1857 {
1858 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1859 }
1860
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001861 applyState(mode);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001862 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001863 applyShaders();
1864 applyTextures();
1865
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001866 if (!cullSkipsDraw(mode))
1867 {
1868 device->BeginScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001869 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001870 device->EndScene();
1871 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001872}
1873
1874void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
1875{
1876 if (!currentProgram)
1877 {
1878 return error(GL_INVALID_OPERATION);
1879 }
1880
1881 if (!indices && !elementArrayBuffer)
1882 {
1883 return error(GL_INVALID_OPERATION);
1884 }
1885
1886 IDirect3DDevice9 *device = getDevice();
1887 D3DPRIMITIVETYPE primitiveType;
1888 int primitiveCount;
1889
1890 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1891 return error(GL_INVALID_ENUM);
1892
1893 if (primitiveCount <= 0)
1894 {
1895 return;
1896 }
1897
1898 if (!applyRenderTarget(false))
1899 {
1900 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1901 }
1902
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001903 applyState(mode);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001904 TranslatedIndexData indexInfo = applyIndexBuffer(indices, count, mode, type);
1905 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001906 applyShaders();
1907 applyTextures();
1908
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001909 if (!cullSkipsDraw(mode))
1910 {
1911 device->BeginScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001912 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 +00001913 device->EndScene();
1914 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001915}
1916
1917void Context::finish()
1918{
1919 IDirect3DDevice9 *device = getDevice();
1920 IDirect3DQuery9 *occlusionQuery = NULL;
1921
1922 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
1923
1924 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1925 {
1926 return error(GL_OUT_OF_MEMORY);
1927 }
1928
1929 ASSERT(SUCCEEDED(result));
1930
1931 if (occlusionQuery)
1932 {
1933 occlusionQuery->Issue(D3DISSUE_BEGIN);
1934
1935 // Render something outside the render target
1936 device->SetPixelShader(NULL);
1937 device->SetVertexShader(NULL);
1938 device->SetFVF(D3DFVF_XYZRHW);
1939 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
1940 device->BeginScene();
1941 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
1942 device->EndScene();
1943
1944 occlusionQuery->Issue(D3DISSUE_END);
1945
1946 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1947 {
1948 // Keep polling, but allow other threads to do something useful first
1949 Sleep(0);
1950 }
1951
1952 occlusionQuery->Release();
1953 }
1954}
1955
1956void Context::flush()
1957{
1958 IDirect3DDevice9 *device = getDevice();
1959 IDirect3DQuery9 *eventQuery = NULL;
1960
1961 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
1962
1963 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1964 {
1965 return error(GL_OUT_OF_MEMORY);
1966 }
1967
1968 ASSERT(SUCCEEDED(result));
1969
1970 if (eventQuery)
1971 {
1972 eventQuery->Issue(D3DISSUE_END);
1973
1974 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1975 {
1976 // Keep polling, but allow other threads to do something useful first
1977 Sleep(0);
1978 }
1979
1980 eventQuery->Release();
1981 }
1982}
1983
1984void Context::recordInvalidEnum()
1985{
1986 mInvalidEnum = true;
1987}
1988
1989void Context::recordInvalidValue()
1990{
1991 mInvalidValue = true;
1992}
1993
1994void Context::recordInvalidOperation()
1995{
1996 mInvalidOperation = true;
1997}
1998
1999void Context::recordOutOfMemory()
2000{
2001 mOutOfMemory = true;
2002}
2003
2004void Context::recordInvalidFramebufferOperation()
2005{
2006 mInvalidFramebufferOperation = true;
2007}
2008
2009// Get one of the recorded errors and clear its flag, if any.
2010// [OpenGL ES 2.0.24] section 2.5 page 13.
2011GLenum Context::getError()
2012{
2013 if (mInvalidEnum)
2014 {
2015 mInvalidEnum = false;
2016
2017 return GL_INVALID_ENUM;
2018 }
2019
2020 if (mInvalidValue)
2021 {
2022 mInvalidValue = false;
2023
2024 return GL_INVALID_VALUE;
2025 }
2026
2027 if (mInvalidOperation)
2028 {
2029 mInvalidOperation = false;
2030
2031 return GL_INVALID_OPERATION;
2032 }
2033
2034 if (mOutOfMemory)
2035 {
2036 mOutOfMemory = false;
2037
2038 return GL_OUT_OF_MEMORY;
2039 }
2040
2041 if (mInvalidFramebufferOperation)
2042 {
2043 mInvalidFramebufferOperation = false;
2044
2045 return GL_INVALID_FRAMEBUFFER_OPERATION;
2046 }
2047
2048 return GL_NO_ERROR;
2049}
2050
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002051const char *Context::getPixelShaderProfile()
2052{
2053 return mPsProfile;
2054}
2055
2056const char *Context::getVertexShaderProfile()
2057{
2058 return mVsProfile;
2059}
2060
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002061void Context::detachBuffer(GLuint buffer)
2062{
2063 // [OpenGL ES 2.0.24] section 2.9 page 22:
2064 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2065 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2066
2067 if (arrayBuffer == buffer)
2068 {
2069 arrayBuffer = 0;
2070 }
2071
2072 if (elementArrayBuffer == buffer)
2073 {
2074 elementArrayBuffer = 0;
2075 }
2076
2077 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2078 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002079 if (vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002080 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002081 vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002082 }
2083 }
2084}
2085
2086void Context::detachTexture(GLuint texture)
2087{
2088 // [OpenGL ES 2.0.24] section 3.8 page 84:
2089 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2090 // rebound to texture object zero
2091
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002092 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002093 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002094 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002095 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002096 if (samplerTexture[type][sampler] == texture)
2097 {
2098 samplerTexture[type][sampler] = 0;
2099 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002100 }
2101 }
2102
2103 // [OpenGL ES 2.0.24] section 4.4 page 112:
2104 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2105 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2106 // image was attached in the currently bound framebuffer.
2107
2108 Framebuffer *framebuffer = getFramebuffer();
2109
2110 if (framebuffer)
2111 {
2112 framebuffer->detachTexture(texture);
2113 }
2114}
2115
2116void Context::detachFramebuffer(GLuint framebuffer)
2117{
2118 // [OpenGL ES 2.0.24] section 4.4 page 107:
2119 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2120 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2121
2122 if (this->framebuffer == framebuffer)
2123 {
2124 bindFramebuffer(0);
2125 }
2126}
2127
2128void Context::detachRenderbuffer(GLuint renderbuffer)
2129{
2130 // [OpenGL ES 2.0.24] section 4.4 page 109:
2131 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2132 // had been executed with the target RENDERBUFFER and name of zero.
2133
2134 if (this->renderbuffer == renderbuffer)
2135 {
2136 bindRenderbuffer(0);
2137 }
2138
2139 // [OpenGL ES 2.0.24] section 4.4 page 111:
2140 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2141 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2142 // point to which this image was attached in the currently bound framebuffer.
2143
2144 Framebuffer *framebuffer = getFramebuffer();
2145
2146 if (framebuffer)
2147 {
2148 framebuffer->detachRenderbuffer(renderbuffer);
2149 }
2150}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002151
2152Texture *Context::getIncompleteTexture(SamplerType type)
2153{
2154 Texture *t = mIncompleteTextures[type];
2155
2156 if (t == NULL)
2157 {
2158 static const GLubyte color[] = { 0, 0, 0, 255 };
2159
2160 switch (type)
2161 {
2162 default:
2163 UNREACHABLE();
2164 // default falls through to SAMPLER_2D
2165
2166 case SAMPLER_2D:
2167 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002168 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002169 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002170 t = incomplete2d;
2171 }
2172 break;
2173
2174 case SAMPLER_CUBE:
2175 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002176 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002177
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002178 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2179 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2180 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2181 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2182 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2183 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002184
2185 t = incompleteCube;
2186 }
2187 break;
2188 }
2189
2190 mIncompleteTextures[type] = t;
2191 }
2192
2193 return t;
2194}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002195
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002196bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002197{
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002198 return cullFace && cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002199}
2200
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002201bool Context::isTriangleMode(GLenum drawMode)
2202{
2203 switch (drawMode)
2204 {
2205 case GL_TRIANGLES:
2206 case GL_TRIANGLE_FAN:
2207 case GL_TRIANGLE_STRIP:
2208 return true;
2209 case GL_POINTS:
2210 case GL_LINES:
2211 case GL_LINE_LOOP:
2212 case GL_LINE_STRIP:
2213 return false;
2214 default: UNREACHABLE();
2215 }
2216
2217 return false;
2218}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002219}
2220
2221extern "C"
2222{
2223gl::Context *glCreateContext(const egl::Config *config)
2224{
2225 return new gl::Context(config);
2226}
2227
2228void glDestroyContext(gl::Context *context)
2229{
2230 delete context;
2231
2232 if (context == gl::getContext())
2233 {
2234 gl::makeCurrent(NULL, NULL, NULL);
2235 }
2236}
2237
2238void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2239{
2240 gl::makeCurrent(context, display, surface);
2241}
2242
2243gl::Context *glGetCurrentContext()
2244{
2245 return gl::getContext();
2246}
2247}