1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief GL Rendering Context.
22 *//*--------------------------------------------------------------------*/
23
24#include "sglrGLContext.hpp"
25#include "sglrShaderProgram.hpp"
26#include "gluPixelTransfer.hpp"
27#include "gluTexture.hpp"
28#include "gluCallLogWrapper.hpp"
29#include "gluStrUtil.hpp"
30#include "glwFunctions.hpp"
31#include "glwEnums.hpp"
32
33namespace sglr
34{
35
36using std::vector;
37using std::string;
38using tcu::TestLog;
39using tcu::Vec4;
40using tcu::TextureFormat;
41
42GLContext::GLContext (const glu::RenderContext& context, tcu::TestLog& log, deUint32 logFlags, const tcu::IVec4& baseViewport)
43	: Context					(context.getType())
44	, m_context					(context)
45	, m_log						(log)
46	, m_logFlags				(logFlags)
47	, m_baseViewport			(baseViewport)
48	, m_curViewport				(0, 0, m_baseViewport.z(), m_baseViewport.w())
49	, m_curScissor				(0, 0, m_baseViewport.z(), m_baseViewport.w())
50	, m_readFramebufferBinding	(0)
51	, m_drawFramebufferBinding	(0)
52	, m_wrapper					(DE_NULL)
53{
54	const glw::Functions& gl = m_context.getFunctions();
55
56	// Logging?
57	m_wrapper = new glu::CallLogWrapper(gl, log);
58	m_wrapper->enableLogging((logFlags & GLCONTEXT_LOG_CALLS) != 0);
59
60	// Setup base viewport. This offset is active when default framebuffer is active.
61	// \note Calls related to setting up base viewport are not included in log.
62	gl.viewport(baseViewport.x(), baseViewport.y(), baseViewport.z(), baseViewport.w());
63}
64
65GLContext::~GLContext (void)
66{
67	const glw::Functions& gl = m_context.getFunctions();
68
69	// Clean up all still alive objects
70	for (std::set<deUint32>::const_iterator i = m_allocatedFbos.begin();
71		 i != m_allocatedFbos.end(); i++)
72	{
73		deUint32 fbo = *i;
74		gl.deleteFramebuffers(1, &fbo);
75	}
76
77	for (std::set<deUint32>::const_iterator i = m_allocatedRbos.begin();
78		 i != m_allocatedRbos.end(); i++)
79	{
80		deUint32 rbo = *i;
81		gl.deleteRenderbuffers(1, &rbo);
82	}
83
84	for (std::set<deUint32>::const_iterator i = m_allocatedTextures.begin();
85		 i != m_allocatedTextures.end(); i++)
86	{
87		deUint32 tex = *i;
88		gl.deleteTextures(1, &tex);
89	}
90
91	for (std::set<deUint32>::const_iterator i = m_allocatedBuffers.begin();
92		 i != m_allocatedBuffers.end(); i++)
93	{
94		deUint32 buf = *i;
95		gl.deleteBuffers(1, &buf);
96	}
97
98	for (std::set<deUint32>::const_iterator i = m_allocatedVaos.begin();
99		 i != m_allocatedVaos.end(); i++)
100	{
101		deUint32 vao = *i;
102		gl.deleteVertexArrays(1, &vao);
103	}
104
105	for (std::vector<glu::ShaderProgram*>::iterator i = m_programs.begin();
106		i != m_programs.end(); i++)
107	{
108		delete *i;
109	}
110
111	gl.useProgram(0);
112
113	delete m_wrapper;
114}
115
116void GLContext::enableLogging (deUint32 logFlags)
117{
118	m_logFlags = logFlags;
119	m_wrapper->enableLogging((logFlags & GLCONTEXT_LOG_CALLS) != 0);
120}
121
122tcu::IVec2 GLContext::getDrawOffset (void) const
123{
124	if (m_drawFramebufferBinding)
125		return tcu::IVec2(0, 0);
126	else
127		return tcu::IVec2(m_baseViewport.x(), m_baseViewport.y());
128}
129
130tcu::IVec2 GLContext::getReadOffset (void) const
131{
132	if (m_readFramebufferBinding)
133		return tcu::IVec2(0, 0);
134	else
135		return tcu::IVec2(m_baseViewport.x(), m_baseViewport.y());
136}
137
138int GLContext::getWidth (void) const
139{
140	return m_baseViewport.z();
141}
142
143int GLContext::getHeight (void) const
144{
145	return m_baseViewport.w();
146}
147
148void GLContext::activeTexture (deUint32 texture)
149{
150	m_wrapper->glActiveTexture(texture);
151}
152
153void GLContext::texParameteri (deUint32 target, deUint32 pname, int value)
154{
155	m_wrapper->glTexParameteri(target, pname, value);
156}
157
158deUint32 GLContext::checkFramebufferStatus(deUint32 target)
159{
160	return m_wrapper->glCheckFramebufferStatus(target);
161}
162
163void GLContext::viewport (int x, int y, int width, int height)
164{
165	m_curViewport = tcu::IVec4(x, y, width, height);
166	tcu::IVec2 offset = getDrawOffset();
167
168	// \note For clarity don't add the offset to log
169	if ((m_logFlags & GLCONTEXT_LOG_CALLS) != 0)
170		m_log << TestLog::Message << "glViewport(" << x << ", " << y << ", " << width << ", " << height << ");" << TestLog::EndMessage;
171	m_context.getFunctions().viewport(x+offset.x(), y+offset.y(), width, height);
172}
173
174void GLContext::bindTexture (deUint32 target, deUint32 texture)
175{
176	m_allocatedTextures.insert(texture);
177	m_wrapper->glBindTexture(target, texture);
178}
179
180void GLContext::genTextures (int numTextures, deUint32* textures)
181{
182	m_wrapper->glGenTextures(numTextures, textures);
183	if (numTextures > 0)
184		m_allocatedTextures.insert(textures, textures+numTextures);
185}
186
187void GLContext::deleteTextures (int numTextures, const deUint32* textures)
188{
189	for (int i = 0; i < numTextures; i++)
190		m_allocatedTextures.erase(textures[i]);
191	m_wrapper->glDeleteTextures(numTextures, textures);
192}
193
194void GLContext::bindFramebuffer (deUint32 target, deUint32 framebuffer)
195{
196	// \todo [2011-10-13 pyry] This is a bit of a hack since test cases assumes 0 default fbo.
197	deUint32 defaultFbo = m_context.getDefaultFramebuffer();
198	TCU_CHECK(framebuffer == 0 || framebuffer != defaultFbo);
199
200	bool isValidTarget = target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER;
201
202	if (isValidTarget && framebuffer != 0)
203		m_allocatedFbos.insert(framebuffer);
204
205	// Update bindings.
206	if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER)
207		m_readFramebufferBinding = framebuffer;
208
209	if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER)
210		m_drawFramebufferBinding = framebuffer;
211
212	if (framebuffer == 0) // Redirect 0 to platform-defined default framebuffer.
213		m_wrapper->glBindFramebuffer(target, defaultFbo);
214	else
215		m_wrapper->glBindFramebuffer(target, framebuffer);
216
217	// Update viewport and scissor if we updated draw framebuffer binding \note Not logged for clarity
218	if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER)
219	{
220		tcu::IVec2 offset = getDrawOffset();
221		m_context.getFunctions().viewport(m_curViewport.x()+offset.x(), m_curViewport.y()+offset.y(), m_curViewport.z(), m_curViewport.w());
222		m_context.getFunctions().scissor(m_curScissor.x()+offset.x(), m_curScissor.y()+offset.y(), m_curScissor.z(), m_curScissor.w());
223	}
224}
225
226void GLContext::genFramebuffers (int numFramebuffers, deUint32* framebuffers)
227{
228	m_wrapper->glGenFramebuffers(numFramebuffers, framebuffers);
229	if (numFramebuffers > 0)
230		m_allocatedFbos.insert(framebuffers, framebuffers+numFramebuffers);
231}
232
233void GLContext::deleteFramebuffers (int numFramebuffers, const deUint32* framebuffers)
234{
235	for (int i = 0; i < numFramebuffers; i++)
236		m_allocatedFbos.erase(framebuffers[i]);
237	m_wrapper->glDeleteFramebuffers(numFramebuffers, framebuffers);
238}
239
240void GLContext::bindRenderbuffer (deUint32 target, deUint32 renderbuffer)
241{
242	m_allocatedRbos.insert(renderbuffer);
243	m_wrapper->glBindRenderbuffer(target, renderbuffer);
244}
245
246void GLContext::genRenderbuffers (int numRenderbuffers, deUint32* renderbuffers)
247{
248	m_wrapper->glGenRenderbuffers(numRenderbuffers, renderbuffers);
249	if (numRenderbuffers > 0)
250		m_allocatedRbos.insert(renderbuffers, renderbuffers+numRenderbuffers);
251}
252
253void GLContext::deleteRenderbuffers (int numRenderbuffers, const deUint32* renderbuffers)
254{
255	for (int i = 0; i < numRenderbuffers; i++)
256		m_allocatedRbos.erase(renderbuffers[i]);
257	m_wrapper->glDeleteRenderbuffers(numRenderbuffers, renderbuffers);
258}
259
260void GLContext::pixelStorei (deUint32 pname, int param)
261{
262	m_wrapper->glPixelStorei(pname, param);
263}
264
265void GLContext::texImage1D (deUint32 target, int level, deUint32 internalFormat, int width, int border, deUint32 format, deUint32 type, const void* data)
266{
267	m_wrapper->glTexImage1D(target, level, internalFormat, width, border, format, type, data);
268}
269
270void GLContext::texImage2D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int border, deUint32 format, deUint32 type, const void* data)
271{
272	m_wrapper->glTexImage2D(target, level, internalFormat, width, height, border, format, type, data);
273}
274
275void GLContext::texImage3D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int depth, int border, deUint32 format, deUint32 type, const void* data)
276{
277	m_wrapper->glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, data);
278}
279
280void GLContext::texSubImage1D (deUint32 target, int level, int xoffset, int width, deUint32 format, deUint32 type, const void* data)
281{
282	m_wrapper->glTexSubImage1D(target, level, xoffset, width, format, type, data);
283}
284
285void GLContext::texSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int width, int height, deUint32 format, deUint32 type, const void* data)
286{
287	m_wrapper->glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, data);
288}
289
290void GLContext::texSubImage3D (deUint32 target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, deUint32 format, deUint32 type, const void* data)
291{
292	m_wrapper->glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
293}
294
295void GLContext::copyTexImage1D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int border)
296{
297	// Don't log offset.
298	if ((m_logFlags & GLCONTEXT_LOG_CALLS) != 0)
299		m_log << TestLog::Message << "glCopyTexImage1D("
300								  << glu::getTextureTargetStr(target) << ", "
301								  << level << ", "
302								  << glu::getTextureFormatStr(internalFormat) << ", "
303								  << x << ", " << y << ", "
304								  << width << ", " << border << ")"
305			  << TestLog::EndMessage;
306
307	tcu::IVec2 offset = getReadOffset();
308	m_context.getFunctions().copyTexImage1D(target, level, internalFormat, offset.x()+x, offset.y()+y, width, border);
309}
310
311void GLContext::copyTexImage2D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int height, int border)
312{
313	// Don't log offset.
314	if ((m_logFlags & GLCONTEXT_LOG_CALLS) != 0)
315		m_log << TestLog::Message << "glCopyTexImage2D("
316								  << glu::getTextureTargetStr(target) << ", "
317								  << level << ", "
318								  << glu::getTextureFormatStr(internalFormat) << ", "
319								  << x << ", " << y << ", "
320								  << width << ", " << height
321								  << ", " << border << ")"
322			  << TestLog::EndMessage;
323
324	tcu::IVec2 offset = getReadOffset();
325	m_context.getFunctions().copyTexImage2D(target, level, internalFormat, offset.x()+x, offset.y()+y, width, height, border);
326}
327
328void GLContext::copyTexSubImage1D (deUint32 target, int level, int xoffset, int x, int y, int width)
329{
330	if ((m_logFlags & GLCONTEXT_LOG_CALLS) != 0)
331		m_log << TestLog::Message << "glCopyTexSubImage1D("
332								  << glu::getTextureTargetStr(target) << ", "
333								  << level << ", "
334								  << xoffset << ", "
335								  << x << ", " << y << ", "
336								  << width << ")"
337			  << TestLog::EndMessage;
338
339	tcu::IVec2 offset = getReadOffset();
340	m_context.getFunctions().copyTexSubImage1D(target, level, xoffset, offset.x()+x, offset.y()+y, width);
341}
342
343void GLContext::copyTexSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int x, int y, int width, int height)
344{
345	if ((m_logFlags & GLCONTEXT_LOG_CALLS) != 0)
346		m_log << TestLog::Message << "glCopyTexSubImage2D("
347								  << glu::getTextureTargetStr(target) << ", "
348								  << level
349								  << ", " << xoffset << ", " << yoffset << ", "
350								  << x << ", " << y << ", "
351								  << width << ", " << height << ")"
352			  << TestLog::EndMessage;
353
354	tcu::IVec2 offset = getReadOffset();
355	m_context.getFunctions().copyTexSubImage2D(target, level, xoffset, yoffset, offset.x()+x, offset.y()+y, width, height);
356}
357
358void GLContext::copyTexSubImage3D (deUint32 target, int level, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height)
359{
360	if ((m_logFlags & GLCONTEXT_LOG_CALLS) != 0)
361		m_log << TestLog::Message << "glCopyTexSubImage3D("
362								  << glu::getTextureTargetStr(target) << ", "
363								  << level
364								  << ", " << xoffset << ", " << yoffset << ", " << zoffset << ", "
365								  << x << ", " << y << ", "
366								  << width << ", " << height << ")"
367			  << TestLog::EndMessage;
368
369	tcu::IVec2 offset = getReadOffset();
370	m_context.getFunctions().copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, offset.x()+x, offset.y()+y, width, height);
371}
372
373void GLContext::texStorage2D (deUint32 target, int levels, deUint32 internalFormat, int width, int height)
374{
375	m_wrapper->glTexStorage2D(target, levels, internalFormat, width, height);
376}
377
378void GLContext::texStorage3D (deUint32 target, int levels, deUint32 internalFormat, int width, int height, int depth)
379{
380	m_wrapper->glTexStorage3D(target, levels, internalFormat, width, height, depth);
381}
382
383void GLContext::framebufferTexture2D (deUint32 target, deUint32 attachment, deUint32 textarget, deUint32 texture, int level)
384{
385	m_wrapper->glFramebufferTexture2D(target, attachment, textarget, texture, level);
386}
387
388void GLContext::framebufferTextureLayer (deUint32 target, deUint32 attachment, deUint32 texture, int level, int layer)
389{
390	m_wrapper->glFramebufferTextureLayer(target, attachment, texture, level, layer);
391}
392
393void GLContext::framebufferRenderbuffer (deUint32 target, deUint32 attachment, deUint32 renderbuffertarget, deUint32 renderbuffer)
394{
395	m_wrapper->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
396}
397
398void GLContext::getFramebufferAttachmentParameteriv (deUint32 target, deUint32 attachment, deUint32 pname, int* params)
399{
400	m_wrapper->glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
401}
402
403void GLContext::renderbufferStorage (deUint32 target, deUint32 internalformat, int width, int height)
404{
405	m_wrapper->glRenderbufferStorage(target, internalformat, width, height);
406}
407
408void GLContext::renderbufferStorageMultisample (deUint32 target, int samples, deUint32 internalFormat, int width, int height)
409{
410	m_wrapper->glRenderbufferStorageMultisample(target, samples, internalFormat, width, height);
411}
412
413void GLContext::bindBuffer (deUint32 target, deUint32 buffer)
414{
415	m_allocatedBuffers.insert(buffer);
416	m_wrapper->glBindBuffer(target, buffer);
417}
418
419void GLContext::genBuffers (int numBuffers, deUint32* buffers)
420{
421	m_wrapper->glGenBuffers(numBuffers, buffers);
422	if (numBuffers > 0)
423		m_allocatedBuffers.insert(buffers, buffers+numBuffers);
424}
425
426void GLContext::deleteBuffers (int numBuffers, const deUint32* buffers)
427{
428	m_wrapper->glDeleteBuffers(numBuffers, buffers);
429	for (int i = 0; i < numBuffers; i++)
430		m_allocatedBuffers.erase(buffers[i]);
431}
432
433void GLContext::bufferData (deUint32 target, deIntptr size, const void* data, deUint32 usage)
434{
435	m_wrapper->glBufferData(target, (glw::GLsizeiptr)size, data, usage);
436}
437
438void GLContext::bufferSubData (deUint32 target, deIntptr offset, deIntptr size, const void* data)
439{
440	m_wrapper->glBufferSubData(target, (glw::GLintptr)offset, (glw::GLsizeiptr)size, data);
441}
442
443void GLContext::clearColor (float red, float green, float blue, float alpha)
444{
445	m_wrapper->glClearColor(red, green, blue, alpha);
446}
447
448void GLContext::clearDepthf (float depth)
449{
450	m_wrapper->glClearDepthf(depth);
451}
452
453void GLContext::clearStencil (int stencil)
454{
455	m_wrapper->glClearStencil(stencil);
456}
457
458void GLContext::clear (deUint32 buffers)
459{
460	m_wrapper->glClear(buffers);
461}
462
463void GLContext::clearBufferiv (deUint32 buffer, int drawbuffer, const int* value)
464{
465	m_wrapper->glClearBufferiv(buffer, drawbuffer, value);
466}
467
468void GLContext::clearBufferfv (deUint32 buffer, int drawbuffer, const float* value)
469{
470	m_wrapper->glClearBufferfv(buffer, drawbuffer, value);
471}
472
473void GLContext::clearBufferuiv (deUint32 buffer, int drawbuffer, const deUint32* value)
474{
475	m_wrapper->glClearBufferuiv(buffer, drawbuffer, value);
476}
477
478void GLContext::clearBufferfi (deUint32 buffer, int drawbuffer, float depth, int stencil)
479{
480	m_wrapper->glClearBufferfi(buffer, drawbuffer, depth, stencil);
481}
482
483void GLContext::scissor (int x, int y, int width, int height)
484{
485	m_curScissor = tcu::IVec4(x, y, width, height);
486
487	// \note For clarity don't add the offset to log
488	if ((m_logFlags & GLCONTEXT_LOG_CALLS) != 0)
489		m_log << TestLog::Message << "glScissor(" << x << ", " << y << ", " << width << ", " << height << ");" << TestLog::EndMessage;
490
491	tcu::IVec2 offset = getDrawOffset();
492	m_context.getFunctions().scissor(offset.x()+x, offset.y()+y, width, height);
493}
494
495void GLContext::enable (deUint32 cap)
496{
497	m_wrapper->glEnable(cap);
498}
499
500void GLContext::disable (deUint32 cap)
501{
502	m_wrapper->glDisable(cap);
503}
504
505void GLContext::stencilFunc (deUint32 func, int ref, deUint32 mask)
506{
507	m_wrapper->glStencilFunc(func, ref, mask);
508}
509
510void GLContext::stencilOp (deUint32 sfail, deUint32 dpfail, deUint32 dppass)
511{
512	m_wrapper->glStencilOp(sfail, dpfail, dppass);
513}
514
515void GLContext::depthFunc (deUint32 func)
516{
517	m_wrapper->glDepthFunc(func);
518}
519
520void GLContext::depthRangef (float n, float f)
521{
522	m_wrapper->glDepthRangef(n, f);
523}
524
525void GLContext::depthRange (double n, double f)
526{
527	m_wrapper->glDepthRange(n, f);
528}
529
530void GLContext::polygonOffset (float factor, float units)
531{
532	m_wrapper->glPolygonOffset(factor, units);
533}
534
535void GLContext::provokingVertex (deUint32 convention)
536{
537	m_wrapper->glProvokingVertex(convention);
538}
539
540void GLContext::primitiveRestartIndex (deUint32 index)
541{
542	m_wrapper->glPrimitiveRestartIndex(index);
543}
544
545void GLContext::stencilFuncSeparate (deUint32 face, deUint32 func, int ref, deUint32 mask)
546{
547	m_wrapper->glStencilFuncSeparate(face, func, ref, mask);
548}
549
550void GLContext::stencilOpSeparate (deUint32 face, deUint32 sfail, deUint32 dpfail, deUint32 dppass)
551{
552	m_wrapper->glStencilOpSeparate(face, sfail, dpfail, dppass);
553}
554
555void GLContext::blendEquation (deUint32 mode)
556{
557	m_wrapper->glBlendEquation(mode);
558}
559
560void GLContext::blendEquationSeparate (deUint32 modeRGB, deUint32 modeAlpha)
561{
562	m_wrapper->glBlendEquationSeparate(modeRGB, modeAlpha);
563}
564
565void GLContext::blendFunc (deUint32 src, deUint32 dst)
566{
567	m_wrapper->glBlendFunc(src, dst);
568}
569
570void GLContext::blendFuncSeparate (deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
571{
572	m_wrapper->glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
573}
574
575void GLContext::blendColor (float red, float green, float blue, float alpha)
576{
577	m_wrapper->glBlendColor(red, green, blue, alpha);
578}
579
580void GLContext::colorMask (deBool r, deBool g, deBool b, deBool a)
581{
582	m_wrapper->glColorMask((glw::GLboolean)r, (glw::GLboolean)g, (glw::GLboolean)b, (glw::GLboolean)a);
583}
584
585void GLContext::depthMask (deBool mask)
586{
587	m_wrapper->glDepthMask((glw::GLboolean)mask);
588}
589
590void GLContext::stencilMask (deUint32 mask)
591{
592	m_wrapper->glStencilMask(mask);
593}
594
595void GLContext::stencilMaskSeparate (deUint32 face, deUint32 mask)
596{
597	m_wrapper->glStencilMaskSeparate(face, mask);
598}
599
600void GLContext::blitFramebuffer (int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, deUint32 mask, deUint32 filter)
601{
602	tcu::IVec2	drawOffset	= getDrawOffset();
603	tcu::IVec2	readOffset	= getReadOffset();
604
605	if ((m_logFlags & GLCONTEXT_LOG_CALLS) != 0)
606		m_log << TestLog::Message << "glBlitFramebuffer("
607								  << srcX0 << ", " << srcY0 << ", " << srcX1 << ", " << srcY1 << ", "
608								  << dstX0 << ", " << dstY0 << ", " << dstX1 << ", " << dstY1 << ", "
609								  << glu::getBufferMaskStr(mask) << ", "
610								  << glu::getTextureFilterStr(filter) << ")"
611			  << TestLog::EndMessage;
612
613	m_context.getFunctions().blitFramebuffer(readOffset.x()+srcX0, readOffset.y()+srcY0, readOffset.x()+srcX1, readOffset.y()+srcY1,
614											 drawOffset.x()+dstX0, drawOffset.y()+dstY0, drawOffset.x()+dstX1, drawOffset.y()+dstY1,
615											 mask, filter);
616}
617
618void GLContext::invalidateSubFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments, int x, int y, int width, int height)
619{
620	tcu::IVec2 drawOffset = getDrawOffset();
621
622	if ((m_logFlags & GLCONTEXT_LOG_CALLS) != 0)
623		m_log << TestLog::Message << "glInvalidateSubFramebuffer("
624								  << glu::getFramebufferTargetStr(target) << ", " << numAttachments << ", "
625								  << glu::getInvalidateAttachmentStr(attachments, numAttachments) << ", "
626								  << x << ", " << y << ", " << width << ", " << height << ")"
627			  << TestLog::EndMessage;
628
629	m_context.getFunctions().invalidateSubFramebuffer(target, numAttachments, attachments, x+drawOffset.x(), y+drawOffset.y(), width, height);
630}
631
632void GLContext::invalidateFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments)
633{
634	m_wrapper->glInvalidateFramebuffer(target, numAttachments, attachments);
635}
636
637void GLContext::bindVertexArray (deUint32 array)
638{
639	m_wrapper->glBindVertexArray(array);
640}
641
642void GLContext::genVertexArrays (int numArrays, deUint32* vertexArrays)
643{
644	m_wrapper->glGenVertexArrays(numArrays, vertexArrays);
645	if (numArrays > 0)
646		m_allocatedVaos.insert(vertexArrays, vertexArrays+numArrays);
647}
648
649void GLContext::deleteVertexArrays (int numArrays, const deUint32* vertexArrays)
650{
651	for (int i = 0; i < numArrays; i++)
652		m_allocatedVaos.erase(vertexArrays[i]);
653	m_wrapper->glDeleteVertexArrays(numArrays, vertexArrays);
654}
655
656void GLContext::vertexAttribPointer (deUint32 index, int size, deUint32 type, deBool normalized, int stride, const void *pointer)
657{
658	m_wrapper->glVertexAttribPointer(index, size, type, (glw::GLboolean)normalized, stride, pointer);
659}
660
661void GLContext::vertexAttribIPointer (deUint32 index, int size, deUint32 type, int stride, const void *pointer)
662{
663	m_wrapper->glVertexAttribIPointer(index, size, type, stride, pointer);
664}
665
666void GLContext::enableVertexAttribArray (deUint32 index)
667{
668	m_wrapper->glEnableVertexAttribArray(index);
669}
670
671void GLContext::disableVertexAttribArray (deUint32 index)
672{
673	m_wrapper->glDisableVertexAttribArray(index);
674}
675
676void GLContext::vertexAttribDivisor (deUint32 index, deUint32 divisor)
677{
678	m_wrapper->glVertexAttribDivisor(index, divisor);
679}
680
681void GLContext::vertexAttrib1f (deUint32 index, float x)
682{
683	m_wrapper->glVertexAttrib1f(index, x);
684}
685
686void GLContext::vertexAttrib2f (deUint32 index, float x, float y)
687{
688	m_wrapper->glVertexAttrib2f(index, x, y);
689}
690
691void GLContext::vertexAttrib3f (deUint32 index, float x, float y, float z)
692{
693	m_wrapper->glVertexAttrib3f(index, x, y, z);
694}
695
696void GLContext::vertexAttrib4f (deUint32 index, float x, float y, float z, float w)
697{
698	m_wrapper->glVertexAttrib4f(index, x, y, z, w);
699}
700
701void GLContext::vertexAttribI4i (deUint32 index, deInt32 x, deInt32 y, deInt32 z, deInt32 w)
702{
703	m_wrapper->glVertexAttribI4i(index, x, y, z, w);
704}
705
706void GLContext::vertexAttribI4ui (deUint32 index, deUint32 x, deUint32 y, deUint32 z, deUint32 w)
707{
708	m_wrapper->glVertexAttribI4ui(index, x, y, z, w);
709}
710
711deInt32 GLContext::getAttribLocation (deUint32 program, const char *name)
712{
713	return m_wrapper->glGetAttribLocation(program, name);
714}
715
716void GLContext::uniform1f (deInt32 location, float v0)
717{
718	m_wrapper->glUniform1f(location, v0);
719}
720
721void GLContext::uniform1i (deInt32 location, deInt32 v0)
722{
723	m_wrapper->glUniform1i(location, v0);
724}
725
726void GLContext::uniform1fv (deInt32 location, deInt32 count, const float* value)
727{
728	m_wrapper->glUniform1fv(location, count, value);
729}
730
731void GLContext::uniform2fv (deInt32 location, deInt32 count, const float* value)
732{
733	m_wrapper->glUniform2fv(location, count, value);
734}
735
736void GLContext::uniform3fv (deInt32 location, deInt32 count, const float* value)
737{
738	m_wrapper->glUniform3fv(location, count, value);
739}
740
741void GLContext::uniform4fv (deInt32 location, deInt32 count, const float* value)
742{
743	m_wrapper->glUniform4fv(location, count, value);
744}
745
746void GLContext::uniform1iv (deInt32 location, deInt32 count, const deInt32* value)
747{
748	m_wrapper->glUniform1iv(location, count, value);
749}
750
751void GLContext::uniform2iv (deInt32 location, deInt32 count, const deInt32* value)
752{
753	m_wrapper->glUniform2iv(location, count, value);
754}
755
756void GLContext::uniform3iv (deInt32 location, deInt32 count, const deInt32* value)
757{
758	m_wrapper->glUniform3iv(location, count, value);
759}
760
761void GLContext::uniform4iv (deInt32 location, deInt32 count, const deInt32* value)
762{
763	m_wrapper->glUniform4iv(location, count, value);
764}
765
766void GLContext::uniformMatrix3fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
767{
768	m_wrapper->glUniformMatrix3fv(location, count, (glw::GLboolean)transpose, value);
769}
770
771void GLContext::uniformMatrix4fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
772{
773	m_wrapper->glUniformMatrix4fv(location, count, (glw::GLboolean)transpose, value);
774}
775deInt32 GLContext::getUniformLocation (deUint32 program, const char *name)
776{
777	return m_wrapper->glGetUniformLocation(program, name);
778}
779
780void GLContext::lineWidth (float w)
781{
782	m_wrapper->glLineWidth(w);
783}
784
785void GLContext::drawArrays (deUint32 mode, int first, int count)
786{
787	m_wrapper->glDrawArrays(mode, first, count);
788}
789
790void GLContext::drawArraysInstanced (deUint32 mode, int first, int count, int instanceCount)
791{
792	m_wrapper->glDrawArraysInstanced(mode, first, count, instanceCount);
793}
794
795void GLContext::drawElements (deUint32 mode, int count, deUint32 type, const void *indices)
796{
797	m_wrapper->glDrawElements(mode, count, type, indices);
798}
799
800void GLContext::drawElementsInstanced (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount)
801{
802	m_wrapper->glDrawElementsInstanced(mode, count, type, indices, instanceCount);
803}
804
805void GLContext::drawElementsBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int baseVertex)
806{
807	m_wrapper->glDrawElementsBaseVertex(mode, count, type, indices, baseVertex);
808}
809
810void GLContext::drawElementsInstancedBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount, int baseVertex)
811{
812	m_wrapper->glDrawElementsInstancedBaseVertex(mode, count, type, indices, instanceCount, baseVertex);
813}
814
815void GLContext::drawRangeElements (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices)
816{
817	m_wrapper->glDrawRangeElements(mode, start, end, count, type, indices);
818}
819
820void GLContext::drawRangeElementsBaseVertex (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices, int baseVertex)
821{
822	m_wrapper->glDrawRangeElementsBaseVertex(mode, start, end, count, type, indices, baseVertex);
823}
824
825void GLContext::drawArraysIndirect (deUint32 mode, const void *indirect)
826{
827	m_wrapper->glDrawArraysIndirect(mode, indirect);
828}
829
830void GLContext::drawElementsIndirect (deUint32 mode, deUint32 type, const void *indirect)
831{
832	m_wrapper->glDrawElementsIndirect(mode, type, indirect);
833}
834
835void GLContext::multiDrawArrays (deUint32 mode, const int* first, const int* count, int primCount)
836{
837	m_wrapper->glMultiDrawArrays(mode, first, count, primCount);
838}
839
840void GLContext::multiDrawElements (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount)
841{
842	m_wrapper->glMultiDrawElements(mode, count, type, indices, primCount);
843}
844
845void GLContext::multiDrawElementsBaseVertex (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount, const int* baseVertex)
846{
847	m_wrapper->glMultiDrawElementsBaseVertex(mode, count, type, indices, primCount, baseVertex);
848}
849
850deUint32 GLContext::createProgram (ShaderProgram* shader)
851{
852	m_programs.reserve(m_programs.size()+1);
853
854	glu::ShaderProgram* program = DE_NULL;
855
856	if (!shader->m_hasGeometryShader)
857		program = new glu::ShaderProgram(m_context, glu::makeVtxFragSources(shader->m_vertSrc, shader->m_fragSrc));
858	else
859		program = new glu::ShaderProgram(m_context,
860										 glu::ProgramSources() << glu::VertexSource(shader->m_vertSrc)
861															   << glu::FragmentSource(shader->m_fragSrc)
862															   << glu::GeometrySource(shader->m_geomSrc));
863
864	if (!program->isOk())
865	{
866		m_log << *program;
867		delete program;
868		TCU_FAIL("Compile failed");
869	}
870
871	if ((m_logFlags & GLCONTEXT_LOG_PROGRAMS) != 0)
872		m_log << *program;
873
874	m_programs.push_back(program);
875	return program->getProgram();
876}
877
878void GLContext::deleteProgram (deUint32 program)
879{
880	for (std::vector<glu::ShaderProgram*>::iterator i = m_programs.begin(); i != m_programs.end(); i++)
881	{
882		if ((*i)->getProgram() == program)
883		{
884			delete *i;
885			m_programs.erase(i);
886			return;
887		}
888	}
889
890	DE_FATAL("invalid delete");
891}
892
893void GLContext::useProgram (deUint32 program)
894{
895	m_wrapper->glUseProgram(program);
896}
897
898void GLContext::readPixels (int x, int y, int width, int height, deUint32 format, deUint32 type, void* data)
899{
900	// Don't log offset.
901	if ((m_logFlags & GLCONTEXT_LOG_CALLS) != 0)
902		m_log << TestLog::Message << "glReadPixels("
903								  << x << ", " << y << ", " << width << ", " << height << ", "
904								  << glu::getTextureFormatStr(format) << ", "
905								  << glu::getTypeStr(type) << ", " << data << ")"
906			  << TestLog::EndMessage;
907
908	tcu::IVec2 offset = getReadOffset();
909	m_context.getFunctions().readPixels(x+offset.x(), y+offset.y(), width, height, format, type, data);
910}
911
912deUint32 GLContext::getError (void)
913{
914	return m_wrapper->glGetError();
915}
916
917void GLContext::finish (void)
918{
919	m_wrapper->glFinish();
920}
921
922void GLContext::getIntegerv (deUint32 pname, int* params)
923{
924	m_wrapper->glGetIntegerv(pname, params);
925}
926
927const char* GLContext::getString (deUint32 pname)
928{
929	return (const char*)m_wrapper->glGetString(pname);
930}
931
932} // sglr
933