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