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