blob: f1f024c0dbb92e5a46664464a71959614eb05235 [file] [log] [blame]
[email protected]529c6672012-01-04 02:18:261// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]94307712012-11-16 23:26:1112#include <stack>
[email protected]f39f4b3f2010-05-12 17:04:0813#include <string>
14#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0615
[email protected]00eb49a2010-08-12 20:46:5716#include "base/at_exit.h"
[email protected]d353541f2012-05-03 22:45:4117#include "base/atomicops.h"
[email protected]9d37f062011-11-22 01:24:5218#include "base/bind.h"
[email protected]e844ae22012-01-14 03:36:2619#include "base/command_line.h"
[email protected]1078f912011-12-23 13:12:1420#include "base/debug/trace_event.h"
[email protected]e51bdf32011-11-23 22:21:4621#if defined(OS_MACOSX)
22#include "base/mac/scoped_cftyperef.h"
23#endif
[email protected]3b63f8f42011-03-28 01:54:1524#include "base/memory/scoped_ptr.h"
[email protected]f4390962013-06-11 07:29:2225#include "base/strings/string_number_conversions.h"
[email protected]d37231fa2010-04-09 21:16:0226#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3227#define GLES2_GPU_SERVICE 1
[email protected]f4390962013-06-11 07:29:2228#include "gpu/command_buffer/common/debug_marker_manager.h"
[email protected]96449d2c2009-11-25 00:01:3229#include "gpu/command_buffer/common/gles2_cmd_format.h"
30#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1031#include "gpu/command_buffer/common/id_allocator.h"
[email protected]2ad674132013-06-05 07:48:5132#include "gpu/command_buffer/common/mailbox.h"
[email protected]f4390962013-06-11 07:29:2233#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34#include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
[email protected]3916c97e2010-02-25 03:20:5035#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3236#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5037#include "gpu/command_buffer/service/context_group.h"
[email protected]e259eb412012-10-13 05:47:2438#include "gpu/command_buffer/service/context_state.h"
[email protected]d3eba342013-04-18 21:11:5039#include "gpu/command_buffer/service/error_state.h"
[email protected]915a59a12010-09-30 21:29:1140#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5841#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3242#include "gpu/command_buffer/service/gl_utils.h"
[email protected]43410e92012-04-20 17:06:2843#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
[email protected]ba3176a2009-12-16 18:19:4644#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]e844ae22012-01-14 03:36:2645#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]fb97b662013-02-20 23:02:1446#include "gpu/command_buffer/service/gpu_tracer.h"
[email protected]09d50362012-10-18 20:54:3747#include "gpu/command_buffer/service/image_manager.h"
[email protected]78b514b2012-05-01 21:50:5948#include "gpu/command_buffer/service/mailbox_manager.h"
[email protected]ff6493f2012-07-31 19:52:2549#include "gpu/command_buffer/service/memory_tracking.h"
[email protected]a93bb842010-02-16 23:03:4750#include "gpu/command_buffer/service/program_manager.h"
[email protected]882ba1e22012-03-08 19:02:5351#include "gpu/command_buffer/service/query_manager.h"
[email protected]a25fa872010-03-25 02:57:5852#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4753#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4554#include "gpu/command_buffer/service/shader_translator.h"
[email protected]87fb6ab2012-06-13 22:28:0455#include "gpu/command_buffer/service/shader_translator_cache.h"
[email protected]b0af4f52011-09-28 22:04:4256#include "gpu/command_buffer/service/stream_texture.h"
57#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]a93bb842010-02-16 23:03:4758#include "gpu/command_buffer/service/texture_manager.h"
[email protected]944b62f32012-09-27 02:20:4659#include "gpu/command_buffer/service/vertex_array_manager.h"
[email protected]f4390962013-06-11 07:29:2260#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]d8bc3ec2013-03-07 06:28:4061#include "ui/gl/gl_bindings.h"
[email protected]09d50362012-10-18 20:54:3762#include "ui/gl/gl_image.h"
[email protected]c9e2cbbb2012-05-12 21:17:2763#include "ui/gl/gl_implementation.h"
64#include "ui/gl/gl_surface.h"
[email protected]423e644f2013-06-19 00:48:2765
[email protected]e51bdf32011-11-23 22:21:4666#if defined(OS_MACOSX)
[email protected]423e644f2013-06-19 00:48:2767#include "ui/gl/io_surface_support_mac.h"
[email protected]e51bdf32011-11-23 22:21:4668#endif
[email protected]de17df392010-04-23 21:09:4169
[email protected]693ca512012-11-13 18:09:1370// TODO(zmo): we can't include "City.h" due to type def conflicts.
71extern uint64 CityHash64(const char*, size_t);
72
[email protected]a7a27ace2009-12-12 00:11:2573namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3274namespace gles2 {
75
[email protected]f0d74742011-10-03 16:31:0476namespace {
[email protected]693ca512012-11-13 18:09:1377
[email protected]f0d74742011-10-03 16:31:0478static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
[email protected]70dc60932013-06-04 03:33:4979static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
[email protected]aff39ac82013-06-08 04:53:1380static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
[email protected]693ca512012-11-13 18:09:1381
[email protected]3d944a82013-02-12 19:09:0282#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
[email protected]693ca512012-11-13 18:09:1383khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
84 return static_cast<khronos_uint64_t>(
85 CityHash64(name, static_cast<size_t>(len)));
86}
[email protected]3d944a82013-02-12 19:09:0287#endif
[email protected]693ca512012-11-13 18:09:1388
[email protected]448e459e2013-06-12 17:00:4189static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
90 GLint rangeMax,
91 GLint precision) {
92 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
93}
94
[email protected]8dc1bf92013-03-12 03:58:2195static void GetShaderPrecisionFormatImpl(GLenum shader_type,
96 GLenum precision_type,
97 GLint *range, GLint *precision) {
98 switch (precision_type) {
99 case GL_LOW_INT:
100 case GL_MEDIUM_INT:
101 case GL_HIGH_INT:
102 // These values are for a 32-bit twos-complement integer format.
103 range[0] = 31;
104 range[1] = 30;
105 *precision = 0;
106 break;
107 case GL_LOW_FLOAT:
108 case GL_MEDIUM_FLOAT:
109 case GL_HIGH_FLOAT:
110 // These values are for an IEEE single-precision floating-point format.
111 range[0] = 127;
112 range[1] = 127;
113 *precision = 23;
114 break;
115 default:
116 NOTREACHED();
117 break;
118 }
119
[email protected]8af4d5e2013-03-15 23:55:33120 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
121 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
[email protected]8dc1bf92013-03-12 03:58:21122 // This function is sometimes defined even though it's really just
123 // a stub, so we need to set range and precision as if it weren't
124 // defined before calling it.
[email protected]501b57402013-03-14 22:21:44125 // On Mac OS with some GPUs, calling this generates a
126 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
127 // platforms.
[email protected]8dc1bf92013-03-12 03:58:21128 glGetShaderPrecisionFormat(shader_type, precision_type,
129 range, precision);
[email protected]448e459e2013-06-12 17:00:41130
131 // TODO(brianderson): Make the following official workarounds.
132
133 // Some drivers have bugs where they report the ranges as a negative number.
134 // Taking the absolute value here shouldn't hurt because negative numbers
135 // aren't expected anyway.
136 range[0] = abs(range[0]);
137 range[1] = abs(range[1]);
138
139 // If the driver reports a precision for highp float that isn't actually
140 // highp, don't pretend like it's supported because shader compilation will
141 // fail anyway.
142 if (precision_type == GL_HIGH_FLOAT &&
143 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
144 range[0] = 0;
145 range[1] = 0;
146 *precision = 0;
147 }
[email protected]8dc1bf92013-03-12 03:58:21148 }
149}
150
[email protected]b04e24c2013-01-08 18:35:25151} // namespace
[email protected]f0d74742011-10-03 16:31:04152
[email protected]6217d392010-03-25 22:08:35153class GLES2DecoderImpl;
154
[email protected]ab09b612013-03-11 22:11:51155// Local versions of the SET_GL_ERROR macros
156#define LOCAL_SET_GL_ERROR(error, function_name, msg) \
[email protected]d3eba342013-04-18 21:11:50157 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
[email protected]ab09b612013-03-11 22:11:51158#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
[email protected]d3eba342013-04-18 21:11:50159 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
160 function_name, value, label)
[email protected]ab09b612013-03-11 22:11:51161#define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
[email protected]d3eba342013-04-18 21:11:50162 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
163 function_name, pname)
[email protected]ab09b612013-03-11 22:11:51164#define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
[email protected]d3eba342013-04-18 21:11:50165 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
166 function_name)
[email protected]ab09b612013-03-11 22:11:51167#define LOCAL_PEEK_GL_ERROR(function_name) \
[email protected]d3eba342013-04-18 21:11:50168 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
[email protected]ab09b612013-03-11 22:11:51169#define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
[email protected]d3eba342013-04-18 21:11:50170 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
[email protected]ab09b612013-03-11 22:11:51171#define LOCAL_PERFORMANCE_WARNING(msg) \
172 PerformanceWarning(__FILE__, __LINE__, msg)
173#define LOCAL_RENDER_WARNING(msg) \
174 RenderWarning(__FILE__, __LINE__, msg)
175
[email protected]07f54fcc2009-12-22 02:46:30176// Check that certain assumptions the code makes are true. There are places in
177// the code where shared memory is passed direclty to GL. Example, glUniformiv,
178// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
179// a few others) are 32bits. If they are not 32bits the code will have to change
180// to call those GL functions with service side memory and then copy the results
181// to shared memory, converting the sizes.
182COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
183 GLint_not_same_size_as_uint32);
184COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
185 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:37186COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
187 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:30188
[email protected]43f28f832010-02-03 02:28:48189// TODO(kbr): the use of this anonymous namespace core dumps the
190// linker on Mac OS X 10.6 when the symbol ordering file is used
191// namespace {
[email protected]96449d2c2009-11-25 00:01:32192
193// Returns the address of the first byte after a struct.
194template <typename T>
195const void* AddressAfterStruct(const T& pod) {
196 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
197}
198
[email protected]07f54fcc2009-12-22 02:46:30199// Returns the address of the frst byte after the struct or NULL if size >
200// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:32201template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:30202RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
203 uint32 size,
204 uint32 immediate_data_size) {
205 return (size <= immediate_data_size) ?
206 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
207 NULL;
[email protected]96449d2c2009-11-25 00:01:32208}
209
[email protected]07f54fcc2009-12-22 02:46:30210// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18211bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32212 GLuint count,
213 size_t size,
[email protected]a76b0052010-03-05 00:33:18214 unsigned int elements_per_unit,
215 uint32* dst) {
216 uint32 value;
217 if (!SafeMultiplyUint32(count, size, &value)) {
218 return false;
219 }
220 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
221 return false;
222 }
223 *dst = value;
224 return true;
[email protected]96449d2c2009-11-25 00:01:32225}
226
227// A struct to hold info about each command.
228struct CommandInfo {
229 int arg_flags; // How to handle the arguments for this command
230 int arg_count; // How many arguments are expected for this command.
231};
232
233// A table of CommandInfo for all the commands.
234const CommandInfo g_command_info[] = {
[email protected]ed9f9cd2013-02-27 21:12:35235 #define GLES2_CMD_OP(name) { \
236 cmds::name::kArgFlags, \
237 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
[email protected]96449d2c2009-11-25 00:01:32238
239 GLES2_COMMAND_LIST(GLES2_CMD_OP)
240
241 #undef GLES2_CMD_OP
242};
243
[email protected]258a3313f2011-10-18 20:13:57244// Return true if a character belongs to the ASCII subset as defined in
245// GLSL ES 1.0 spec section 3.1.
246static bool CharacterIsValidForGLES(unsigned char c) {
247 // Printing characters are valid except " $ ` @ \ ' DEL.
248 if (c >= 32 && c <= 126 &&
249 c != '"' &&
250 c != '$' &&
251 c != '`' &&
252 c != '@' &&
253 c != '\\' &&
254 c != '\'') {
255 return true;
256 }
257 // Horizontal tab, line feed, vertical tab, form feed, carriage return
258 // are also valid.
259 if (c >= 9 && c <= 13) {
260 return true;
261 }
262
263 return false;
264}
265
266static bool StringIsValidForGLES(const char* str) {
267 for (; *str; ++str) {
268 if (!CharacterIsValidForGLES(*str)) {
269 return false;
270 }
271 }
272 return true;
273}
274
[email protected]297ca1c2011-06-20 23:08:46275// Wrapper for glEnable/glDisable that doesn't suck.
276static void EnableDisable(GLenum pname, bool enable) {
277 if (enable) {
278 glEnable(pname);
279 } else {
280 glDisable(pname);
281 }
282}
283
[email protected]6217d392010-03-25 22:08:35284// This class prevents any GL errors that occur when it is in scope from
285// being reported to the client.
286class ScopedGLErrorSuppressor {
287 public:
[email protected]ab09b612013-03-11 22:11:51288 explicit ScopedGLErrorSuppressor(
289 const char* function_name, GLES2DecoderImpl* decoder);
[email protected]6217d392010-03-25 22:08:35290 ~ScopedGLErrorSuppressor();
291 private:
[email protected]ab09b612013-03-11 22:11:51292 const char* function_name_;
[email protected]6217d392010-03-25 22:08:35293 GLES2DecoderImpl* decoder_;
294 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
295};
296
297// Temporarily changes a decoder's bound 2D texture and restore it when this
298// object goes out of scope. Also temporarily switches to using active texture
299// unit zero in case the client has changed that to something invalid.
300class ScopedTexture2DBinder {
301 public:
302 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
303 ~ScopedTexture2DBinder();
304
305 private:
306 GLES2DecoderImpl* decoder_;
307 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
308};
309
310// Temporarily changes a decoder's bound render buffer and restore it when this
311// object goes out of scope.
312class ScopedRenderBufferBinder {
313 public:
314 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
315 ~ScopedRenderBufferBinder();
316
317 private:
318 GLES2DecoderImpl* decoder_;
319 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
320};
321
322// Temporarily changes a decoder's bound frame buffer and restore it when this
323// object goes out of scope.
324class ScopedFrameBufferBinder {
325 public:
326 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
327 ~ScopedFrameBufferBinder();
328
329 private:
330 GLES2DecoderImpl* decoder_;
331 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
332};
333
[email protected]34ff8b0c2010-10-01 20:06:02334// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52335// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27336// if it is bound or enforce_internal_framebuffer is true. If internal is
337// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02338class ScopedResolvedFrameBufferBinder {
339 public:
[email protected]e7e38032011-07-26 17:25:25340 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27341 bool enforce_internal_framebuffer,
342 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02343 ~ScopedResolvedFrameBufferBinder();
344
345 private:
346 GLES2DecoderImpl* decoder_;
347 bool resolve_and_bind_;
348 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
349};
350
[email protected]63b465922012-09-06 02:04:52351// This class records texture upload time when in scope.
352class ScopedTextureUploadTimer {
353 public:
354 explicit ScopedTextureUploadTimer(GLES2DecoderImpl* decoder);
355 ~ScopedTextureUploadTimer();
356
357 private:
358 GLES2DecoderImpl* decoder_;
359 base::TimeTicks begin_time_;
360 DISALLOW_COPY_AND_ASSIGN(ScopedTextureUploadTimer);
361};
362
[email protected]6217d392010-03-25 22:08:35363// Encapsulates an OpenGL texture.
[email protected]ed9f9cd2013-02-27 21:12:35364class BackTexture {
[email protected]6217d392010-03-25 22:08:35365 public:
[email protected]ed9f9cd2013-02-27 21:12:35366 explicit BackTexture(GLES2DecoderImpl* decoder);
367 ~BackTexture();
[email protected]6217d392010-03-25 22:08:35368
369 // Create a new render texture.
370 void Create();
371
372 // Set the initial size and format of a render texture or resize it.
[email protected]678a73f2012-12-19 19:22:09373 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
[email protected]6217d392010-03-25 22:08:35374
375 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58376 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35377
378 // Destroy the render texture. This must be explicitly called before
379 // destroying this object.
380 void Destroy();
381
[email protected]97872062010-11-03 19:07:05382 // Invalidate the texture. This can be used when a context is lost and it is
383 // not possible to make it current in order to free the resource.
384 void Invalidate();
385
[email protected]6217d392010-03-25 22:08:35386 GLuint id() const {
387 return id_;
388 }
389
[email protected]d37231fa2010-04-09 21:16:02390 gfx::Size size() const {
391 return size_;
392 }
393
[email protected]1078f912011-12-23 13:12:14394 size_t estimated_size() const {
[email protected]ff6493f2012-07-31 19:52:25395 return memory_tracker_.GetMemRepresented();
[email protected]1078f912011-12-23 13:12:14396 }
397
[email protected]6217d392010-03-25 22:08:35398 private:
399 GLES2DecoderImpl* decoder_;
[email protected]ff6493f2012-07-31 19:52:25400 MemoryTypeTracker memory_tracker_;
[email protected]68e81a4a62012-12-13 01:16:48401 size_t bytes_allocated_;
[email protected]6217d392010-03-25 22:08:35402 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02403 gfx::Size size_;
[email protected]ed9f9cd2013-02-27 21:12:35404 DISALLOW_COPY_AND_ASSIGN(BackTexture);
[email protected]6217d392010-03-25 22:08:35405};
406
407// Encapsulates an OpenGL render buffer of any format.
[email protected]ed9f9cd2013-02-27 21:12:35408class BackRenderbuffer {
[email protected]6217d392010-03-25 22:08:35409 public:
[email protected]ed9f9cd2013-02-27 21:12:35410 explicit BackRenderbuffer(GLES2DecoderImpl* decoder);
411 ~BackRenderbuffer();
[email protected]6217d392010-03-25 22:08:35412
413 // Create a new render buffer.
414 void Create();
415
416 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02417 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35418
419 // Destroy the render buffer. This must be explicitly called before destroying
420 // this object.
421 void Destroy();
422
[email protected]97872062010-11-03 19:07:05423 // Invalidate the render buffer. This can be used when a context is lost and
424 // it is not possible to make it current in order to free the resource.
425 void Invalidate();
426
[email protected]6217d392010-03-25 22:08:35427 GLuint id() const {
428 return id_;
429 }
430
[email protected]1078f912011-12-23 13:12:14431 size_t estimated_size() const {
[email protected]ff6493f2012-07-31 19:52:25432 return memory_tracker_.GetMemRepresented();
[email protected]1078f912011-12-23 13:12:14433 }
434
[email protected]6217d392010-03-25 22:08:35435 private:
436 GLES2DecoderImpl* decoder_;
[email protected]ff6493f2012-07-31 19:52:25437 MemoryTypeTracker memory_tracker_;
[email protected]68e81a4a62012-12-13 01:16:48438 size_t bytes_allocated_;
[email protected]6217d392010-03-25 22:08:35439 GLuint id_;
[email protected]ed9f9cd2013-02-27 21:12:35440 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
[email protected]6217d392010-03-25 22:08:35441};
442
443// Encapsulates an OpenGL frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35444class BackFramebuffer {
[email protected]6217d392010-03-25 22:08:35445 public:
[email protected]ed9f9cd2013-02-27 21:12:35446 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
447 ~BackFramebuffer();
[email protected]6217d392010-03-25 22:08:35448
449 // Create a new frame buffer.
450 void Create();
451
452 // Attach a color render buffer to a frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35453 void AttachRenderTexture(BackTexture* texture);
[email protected]6217d392010-03-25 22:08:35454
[email protected]b9363b22010-06-09 22:06:15455 // Attach a render buffer to a frame buffer. Note that this unbinds any
456 // currently bound frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35457 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35458
[email protected]6217d392010-03-25 22:08:35459 // Destroy the frame buffer. This must be explicitly called before destroying
460 // this object.
461 void Destroy();
462
[email protected]97872062010-11-03 19:07:05463 // Invalidate the frame buffer. This can be used when a context is lost and it
464 // is not possible to make it current in order to free the resource.
465 void Invalidate();
466
[email protected]6217d392010-03-25 22:08:35467 // See glCheckFramebufferStatusEXT.
468 GLenum CheckStatus();
469
470 GLuint id() const {
471 return id_;
472 }
473
474 private:
475 GLES2DecoderImpl* decoder_;
476 GLuint id_;
[email protected]ed9f9cd2013-02-27 21:12:35477 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
[email protected]6217d392010-03-25 22:08:35478};
[email protected]34ff8b0c2010-10-01 20:06:02479
[email protected]43f28f832010-02-03 02:28:48480// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32481
[email protected]ddb1e5a2010-12-13 20:10:45482bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
483 uint32* service_texture_id) {
484 return false;
485}
486
[email protected]a3ded6d2010-10-19 06:44:39487GLES2Decoder::GLES2Decoder()
[email protected]55e136f2013-04-03 18:50:06488 : initialized_(false),
489 debug_(false),
[email protected]1d82e822013-04-10 21:32:32490 log_commands_(false) {
[email protected]96449d2c2009-11-25 00:01:32491}
492
[email protected]3916c97e2010-02-25 03:20:50493GLES2Decoder::~GLES2Decoder() {
494}
495
[email protected]57edfdad2012-02-07 04:57:15496bool GLES2Decoder::testing_force_is_angle_;
497
498void GLES2Decoder::set_testing_force_is_angle(bool force) {
499 testing_force_is_angle_ = force;
500}
501
502bool GLES2Decoder::IsAngle() {
503#if defined(OS_WIN)
504 return testing_force_is_angle_ ||
505 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
506#else
507 return testing_force_is_angle_;
508#endif
509}
510
[email protected]f39f4b3f2010-05-12 17:04:08511// This class implements GLES2Decoder so we don't have to expose all the GLES2
512// cmd stuff to outside this class.
[email protected]ee1e6aa2012-11-29 09:24:10513class GLES2DecoderImpl : public GLES2Decoder {
[email protected]f39f4b3f2010-05-12 17:04:08514 public:
[email protected]476ccb72012-12-06 15:52:52515 // Used by PrepForSetUniformByLocation to validate types.
516 struct BaseUniformInfo {
517 const GLenum* const valid_types;
518 size_t num_valid_types;
519 };
520
[email protected]aa7666122011-09-02 19:45:52521 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]b8e97b62012-09-30 15:09:00522 virtual ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08523
[email protected]96449d2c2009-11-25 00:01:32524 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14525 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50526 unsigned int arg_count,
[email protected]b8e97b62012-09-30 15:09:00527 const void* args) OVERRIDE;
[email protected]96449d2c2009-11-25 00:01:32528
529 // Overridden from AsyncAPIInterface.
[email protected]b8e97b62012-09-30 15:09:00530 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
[email protected]96449d2c2009-11-25 00:01:32531
532 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38533 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
534 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:23535 bool offscreen,
[email protected]6217d392010-03-25 22:08:35536 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29537 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39538 const char* allowed_extensions,
[email protected]b8e97b62012-09-30 15:09:00539 const std::vector<int32>& attribs) OVERRIDE;
540 virtual void Destroy(bool have_context) OVERRIDE;
[email protected]63c9b052012-05-17 18:27:38541 virtual void SetSurface(
542 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
[email protected]2ad674132013-06-05 07:48:51543 virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
[email protected]b8e97b62012-09-30 15:09:00544 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
[email protected]9a5afa432011-07-22 18:16:39545 void UpdateParentTextureInfo();
[email protected]b8e97b62012-09-30 15:09:00546 virtual bool MakeCurrent() OVERRIDE;
547 virtual void ReleaseCurrent() OVERRIDE;
548 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
549 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
550 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
[email protected]1868a342012-11-07 15:56:02551 virtual void RestoreState() const OVERRIDE;
[email protected]29a4d902013-02-26 20:18:06552
553 virtual void RestoreActiveTexture() const OVERRIDE {
554 state_.RestoreActiveTexture();
555 }
[email protected]217004512013-05-10 21:25:55556 virtual void RestoreAllTextureUnitBindings() const OVERRIDE {
557 state_.RestoreAllTextureUnitBindings();
558 }
[email protected]29a4d902013-02-26 20:18:06559 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
560 state_.RestoreAttribute(index);
561 }
562 virtual void RestoreBufferBindings() const OVERRIDE {
563 state_.RestoreBufferBindings();
564 }
565 virtual void RestoreGlobalState() const OVERRIDE {
566 state_.RestoreGlobalState();
567 }
568 virtual void RestoreProgramBindings() const OVERRIDE {
569 state_.RestoreProgramBindings();
570 }
571 virtual void RestoreRenderbufferBindings() const OVERRIDE {
572 state_.RestoreRenderbufferBindings();
573 }
574 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
575 state_.RestoreTextureUnitBindings(unit);
576 }
577 virtual void RestoreFramebufferBindings() const OVERRIDE;
578 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
579
[email protected]b8e97b62012-09-30 15:09:00580 virtual QueryManager* GetQueryManager() OVERRIDE {
581 return query_manager_.get();
582 }
583 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
[email protected]944b62f32012-09-27 02:20:46584 return vertex_array_manager_.get();
585 }
[email protected]b8e97b62012-09-30 15:09:00586 virtual bool ProcessPendingQueries() OVERRIDE;
[email protected]2b1767cf2013-03-16 09:25:05587 virtual bool HasMoreIdleWork() OVERRIDE;
588 virtual void PerformIdleWork() OVERRIDE;
[email protected]43f28f832010-02-03 02:28:48589
[email protected]9d37f062011-11-22 01:24:52590 virtual void SetResizeCallback(
[email protected]729c0b42013-05-26 02:05:07591 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
[email protected]22f320a2011-08-30 01:17:00592
[email protected]1d82e822013-04-10 21:32:32593 virtual Logger* GetLogger() OVERRIDE;
[email protected]d3eba342013-04-18 21:11:50594 virtual ErrorState* GetErrorState() OVERRIDE;
[email protected]1d82e822013-04-10 21:32:32595
[email protected]e3932abb2013-03-13 00:01:37596 virtual void SetShaderCacheCallback(
597 const ShaderCacheCallback& callback) OVERRIDE;
[email protected]840a7e462013-02-27 01:29:51598 virtual void SetWaitSyncPointCallback(
599 const WaitSyncPointCallback& callback) OVERRIDE;
[email protected]22f320a2011-08-30 01:17:00600
[email protected]85a4ac22013-05-31 01:58:47601 virtual AsyncPixelTransferManager*
602 GetAsyncPixelTransferManager() OVERRIDE;
603 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
[email protected]498b5c072013-06-04 19:30:07604 virtual void SetAsyncPixelTransferManagerForTest(
605 AsyncPixelTransferManager* manager) OVERRIDE;
[email protected]69a8701e2013-03-07 21:31:09606 void ProcessFinishedAsyncTransfers();
[email protected]32145a92012-12-17 09:01:59607
[email protected]1318e922010-09-17 22:03:16608 virtual bool GetServiceTextureId(uint32 client_texture_id,
[email protected]b8e97b62012-09-30 15:09:00609 uint32* service_texture_id) OVERRIDE;
[email protected]43f28f832010-02-03 02:28:48610
[email protected]63b465922012-09-06 02:04:52611 virtual uint32 GetTextureUploadCount() OVERRIDE;
612 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
613 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
[email protected]dc25dda2012-09-27 21:36:30614 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
[email protected]63b465922012-09-06 02:04:52615
[email protected]8e3e0662010-08-23 18:46:30616 // Restores the current state to the user's settings.
617 void RestoreCurrentFramebufferBindings();
618 void RestoreCurrentRenderbufferBindings();
619 void RestoreCurrentTexture2DBindings();
620
[email protected]297ca1c2011-06-20 23:08:46621 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
622 void ApplyDirtyState();
623
624 // These check the state of the currently bound framebuffer or the
625 // backbuffer if no framebuffer is bound.
[email protected]f3b191b2013-06-19 03:43:54626 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
627 // check with all attached and enabled color attachments.
628 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
[email protected]297ca1c2011-06-20 23:08:46629 bool BoundFramebufferHasDepthAttachment();
630 bool BoundFramebufferHasStencilAttachment();
631
[email protected]b8e97b62012-09-30 15:09:00632 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
[email protected]38d139d2011-07-14 00:38:43633
[email protected]96449d2c2009-11-25 00:01:32634 private:
[email protected]70d34263c2013-01-09 00:27:45635 friend class ScopedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35636 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02637 friend class ScopedResolvedFrameBufferBinder;
[email protected]63b465922012-09-06 02:04:52638 friend class ScopedTextureUploadTimer;
[email protected]ed9f9cd2013-02-27 21:12:35639 friend class BackTexture;
640 friend class BackRenderbuffer;
641 friend class BackFramebuffer;
[email protected]6217d392010-03-25 22:08:35642
[email protected]c2f8c8402010-12-06 18:07:24643 // Initialize or re-initialize the shader translator.
644 bool InitializeShaderTranslator();
645
[email protected]302ce6d2011-07-07 23:28:11646 void UpdateCapabilities();
647
[email protected]ae51d192010-04-27 00:48:03648 // Helpers for the glGen and glDelete functions.
649 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
650 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
651 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
652 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
653 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
654 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
655 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
656 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]882ba1e22012-03-08 19:02:53657 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
658 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
[email protected]944b62f32012-09-27 02:20:46659 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
660 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47661
[email protected]70d34263c2013-01-09 00:27:45662 // Workarounds
663 void OnFboChanged() const;
[email protected]28718a92013-04-04 12:12:51664 void OnUseFramebuffer() const;
[email protected]70d34263c2013-01-09 00:27:45665
[email protected]3916c97e2010-02-25 03:20:50666 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50667 BufferManager* buffer_manager() {
668 return group_->buffer_manager();
669 }
670
[email protected]a25fa872010-03-25 02:57:58671 RenderbufferManager* renderbuffer_manager() {
672 return group_->renderbuffer_manager();
673 }
674
675 FramebufferManager* framebuffer_manager() {
676 return group_->framebuffer_manager();
677 }
678
[email protected]3916c97e2010-02-25 03:20:50679 ProgramManager* program_manager() {
680 return group_->program_manager();
681 }
682
683 ShaderManager* shader_manager() {
684 return group_->shader_manager();
685 }
686
[email protected]29a4d902013-02-26 20:18:06687 const TextureManager* texture_manager() const {
688 return group_->texture_manager();
689 }
690
[email protected]3916c97e2010-02-25 03:20:50691 TextureManager* texture_manager() {
692 return group_->texture_manager();
693 }
694
[email protected]78b514b2012-05-01 21:50:59695 MailboxManager* mailbox_manager() {
696 return group_->mailbox_manager();
697 }
698
[email protected]09d50362012-10-18 20:54:37699 ImageManager* image_manager() {
700 return group_->image_manager();
701 }
702
[email protected]944b62f32012-09-27 02:20:46703 VertexArrayManager* vertex_array_manager() {
704 return vertex_array_manager_.get();
705 }
706
[email protected]7989c9e2013-01-23 06:39:26707 MemoryTracker* memory_tracker() {
708 return group_->memory_tracker();
709 }
710
[email protected]4f9958142013-07-02 03:58:07711 StreamTextureManager* stream_texture_manager() const {
712 return group_->stream_texture_manager();
713 }
714
[email protected]7989c9e2013-01-23 06:39:26715 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
716 MemoryTracker* tracker = memory_tracker();
717 if (tracker) {
718 return tracker->EnsureGPUMemoryAvailable(estimated_size);
719 }
720 return true;
721 }
722
[email protected]34ff8b0c2010-10-01 20:06:02723 bool IsOffscreenBufferMultisampled() const {
724 return offscreen_target_samples_ > 1;
725 }
726
[email protected]ed9f9cd2013-02-27 21:12:35727 // Creates a Texture for the given texture.
[email protected]370eaf12013-05-18 09:19:49728 TextureRef* CreateTexture(
[email protected]ae51d192010-04-27 00:48:03729 GLuint client_id, GLuint service_id) {
[email protected]ed9f9cd2013-02-27 21:12:35730 return texture_manager()->CreateTexture(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47731 }
732
733 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]370eaf12013-05-18 09:19:49734 TextureRef* GetTexture(GLuint client_id) const {
[email protected]02965c22013-03-09 02:40:07735 return texture_manager()->GetTexture(client_id);
[email protected]a93bb842010-02-16 23:03:47736 }
737
738 // Deletes the texture info for the given texture.
[email protected]ed9f9cd2013-02-27 21:12:35739 void RemoveTexture(GLuint client_id) {
740 texture_manager()->RemoveTexture(client_id);
[email protected]3916c97e2010-02-25 03:20:50741 }
[email protected]a93bb842010-02-16 23:03:47742
[email protected]d37231fa2010-04-09 21:16:02743 // Get the size (in pixels) of the currently bound frame buffer (either FBO
744 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30745 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02746
[email protected]9edc6b22010-12-23 02:00:26747 // Get the format of the currently bound frame buffer (either FBO or regular
748 // back buffer)
749 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46750 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26751
[email protected]a93bb842010-02-16 23:03:47752 // Wrapper for CompressedTexImage2D commands.
753 error::Error DoCompressedTexImage2D(
[email protected]09d50362012-10-18 20:54:37754 GLenum target,
755 GLint level,
756 GLenum internal_format,
757 GLsizei width,
758 GLsizei height,
759 GLint border,
760 GLsizei image_size,
761 const void* data);
[email protected]a93bb842010-02-16 23:03:47762
[email protected]cadde4a2010-07-31 17:10:43763 // Wrapper for CompressedTexSubImage2D.
764 void DoCompressedTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37765 GLenum target,
766 GLint level,
767 GLint xoffset,
768 GLint yoffset,
769 GLsizei width,
770 GLsizei height,
771 GLenum format,
772 GLsizei imageSize,
773 const void * data);
[email protected]cadde4a2010-07-31 17:10:43774
775 // Wrapper for CopyTexImage2D.
776 void DoCopyTexImage2D(
[email protected]09d50362012-10-18 20:54:37777 GLenum target,
778 GLint level,
779 GLenum internal_format,
780 GLint x,
781 GLint y,
782 GLsizei width,
783 GLsizei height,
784 GLint border);
[email protected]cadde4a2010-07-31 17:10:43785
[email protected]6d792ee12013-05-15 00:40:56786 // Wrapper for SwapBuffers.
787 void DoSwapBuffers();
788
[email protected]cadde4a2010-07-31 17:10:43789 // Wrapper for CopyTexSubImage2D.
790 void DoCopyTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37791 GLenum target,
792 GLint level,
793 GLint xoffset,
794 GLint yoffset,
795 GLint x,
796 GLint y,
797 GLsizei width,
798 GLsizei height);
[email protected]cadde4a2010-07-31 17:10:43799
[email protected]f598f422012-12-07 08:30:03800 // Validation for TexImage2D commands.
801 bool ValidateTexImage2D(
802 const char* function_name,
[email protected]09d50362012-10-18 20:54:37803 GLenum target,
804 GLint level,
805 GLenum internal_format,
806 GLsizei width,
807 GLsizei height,
808 GLint border,
809 GLenum format,
810 GLenum type,
811 const void* pixels,
812 uint32 pixels_size);
[email protected]a93bb842010-02-16 23:03:47813
[email protected]f598f422012-12-07 08:30:03814 // Wrapper for TexImage2D commands.
815 void DoTexImage2D(
816 GLenum target,
817 GLint level,
818 GLenum internal_format,
819 GLsizei width,
820 GLsizei height,
821 GLint border,
822 GLenum format,
823 GLenum type,
824 const void* pixels,
825 uint32 pixels_size);
826
827 // Validation for TexSubImage2D.
828 bool ValidateTexSubImage2D(
829 error::Error* error,
830 const char* function_name,
831 GLenum target,
832 GLint level,
833 GLint xoffset,
834 GLint yoffset,
835 GLsizei width,
836 GLsizei height,
837 GLenum format,
838 GLenum type,
839 const void * data);
840
[email protected]cadde4a2010-07-31 17:10:43841 // Wrapper for TexSubImage2D.
[email protected]f598f422012-12-07 08:30:03842 error::Error DoTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37843 GLenum target,
844 GLint level,
845 GLint xoffset,
846 GLint yoffset,
847 GLsizei width,
848 GLsizei height,
849 GLenum format,
850 GLenum type,
851 const void * data);
[email protected]cadde4a2010-07-31 17:10:43852
[email protected]32145a92012-12-17 09:01:59853 // Extra validation for async tex(Sub)Image2D.
854 bool ValidateAsyncTransfer(
855 const char* function_name,
[email protected]85a4ac22013-05-31 01:58:47856 TextureRef* texture_ref,
[email protected]32145a92012-12-17 09:01:59857 GLenum target,
858 GLint level,
859 const void * data);
860
[email protected]e51bdf32011-11-23 22:21:46861 // Wrapper for TexImageIOSurface2DCHROMIUM.
862 void DoTexImageIOSurface2DCHROMIUM(
[email protected]09d50362012-10-18 20:54:37863 GLenum target,
864 GLsizei width,
865 GLsizei height,
866 GLuint io_surface_id,
867 GLuint plane);
[email protected]e51bdf32011-11-23 22:21:46868
[email protected]43410e92012-04-20 17:06:28869 void DoCopyTextureCHROMIUM(
[email protected]09d50362012-10-18 20:54:37870 GLenum target,
871 GLuint source_id,
872 GLuint target_id,
873 GLint level,
[email protected]a4a6bdd12013-04-19 20:46:54874 GLenum internal_format,
875 GLenum dest_type);
[email protected]43410e92012-04-20 17:06:28876
[email protected]97dc7cbe2011-12-06 17:26:17877 // Wrapper for TexStorage2DEXT.
878 void DoTexStorage2DEXT(
[email protected]09d50362012-10-18 20:54:37879 GLenum target,
880 GLint levels,
881 GLenum internal_format,
882 GLsizei width,
883 GLsizei height);
[email protected]97dc7cbe2011-12-06 17:26:17884
[email protected]78b514b2012-05-01 21:50:59885 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
886 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
887
[email protected]09d50362012-10-18 20:54:37888 void DoBindTexImage2DCHROMIUM(
889 GLenum target,
890 GLint image_id);
891 void DoReleaseTexImage2DCHROMIUM(
892 GLenum target,
893 GLint image_id);
894
[email protected]94307712012-11-16 23:26:11895 void DoTraceEndCHROMIUM(void);
896
[email protected]2f143d482013-03-14 18:04:49897 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
898
[email protected]ed9f9cd2013-02-27 21:12:35899 // Creates a Program for the given program.
900 Program* CreateProgram(
[email protected]d685a682011-04-29 16:19:57901 GLuint client_id, GLuint service_id) {
[email protected]ed9f9cd2013-02-27 21:12:35902 return program_manager()->CreateProgram(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47903 }
904
[email protected]07f54fcc2009-12-22 02:46:30905 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ed9f9cd2013-02-27 21:12:35906 Program* GetProgram(GLuint client_id) {
907 return program_manager()->GetProgram(client_id);
[email protected]1d32bc82010-01-13 22:06:46908 }
[email protected]07f54fcc2009-12-22 02:46:30909
[email protected]cae20172012-12-07 00:06:19910#if defined(NDEBUG)
911 void LogClientServiceMapping(
912 const char* /* function_name */,
913 GLuint /* client_id */,
914 GLuint /* service_id */) {
915 }
916 template<typename T>
917 void LogClientServiceForInfo(
918 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
919 }
920#else
921 void LogClientServiceMapping(
922 const char* function_name, GLuint client_id, GLuint service_id) {
[email protected]2a22fe72012-12-07 04:21:26923 if (service_logging_) {
[email protected]1d82e822013-04-10 21:32:32924 DLOG(INFO) << "[" << logger_.GetLogPrefix() << "] " << function_name
[email protected]2a22fe72012-12-07 04:21:26925 << ": client_id = " << client_id
926 << ", service_id = " << service_id;
927 }
[email protected]cae20172012-12-07 00:06:19928 }
929 template<typename T>
930 void LogClientServiceForInfo(
931 T* info, GLuint client_id, const char* function_name) {
[email protected]2a22fe72012-12-07 04:21:26932 if (info) {
[email protected]cae20172012-12-07 00:06:19933 LogClientServiceMapping(function_name, client_id, info->service_id());
934 }
935 }
936#endif
937
[email protected]6b8cf1a2010-05-06 16:13:58938 // Gets the program info for the given program. If it's not a program
939 // generates a GL error. Returns NULL if not program.
[email protected]ed9f9cd2013-02-27 21:12:35940 Program* GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:58941 GLuint client_id, const char* function_name) {
[email protected]df37b9932013-03-08 05:21:42942 Program* program = GetProgram(client_id);
943 if (!program) {
[email protected]ed9f9cd2013-02-27 21:12:35944 if (GetShader(client_id)) {
[email protected]ab09b612013-03-11 22:11:51945 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43946 GL_INVALID_OPERATION, function_name, "shader passed for program");
[email protected]6b8cf1a2010-05-06 16:13:58947 } else {
[email protected]ab09b612013-03-11 22:11:51948 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
[email protected]6b8cf1a2010-05-06 16:13:58949 }
950 }
[email protected]df37b9932013-03-08 05:21:42951 LogClientServiceForInfo(program, client_id, function_name);
952 return program;
[email protected]6b8cf1a2010-05-06 16:13:58953 }
954
955
[email protected]ed9f9cd2013-02-27 21:12:35956 // Creates a Shader for the given shader.
957 Shader* CreateShader(
[email protected]d685a682011-04-29 16:19:57958 GLuint client_id,
959 GLuint service_id,
960 GLenum shader_type) {
[email protected]ed9f9cd2013-02-27 21:12:35961 return shader_manager()->CreateShader(
[email protected]d685a682011-04-29 16:19:57962 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31963 }
964
965 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ed9f9cd2013-02-27 21:12:35966 Shader* GetShader(GLuint client_id) {
967 return shader_manager()->GetShader(client_id);
[email protected]45bf5152010-02-12 00:11:31968 }
969
[email protected]6b8cf1a2010-05-06 16:13:58970 // Gets the shader info for the given shader. If it's not a shader generates a
971 // GL error. Returns NULL if not shader.
[email protected]ed9f9cd2013-02-27 21:12:35972 Shader* GetShaderInfoNotProgram(
[email protected]6b8cf1a2010-05-06 16:13:58973 GLuint client_id, const char* function_name) {
[email protected]df37b9932013-03-08 05:21:42974 Shader* shader = GetShader(client_id);
975 if (!shader) {
[email protected]ed9f9cd2013-02-27 21:12:35976 if (GetProgram(client_id)) {
[email protected]ab09b612013-03-11 22:11:51977 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43978 GL_INVALID_OPERATION, function_name, "program passed for shader");
[email protected]6b8cf1a2010-05-06 16:13:58979 } else {
[email protected]ab09b612013-03-11 22:11:51980 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43981 GL_INVALID_VALUE, function_name, "unknown shader");
[email protected]6b8cf1a2010-05-06 16:13:58982 }
983 }
[email protected]df37b9932013-03-08 05:21:42984 LogClientServiceForInfo(shader, client_id, function_name);
985 return shader;
[email protected]6b8cf1a2010-05-06 16:13:58986 }
987
[email protected]a93bb842010-02-16 23:03:47988 // Creates a buffer info for the given buffer.
[email protected]ed9f9cd2013-02-27 21:12:35989 void CreateBuffer(GLuint client_id, GLuint service_id) {
990 return buffer_manager()->CreateBuffer(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47991 }
992
[email protected]07f54fcc2009-12-22 02:46:30993 // Gets the buffer info for the given buffer.
[email protected]16ccec12013-02-28 03:40:21994 Buffer* GetBuffer(GLuint client_id) {
[email protected]b10492f2013-03-08 05:24:07995 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
996 return buffer;
[email protected]1d32bc82010-01-13 22:06:46997 }
[email protected]07f54fcc2009-12-22 02:46:30998
[email protected]a93bb842010-02-16 23:03:47999 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1000 // on glDeleteBuffers so we can make sure the user does not try to render
1001 // with deleted buffers.
[email protected]ed9f9cd2013-02-27 21:12:351002 void RemoveBuffer(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:471003
[email protected]a25fa872010-03-25 02:57:581004 // Creates a framebuffer info for the given framebuffer.
[email protected]ed9f9cd2013-02-27 21:12:351005 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1006 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:581007 }
1008
1009 // Gets the framebuffer info for the given framebuffer.
[email protected]4d8f0dd2013-03-09 14:37:061010 Framebuffer* GetFramebuffer(GLuint client_id) {
1011 return framebuffer_manager()->GetFramebuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581012 }
1013
1014 // Removes the framebuffer info for the given framebuffer.
[email protected]ed9f9cd2013-02-27 21:12:351015 void RemoveFramebuffer(GLuint client_id) {
1016 framebuffer_manager()->RemoveFramebuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581017 }
1018
1019 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ed9f9cd2013-02-27 21:12:351020 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1021 return renderbuffer_manager()->CreateRenderbuffer(
[email protected]ae51d192010-04-27 00:48:031022 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:581023 }
1024
1025 // Gets the renderbuffer info for the given renderbuffer.
[email protected]ee2a79c32013-03-10 03:50:271026 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1027 return renderbuffer_manager()->GetRenderbuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581028 }
1029
1030 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ed9f9cd2013-02-27 21:12:351031 void RemoveRenderbuffer(GLuint client_id) {
1032 renderbuffer_manager()->RemoveRenderbuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581033 }
1034
[email protected]944b62f32012-09-27 02:20:461035 // Gets the vertex attrib manager for the given vertex array.
1036 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1037 VertexAttribManager* info =
1038 vertex_array_manager()->GetVertexAttribManager(client_id);
1039 return info;
1040 }
1041
1042 // Removes the vertex attrib manager for the given vertex array.
1043 void RemoveVertexAttribManager(GLuint client_id) {
1044 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1045 }
1046
1047 // Creates a vertex attrib manager for the given vertex array.
1048 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1049 return vertex_array_manager()->CreateVertexAttribManager(
1050 client_id, service_id, group_->max_vertex_attribs());
1051 }
1052
[email protected]258a3313f2011-10-18 20:13:571053 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
[email protected]2be6abf32012-06-26 00:28:331054 void DoBindUniformLocationCHROMIUM(
1055 GLuint client_id, GLint location, const char* name);
[email protected]258a3313f2011-10-18 20:13:571056
[email protected]558847a2010-03-24 07:02:541057 error::Error GetAttribLocationHelper(
1058 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1059 const std::string& name_str);
1060
1061 error::Error GetUniformLocationHelper(
1062 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1063 const std::string& name_str);
1064
[email protected]3916c97e2010-02-25 03:20:501065 // Helper for glShaderSource.
1066 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:031067 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:301068
[email protected]0d6bfdc2011-11-02 01:32:201069 // Clear any textures used by the current program.
1070 bool ClearUnclearedTextures();
1071
1072 // Clear any uncleared level in texture.
1073 // Returns false if there was a generated GL error.
[email protected]02965c22013-03-09 02:40:071074 bool ClearTexture(Texture* texture);
[email protected]0d6bfdc2011-11-02 01:32:201075
1076 // Clears any uncleared attachments attached to the given frame buffer.
1077 // Returns false if there was a generated GL error.
[email protected]4d8f0dd2013-03-09 14:37:061078 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
[email protected]3a2e7c7b2010-08-06 01:12:281079
[email protected]0d6bfdc2011-11-02 01:32:201080 // overridden from GLES2Decoder
[email protected]b8e97b62012-09-30 15:09:001081 virtual bool ClearLevel(unsigned service_id,
1082 unsigned bind_target,
1083 unsigned target,
1084 int level,
1085 unsigned format,
1086 unsigned type,
1087 int width,
1088 int height,
1089 bool is_texture_immutable) OVERRIDE;
[email protected]0d6bfdc2011-11-02 01:32:201090
[email protected]c007aa02010-09-02 22:22:401091 // Restore all GL state that affects clearing.
1092 void RestoreClearState();
1093
[email protected]3a2e7c7b2010-08-06 01:12:281094 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:461095 // Returns: true if glEnable/glDisable should actually be called.
1096 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:281097
[email protected]0d6bfdc2011-11-02 01:32:201098 // Check that the currently bound framebuffers are valid.
1099 // Generates GL error if not.
1100 bool CheckBoundFramebuffersValid(const char* func_name);
1101
1102 // Check if a framebuffer meets our requirements.
1103 bool CheckFramebufferValid(
[email protected]ed9f9cd2013-02-27 21:12:351104 Framebuffer* framebuffer,
[email protected]0d6bfdc2011-11-02 01:32:201105 GLenum target,
1106 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:271107
[email protected]939e7362010-05-13 20:49:101108 // Checks if the current program exists and is valid. If not generates the
1109 // appropriate GL error. Returns true if the current program is in a usable
1110 // state.
1111 bool CheckCurrentProgram(const char* function_name);
1112
1113 // Checks if the current program exists and is valid and that location is not
1114 // -1. If the current program is not valid generates the appropriate GL
1115 // error. Returns true if the current program is in a usable state and
1116 // location is not -1.
1117 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1118
1119 // Gets the type of a uniform for a location in the current program. Sets GL
1120 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:361121 // program is valid and the location exists. Adjusts count so it
1122 // does not overflow the uniform.
1123 bool PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:121124 GLint fake_location, const char* function_name,
[email protected]476ccb72012-12-06 15:52:521125 const BaseUniformInfo& base_info,
[email protected]1b0a6752012-02-22 03:44:121126 GLint* real_location, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:101127
[email protected]b177ae22011-11-01 03:29:111128 // Gets the service id for any simulated backbuffer fbo.
[email protected]1868a342012-11-07 15:56:021129 GLuint GetBackbufferServiceId() const;
[email protected]b177ae22011-11-01 03:29:111130
[email protected]b273e432010-04-12 17:23:581131 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1132 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1133
[email protected]ac77603c72013-03-08 13:52:061134 // Helper for glGetVertexAttrib
1135 void GetVertexAttribHelper(
1136 const VertexAttrib* attrib, GLenum pname, GLint* param);
1137
[email protected]96449d2c2009-11-25 00:01:321138 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:031139 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321140
1141 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:031142 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321143
[email protected]3916c97e2010-02-25 03:20:501144 // Wrapper for glActiveTexture
1145 void DoActiveTexture(GLenum texture_unit);
1146
[email protected]ae51d192010-04-27 00:48:031147 // Wrapper for glAttachShader
1148 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1149
[email protected]96449d2c2009-11-25 00:01:321150 // Wrapper for glBindBuffer since we need to track the current targets.
1151 void DoBindBuffer(GLenum target, GLuint buffer);
1152
[email protected]86093972010-03-11 00:13:561153 // Wrapper for glBindFramebuffer since we need to track the current targets.
1154 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1155
1156 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1157 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1158
[email protected]a93bb842010-02-16 23:03:471159 // Wrapper for glBindTexture since we need to track the current targets.
1160 void DoBindTexture(GLenum target, GLuint texture);
1161
[email protected]944b62f32012-09-27 02:20:461162 // Wrapper for glBindVertexArrayOES
1163 void DoBindVertexArrayOES(GLuint array);
[email protected]ab4fd7282012-10-12 16:25:571164 void EmulateVertexArrayState();
[email protected]944b62f32012-09-27 02:20:461165
[email protected]8e3e0662010-08-23 18:46:301166 // Wrapper for glBlitFramebufferEXT.
1167 void DoBlitFramebufferEXT(
1168 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1169 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1170 GLbitfield mask, GLenum filter);
1171
[email protected]36cef8ce2010-03-16 07:34:451172 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111173 void DoBufferData(
1174 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1175
[email protected]36cef8ce2010-03-16 07:34:451176 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111177 void DoBufferSubData(
1178 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1179
[email protected]36cef8ce2010-03-16 07:34:451180 // Wrapper for glCheckFramebufferStatus
1181 GLenum DoCheckFramebufferStatus(GLenum target);
1182
[email protected]3a03a8f2011-03-19 00:51:271183 // Wrapper for glClear
[email protected]a7266a92012-06-28 02:11:081184 error::Error DoClear(GLbitfield mask);
[email protected]3a03a8f2011-03-19 00:51:271185
[email protected]88a61bf2012-10-27 13:00:421186 // Wrappers for various state.
[email protected]88a61bf2012-10-27 13:00:421187 void DoDepthRangef(GLclampf znear, GLclampf zfar);
[email protected]b04e24c2013-01-08 18:35:251188 void DoSampleCoverage(GLclampf value, GLboolean invert);
[email protected]3a2e7c7b2010-08-06 01:12:281189
[email protected]45bf5152010-02-12 00:11:311190 // Wrapper for glCompileShader.
1191 void DoCompileShader(GLuint shader);
1192
[email protected]269200b12010-11-18 22:53:061193 // Helper for DeleteSharedIdsCHROMIUM commands.
1194 void DoDeleteSharedIdsCHROMIUM(
1195 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101196
[email protected]ae51d192010-04-27 00:48:031197 // Wrapper for glDetachShader
1198 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1199
[email protected]3a2e7c7b2010-08-06 01:12:281200 // Wrapper for glDisable
1201 void DoDisable(GLenum cap);
1202
[email protected]07f54fcc2009-12-22 02:46:301203 // Wrapper for glDisableVertexAttribArray.
1204 void DoDisableVertexAttribArray(GLuint index);
1205
[email protected]60f22d32012-12-12 00:31:581206 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1207 // attachments.
1208 void DoDiscardFramebufferEXT(GLenum target,
1209 GLsizei numAttachments,
1210 const GLenum* attachments);
1211
[email protected]3a2e7c7b2010-08-06 01:12:281212 // Wrapper for glEnable
1213 void DoEnable(GLenum cap);
1214
[email protected]07f54fcc2009-12-22 02:46:301215 // Wrapper for glEnableVertexAttribArray.
1216 void DoEnableVertexAttribArray(GLuint index);
1217
[email protected]882ba1e22012-03-08 19:02:531218 // Wrapper for glFinish.
1219 void DoFinish();
1220
1221 // Wrapper for glFlush.
1222 void DoFlush();
1223
[email protected]36cef8ce2010-03-16 07:34:451224 // Wrapper for glFramebufferRenderbufffer.
1225 void DoFramebufferRenderbuffer(
1226 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1227 GLuint renderbuffer);
1228
1229 // Wrapper for glFramebufferTexture2D.
1230 void DoFramebufferTexture2D(
1231 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1232 GLint level);
1233
[email protected]7d3c36e2013-07-12 14:13:161234 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1235 void DoFramebufferTexture2DMultisample(
1236 GLenum target, GLenum attachment, GLenum textarget,
1237 GLuint texture, GLint level, GLsizei samples);
1238
1239 // Common implementation for both DoFramebufferTexture2D wrappers.
1240 void DoFramebufferTexture2DCommon(const char* name,
1241 GLenum target, GLenum attachment, GLenum textarget,
1242 GLuint texture, GLint level, GLsizei samples);
1243
[email protected]a93bb842010-02-16 23:03:471244 // Wrapper for glGenerateMipmap
1245 void DoGenerateMipmap(GLenum target);
1246
[email protected]269200b12010-11-18 22:53:061247 // Helper for GenSharedIdsCHROMIUM commands.
1248 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101249 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1250
[email protected]7d3c36e2013-07-12 14:13:161251 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1252 // to account for different pname values defined in different extension
1253 // variants.
1254 GLenum AdjustGetPname(GLenum pname);
1255
[email protected]b273e432010-04-12 17:23:581256 // Wrapper for DoGetBooleanv.
1257 void DoGetBooleanv(GLenum pname, GLboolean* params);
1258
1259 // Wrapper for DoGetFloatv.
1260 void DoGetFloatv(GLenum pname, GLfloat* params);
1261
[email protected]36cef8ce2010-03-16 07:34:451262 // Wrapper for glGetFramebufferAttachmentParameteriv.
1263 void DoGetFramebufferAttachmentParameteriv(
1264 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1265
[email protected]a0c3e972010-04-21 00:49:131266 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581267 void DoGetIntegerv(GLenum pname, GLint* params);
1268
[email protected]29a9eb52010-04-13 09:04:231269 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061270 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231271 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1272
[email protected]17cfbe0e2013-03-07 01:26:081273 // Wrapper for glGetBufferParameteriv.
1274 void DoGetBufferParameteriv(
1275 GLenum target, GLenum pname, GLint* params);
1276
[email protected]a0c3e972010-04-21 00:49:131277 // Wrapper for glGetProgramiv.
1278 void DoGetProgramiv(
1279 GLuint program_id, GLenum pname, GLint* params);
1280
[email protected]36cef8ce2010-03-16 07:34:451281 // Wrapper for glRenderbufferParameteriv.
1282 void DoGetRenderbufferParameteriv(
1283 GLenum target, GLenum pname, GLint* params);
1284
[email protected]ddd968b82010-03-02 00:44:291285 // Wrapper for glGetShaderiv
1286 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1287
[email protected]b1122982010-05-17 23:04:241288 // Wrappers for glGetVertexAttrib.
1289 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1290 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1291
[email protected]1958e0e2010-04-22 05:17:151292 // Wrappers for glIsXXX functions.
[email protected]3dc69c42012-05-12 02:29:241293 bool DoIsEnabled(GLenum cap);
[email protected]1958e0e2010-04-22 05:17:151294 bool DoIsBuffer(GLuint client_id);
1295 bool DoIsFramebuffer(GLuint client_id);
1296 bool DoIsProgram(GLuint client_id);
1297 bool DoIsRenderbuffer(GLuint client_id);
1298 bool DoIsShader(GLuint client_id);
1299 bool DoIsTexture(GLuint client_id);
[email protected]944b62f32012-09-27 02:20:461300 bool DoIsVertexArrayOES(GLuint client_id);
[email protected]1958e0e2010-04-22 05:17:151301
[email protected]07f54fcc2009-12-22 02:46:301302 // Wrapper for glLinkProgram
1303 void DoLinkProgram(GLuint program);
1304
[email protected]269200b12010-11-18 22:53:061305 // Helper for RegisterSharedIdsCHROMIUM.
1306 void DoRegisterSharedIdsCHROMIUM(
1307 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101308
[email protected]36cef8ce2010-03-16 07:34:451309 // Wrapper for glRenderbufferStorage.
1310 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031311 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451312
[email protected]8e3e0662010-08-23 18:46:301313 // Wrapper for glRenderbufferStorageMultisampleEXT.
1314 void DoRenderbufferStorageMultisample(
1315 GLenum target, GLsizei samples, GLenum internalformat,
1316 GLsizei width, GLsizei height);
1317
[email protected]b273e432010-04-12 17:23:581318 // Wrapper for glReleaseShaderCompiler.
1319 void DoReleaseShaderCompiler() { }
1320
[email protected]3916c97e2010-02-25 03:20:501321 // Wrappers for glTexParameter functions.
1322 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1323 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1324 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1325 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1326
1327 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1328 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121329 void DoUniform1i(GLint fake_location, GLint v0);
1330 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1331 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1332 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1333 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101334
1335 // Wrappers for glUniformfv because some drivers don't correctly accept
1336 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121337 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1338 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1339 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1340 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501341
[email protected]43c2f1f2011-03-25 18:35:361342 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121343 GLint fake_location, GLsizei count, GLboolean transpose,
1344 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361345 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121346 GLint fake_location, GLsizei count, GLboolean transpose,
1347 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361348 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121349 GLint fake_location, GLsizei count, GLboolean transpose,
1350 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361351
[email protected]af6380962012-11-29 23:24:131352 bool SetVertexAttribValue(
1353 const char* function_name, GLuint index, const GLfloat* value);
1354
[email protected]b1122982010-05-17 23:04:241355 // Wrappers for glVertexAttrib??
1356 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1357 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1358 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1359 void DoVertexAttrib4f(
1360 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1361 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1362 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1363 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1364 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1365
[email protected]43410e92012-04-20 17:06:281366 // Wrapper for glViewport
1367 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1368
[email protected]07f54fcc2009-12-22 02:46:301369 // Wrapper for glUseProgram
1370 void DoUseProgram(GLuint program);
1371
[email protected]ae51d192010-04-27 00:48:031372 // Wrapper for glValidateProgram.
1373 void DoValidateProgram(GLuint program_client_id);
1374
[email protected]d2a0e1a2012-08-12 02:25:011375 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1376 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1377 void DoPopGroupMarkerEXT(void);
1378
[email protected]4e8a5b122010-05-08 22:00:101379 // Gets the number of values that will be returned by glGetXXX. Returns
1380 // false if pname is unknown.
1381 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1382
[email protected]07f54fcc2009-12-22 02:46:301383 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]ad84a3a2012-06-08 21:42:431384 bool IsDrawValid(
1385 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301386
[email protected]c13e1da62011-09-09 21:48:301387 // Returns true if successful, simulated will be true if attrib0 was
1388 // simulated.
[email protected]c6aef902012-02-14 03:31:421389 bool SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:431390 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
[email protected]43410e92012-04-20 17:06:281391 void RestoreStateForAttrib(GLuint attrib);
[email protected]b1122982010-05-17 23:04:241392
[email protected]ef526492010-06-02 23:12:251393 // Returns true if textures were set.
1394 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501395 void RestoreStateForNonRenderableTextures();
1396
[email protected]8fbedc02010-11-18 18:43:401397 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421398 bool SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:431399 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421400 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401401 void RestoreStateForSimulatedFixedAttribs();
1402
[email protected]c6aef902012-02-14 03:31:421403 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1404 // cases (primcount is 0 for non-instanced).
1405 error::Error DoDrawArrays(
[email protected]ad84a3a2012-06-08 21:42:431406 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421407 bool instanced, GLenum mode, GLint first, GLsizei count,
1408 GLsizei primcount);
1409 error::Error DoDrawElements(
[email protected]ad84a3a2012-06-08 21:42:431410 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421411 bool instanced, GLenum mode, GLsizei count, GLenum type,
1412 int32 offset, GLsizei primcount);
1413
[email protected]07f54fcc2009-12-22 02:46:301414 // Gets the buffer id for a given target.
[email protected]16ccec12013-02-28 03:40:211415 Buffer* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301416 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]944b62f32012-09-27 02:20:461417 if (target == GL_ARRAY_BUFFER) {
[email protected]7cd76fd2013-06-02 21:11:111418 return state_.bound_array_buffer.get();
[email protected]944b62f32012-09-27 02:20:461419 } else {
[email protected]e259eb412012-10-13 05:47:241420 return state_.vertex_attrib_manager->element_array_buffer();
[email protected]944b62f32012-09-27 02:20:461421 }
[email protected]07f54fcc2009-12-22 02:46:301422 }
1423
[email protected]a93bb842010-02-16 23:03:471424 // Gets the texture id for a given target.
[email protected]370eaf12013-05-18 09:19:491425 TextureRef* GetTextureInfoForTarget(GLenum target) {
[email protected]e259eb412012-10-13 05:47:241426 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]370eaf12013-05-18 09:19:491427 TextureRef* texture = NULL;
[email protected]a93bb842010-02-16 23:03:471428 switch (target) {
1429 case GL_TEXTURE_2D:
[email protected]7cd76fd2013-06-02 21:11:111430 texture = unit.bound_texture_2d.get();
[email protected]3916c97e2010-02-25 03:20:501431 break;
[email protected]a93bb842010-02-16 23:03:471432 case GL_TEXTURE_CUBE_MAP:
1433 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1434 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1435 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1436 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1437 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1438 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]7cd76fd2013-06-02 21:11:111439 texture = unit.bound_texture_cube_map.get();
[email protected]3916c97e2010-02-25 03:20:501440 break;
[email protected]61eeb33f2011-07-26 15:30:311441 case GL_TEXTURE_EXTERNAL_OES:
[email protected]7cd76fd2013-06-02 21:11:111442 texture = unit.bound_texture_external_oes.get();
[email protected]61eeb33f2011-07-26 15:30:311443 break;
[email protected]e51bdf32011-11-23 22:21:461444 case GL_TEXTURE_RECTANGLE_ARB:
[email protected]7cd76fd2013-06-02 21:11:111445 texture = unit.bound_texture_rectangle_arb.get();
[email protected]e51bdf32011-11-23 22:21:461446 break;
[email protected]a93bb842010-02-16 23:03:471447 default:
1448 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501449 return NULL;
[email protected]a93bb842010-02-16 23:03:471450 }
[email protected]02965c22013-03-09 02:40:071451 return texture;
[email protected]a93bb842010-02-16 23:03:471452 }
1453
[email protected]370eaf12013-05-18 09:19:491454 TextureRef* GetTextureInfoForTargetUnlessDefault(
[email protected]09d50362012-10-18 20:54:371455 GLenum target) {
[email protected]370eaf12013-05-18 09:19:491456 TextureRef* texture = GetTextureInfoForTarget(target);
[email protected]02965c22013-03-09 02:40:071457 if (!texture)
[email protected]09d50362012-10-18 20:54:371458 return NULL;
[email protected]02965c22013-03-09 02:40:071459 if (texture == texture_manager()->GetDefaultTextureInfo(target))
[email protected]09d50362012-10-18 20:54:371460 return NULL;
[email protected]02965c22013-03-09 02:40:071461 return texture;
[email protected]09d50362012-10-18 20:54:371462 }
1463
[email protected]61eeb33f2011-07-26 15:30:311464 GLenum GetBindTargetForSamplerType(GLenum type) {
1465 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461466 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1467 switch (type) {
1468 case GL_SAMPLER_2D:
1469 return GL_TEXTURE_2D;
1470 case GL_SAMPLER_CUBE:
1471 return GL_TEXTURE_CUBE_MAP;
1472 case GL_SAMPLER_EXTERNAL_OES:
1473 return GL_TEXTURE_EXTERNAL_OES;
1474 case GL_SAMPLER_2D_RECT_ARB:
1475 return GL_TEXTURE_RECTANGLE_ARB;
1476 }
1477
1478 NOTREACHED();
1479 return 0;
[email protected]61eeb33f2011-07-26 15:30:311480 }
1481
[email protected]8e3e0662010-08-23 18:46:301482 // Gets the framebuffer info for a particular target.
[email protected]4d8f0dd2013-03-09 14:37:061483 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1484 Framebuffer* framebuffer = NULL;
[email protected]8e3e0662010-08-23 18:46:301485 switch (target) {
1486 case GL_FRAMEBUFFER:
[email protected]ebfb73c2012-08-15 02:37:451487 case GL_DRAW_FRAMEBUFFER_EXT:
[email protected]7cd76fd2013-06-02 21:11:111488 framebuffer = state_.bound_draw_framebuffer.get();
[email protected]8e3e0662010-08-23 18:46:301489 break;
[email protected]ebfb73c2012-08-15 02:37:451490 case GL_READ_FRAMEBUFFER_EXT:
[email protected]7cd76fd2013-06-02 21:11:111491 framebuffer = state_.bound_read_framebuffer.get();
[email protected]8e3e0662010-08-23 18:46:301492 break;
1493 default:
1494 NOTREACHED();
1495 break;
1496 }
[email protected]4d8f0dd2013-03-09 14:37:061497 return framebuffer;
[email protected]8e3e0662010-08-23 18:46:301498 }
1499
[email protected]ed9f9cd2013-02-27 21:12:351500 Renderbuffer* GetRenderbufferInfoForTarget(
[email protected]0d6bfdc2011-11-02 01:32:201501 GLenum target) {
[email protected]ee2a79c32013-03-10 03:50:271502 Renderbuffer* renderbuffer = NULL;
[email protected]0d6bfdc2011-11-02 01:32:201503 switch (target) {
1504 case GL_RENDERBUFFER:
[email protected]7cd76fd2013-06-02 21:11:111505 renderbuffer = state_.bound_renderbuffer.get();
[email protected]0d6bfdc2011-11-02 01:32:201506 break;
1507 default:
1508 NOTREACHED();
1509 break;
1510 }
[email protected]ee2a79c32013-03-10 03:50:271511 return renderbuffer;
[email protected]0d6bfdc2011-11-02 01:32:201512 }
1513
[email protected]f7b85372010-02-03 01:11:371514 // Validates the program and location for a glGetUniform call and returns
1515 // a SizeResult setup to receive the result. Returns true if glGetUniform
1516 // should be called.
1517 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121518 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371519 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121520 error::Error* error, GLint* real_location, GLuint* service_id,
1521 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371522
[email protected]1078f912011-12-23 13:12:141523 // Computes the estimated memory used for the backbuffer and passes it to
1524 // the tracing system.
[email protected]260ddc4e2012-06-28 00:01:531525 size_t GetBackbufferMemoryTotal();
[email protected]1078f912011-12-23 13:12:141526
[email protected]a10b4a02012-11-26 23:09:501527 virtual bool WasContextLost() OVERRIDE;
[email protected]93a7d98f2013-07-11 00:04:221528 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
[email protected]c4485aad62012-12-17 10:19:091529 virtual void LoseContext(uint32 reset_status) OVERRIDE;
[email protected]38d139d2011-07-14 00:38:431530
[email protected]e51bdf32011-11-23 22:21:461531#if defined(OS_MACOSX)
1532 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1533#endif
1534
[email protected]81375742012-06-08 00:04:001535 // Validates the combination of texture parameters. For example validates that
1536 // for a given format the specific type, level and targets are valid.
1537 // Synthesizes the correct GL error if invalid. Returns true if valid.
1538 bool ValidateTextureParameters(
1539 const char* function_name,
1540 GLenum target, GLenum format, GLenum type, GLint level);
1541
[email protected]ad84a3a2012-06-08 21:42:431542 bool ValidateCompressedTexDimensions(
1543 const char* function_name,
1544 GLint level, GLsizei width, GLsizei height, GLenum format);
1545 bool ValidateCompressedTexFuncData(
1546 const char* function_name,
1547 GLsizei width, GLsizei height, GLenum format, size_t size);
1548 bool ValidateCompressedTexSubDimensions(
1549 const char* function_name,
1550 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1551 GLsizei width, GLsizei height, GLenum format,
[email protected]ed9f9cd2013-02-27 21:12:351552 Texture* texture);
[email protected]ad84a3a2012-06-08 21:42:431553
[email protected]ab09b612013-03-11 22:11:511554 void RenderWarning(const char* filename, int line, const std::string& msg);
1555 void PerformanceWarning(
1556 const char* filename, int line, const std::string& msg);
[email protected]0f8afe82012-05-14 23:43:011557
[email protected]62e155e2012-10-23 22:43:151558 const FeatureInfo::FeatureFlags& features() const {
1559 return feature_info_->feature_flags();
1560 }
1561
1562 const FeatureInfo::Workarounds& workarounds() const {
1563 return feature_info_->workarounds();
1564 }
1565
[email protected]a7266a92012-06-28 02:11:081566 bool ShouldDeferDraws() {
1567 return !offscreen_target_frame_buffer_.get() &&
[email protected]7cd76fd2013-06-02 21:11:111568 state_.bound_draw_framebuffer.get() == NULL &&
[email protected]a7266a92012-06-28 02:11:081569 surface_->DeferDraws();
1570 }
1571
[email protected]09e17272012-11-30 10:30:441572 bool ShouldDeferReads() {
1573 return !offscreen_target_frame_buffer_.get() &&
[email protected]7cd76fd2013-06-02 21:11:111574 state_.bound_read_framebuffer.get() == NULL &&
[email protected]09e17272012-11-30 10:30:441575 surface_->DeferDraws();
1576 }
1577
[email protected]df37b9932013-03-08 05:21:421578 void ForceCompileShaderIfPending(Shader* shader);
[email protected]c447acd2012-07-23 23:48:411579
[email protected]96449d2c2009-11-25 00:01:321580 // Generate a member function prototype for each command in an automated and
1581 // typesafe way.
1582 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141583 Error Handle ## name( \
[email protected]ed9f9cd2013-02-27 21:12:351584 uint32 immediate_data_size, \
1585 const cmds::name& args); \
[email protected]96449d2c2009-11-25 00:01:321586
1587 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1588
1589 #undef GLES2_CMD_OP
1590
[email protected]2f2d7042010-04-14 21:45:581591 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381592 scoped_refptr<gfx::GLSurface> surface_;
1593 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021594
[email protected]a3ded6d2010-10-19 06:44:391595 // The ContextGroup for this decoder uses to track resources.
[email protected]ed9f9cd2013-02-27 21:12:351596 scoped_refptr<ContextGroup> group_;
[email protected]a3ded6d2010-10-19 06:44:391597
[email protected]1d82e822013-04-10 21:32:321598 DebugMarkerManager debug_marker_manager_;
1599 Logger logger_;
1600
[email protected]e259eb412012-10-13 05:47:241601 // All the state for this context.
1602 ContextState state_;
1603
[email protected]34ff8b0c2010-10-01 20:06:021604 // Current width and height of the offscreen frame buffer.
1605 gfx::Size offscreen_size_;
1606
[email protected]96449d2c2009-11-25 00:01:321607 // Util to help with GL.
1608 GLES2Util util_;
1609
[email protected]43410e92012-04-20 17:06:281610 // unpack flip y as last set by glPixelStorei
1611 bool unpack_flip_y_;
1612
[email protected]6c75c712012-06-19 15:43:171613 // unpack (un)premultiply alpha as last set by glPixelStorei
[email protected]43410e92012-04-20 17:06:281614 bool unpack_premultiply_alpha_;
[email protected]6c75c712012-06-19 15:43:171615 bool unpack_unpremultiply_alpha_;
[email protected]43410e92012-04-20 17:06:281616
[email protected]944b62f32012-09-27 02:20:461617 // Default vertex attribs manager, used when no VAOs are bound.
[email protected]ed9f9cd2013-02-27 21:12:351618 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301619
[email protected]b1122982010-05-17 23:04:241620 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1621 GLuint attrib_0_buffer_id_;
1622
1623 // The value currently in attrib_0.
[email protected]af6380962012-11-29 23:24:131624 Vec4 attrib_0_value_;
[email protected]b1122982010-05-17 23:04:241625
[email protected]fc753442011-02-04 19:49:491626 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1627 bool attrib_0_buffer_matches_value_;
1628
[email protected]b1122982010-05-17 23:04:241629 // The size of attrib 0.
1630 GLsizei attrib_0_size_;
1631
[email protected]8fbedc02010-11-18 18:43:401632 // The buffer used to simulate GL_FIXED attribs.
1633 GLuint fixed_attrib_buffer_id_;
1634
1635 // The size of fiixed attrib buffer.
1636 GLsizei fixed_attrib_buffer_size_;
1637
[email protected]3a2e7c7b2010-08-06 01:12:281638 // state saved for clearing so we can clear render buffers and then
1639 // restore to these values.
[email protected]88a61bf2012-10-27 13:00:421640 bool clear_state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281641
[email protected]b9363b22010-06-09 22:06:151642 // The offscreen frame buffer that the client renders to. With EGL, the
1643 // depth and stencil buffers are separate. With regular GL there is a single
1644 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1645 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]ed9f9cd2013-02-27 21:12:351646 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1647 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1648 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1649 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1650 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021651 GLenum offscreen_target_color_format_;
1652 GLenum offscreen_target_depth_format_;
1653 GLenum offscreen_target_stencil_format_;
1654 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561655 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351656
[email protected]de26b3c2011-08-03 21:54:271657 // The copy that is saved when SwapBuffers is called.
[email protected]ed9f9cd2013-02-27 21:12:351658 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1659 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
[email protected]370eaf12013-05-18 09:19:491660 scoped_refptr<TextureRef>
[email protected]ed9f9cd2013-02-27 21:12:351661 offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271662
1663 // The copy that is used as the destination for multi-sample resolves.
[email protected]ed9f9cd2013-02-27 21:12:351664 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1665 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051666 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351667
[email protected]882ba1e22012-03-08 19:02:531668 scoped_ptr<QueryManager> query_manager_;
[email protected]882ba1e22012-03-08 19:02:531669
[email protected]944b62f32012-09-27 02:20:461670 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1671
[email protected]729c0b42013-05-26 02:05:071672 base::Callback<void(gfx::Size, float)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001673
[email protected]840a7e462013-02-27 01:29:511674 WaitSyncPointCallback wait_sync_point_callback_;
[email protected]43f28f832010-02-03 02:28:481675
[email protected]e3932abb2013-03-13 00:01:371676 ShaderCacheCallback shader_cache_callback_;
1677
[email protected]85a4ac22013-05-31 01:58:471678 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
[email protected]b0af4f52011-09-28 22:04:421679
[email protected]32fe9aa2011-01-21 23:47:131680 // The format of the back buffer_
1681 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461682 bool back_buffer_has_depth_;
1683 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131684
[email protected]60f22d32012-12-12 00:31:581685 // Backbuffer attachments that are currently undefined.
1686 uint32 backbuffer_needs_clear_bits_;
1687
[email protected]473c01ccb2011-06-07 01:33:301688 bool teximage2d_faster_than_texsubimage2d_;
[email protected]473c01ccb2011-06-07 01:33:301689
[email protected]a3a93e7b2010-08-28 00:48:561690 // The current decoder error.
1691 error::Error current_decoder_error_;
1692
[email protected]b1d2dcb2010-05-17 19:24:181693 bool use_shader_translator_;
[email protected]87fb6ab2012-06-13 22:28:041694 scoped_refptr<ShaderTranslator> vertex_translator_;
1695 scoped_refptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181696
[email protected]e82fb792011-09-22 00:33:291697 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411698
[email protected]915a59a12010-09-30 21:29:111699 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051700 const Validators* validators_;
[email protected]ed9f9cd2013-02-27 21:12:351701 scoped_refptr<FeatureInfo> feature_info_;
[email protected]9438b012010-06-15 22:55:051702
[email protected]b493ee622011-04-13 23:52:001703 // This indicates all the following texSubImage2D calls that are part of the
1704 // failed texImage2D call should be ignored.
1705 bool tex_image_2d_failed_;
1706
[email protected]65225772011-05-12 21:10:241707 int frame_number_;
1708
[email protected]706b69f2012-07-27 04:59:301709 bool has_robustness_extension_;
[email protected]38d139d2011-07-14 00:38:431710 GLenum reset_status_;
[email protected]93a7d98f2013-07-11 00:04:221711 bool reset_by_robustness_extension_;
[email protected]38d139d2011-07-14 00:38:431712
[email protected]f0d74742011-10-03 16:31:041713 // These flags are used to override the state of the shared feature_info_
1714 // member. Because the same FeatureInfo instance may be shared among many
1715 // contexts, the assumptions on the availablity of extensions in WebGL
1716 // contexts may be broken. These flags override the shared state to preserve
1717 // WebGL semantics.
1718 bool force_webgl_glsl_validation_;
1719 bool derivatives_explicitly_enabled_;
[email protected]70dc60932013-06-04 03:33:491720 bool frag_depth_explicitly_enabled_;
[email protected]aff39ac82013-06-08 04:53:131721 bool draw_buffers_explicitly_enabled_;
[email protected]f0d74742011-10-03 16:31:041722
[email protected]062c38b2012-01-18 03:25:101723 bool compile_shader_always_succeeds_;
1724
[email protected]cae20172012-12-07 00:06:191725 // Log extra info.
1726 bool service_logging_;
1727
[email protected]e51bdf32011-11-23 22:21:461728#if defined(OS_MACOSX)
1729 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1730 TextureToIOSurfaceMap texture_to_io_surface_map_;
1731#endif
1732
[email protected]43410e92012-04-20 17:06:281733 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1734
[email protected]1868a342012-11-07 15:56:021735 // Cached values of the currently assigned viewport dimensions.
1736 GLsizei viewport_max_width_;
1737 GLsizei viewport_max_height_;
1738
[email protected]63b465922012-09-06 02:04:521739 // Command buffer stats.
1740 int texture_upload_count_;
1741 base::TimeDelta total_texture_upload_time_;
1742 base::TimeDelta total_processing_commands_time_;
1743
[email protected]fb97b662013-02-20 23:02:141744 scoped_ptr<GPUTracer> gpu_tracer_;
[email protected]94307712012-11-16 23:26:111745
[email protected]96449d2c2009-11-25 00:01:321746 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1747};
1748
[email protected]ab09b612013-03-11 22:11:511749ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1750 const char* function_name, GLES2DecoderImpl* decoder)
1751 : function_name_(function_name),
1752 decoder_(decoder) {
[email protected]d3eba342013-04-18 21:11:501753 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(decoder_->GetErrorState(),
1754 function_name_);
[email protected]6217d392010-03-25 22:08:351755}
1756
1757ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
[email protected]d3eba342013-04-18 21:11:501758 ERRORSTATE_CLEAR_REAL_GL_ERRORS(decoder_->GetErrorState(), function_name_);
[email protected]6217d392010-03-25 22:08:351759}
1760
1761ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1762 GLuint id)
1763 : decoder_(decoder) {
[email protected]ab09b612013-03-11 22:11:511764 ScopedGLErrorSuppressor suppressor(
1765 "ScopedTexture2DBinder::ctor", decoder_);
[email protected]6217d392010-03-25 22:08:351766
1767 // TODO(apatrick): Check if there are any other states that need to be reset
1768 // before binding a new texture.
1769 glActiveTexture(GL_TEXTURE0);
1770 glBindTexture(GL_TEXTURE_2D, id);
1771}
1772
1773ScopedTexture2DBinder::~ScopedTexture2DBinder() {
[email protected]ab09b612013-03-11 22:11:511774 ScopedGLErrorSuppressor suppressor(
1775 "ScopedTexture2DBinder::dtor", decoder_);
[email protected]8e3e0662010-08-23 18:46:301776 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351777}
1778
1779ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1780 GLuint id)
1781 : decoder_(decoder) {
[email protected]ab09b612013-03-11 22:11:511782 ScopedGLErrorSuppressor suppressor(
1783 "ScopedRenderBufferBinder::ctor", decoder_);
[email protected]6217d392010-03-25 22:08:351784 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1785}
1786
1787ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
[email protected]ab09b612013-03-11 22:11:511788 ScopedGLErrorSuppressor suppressor(
1789 "ScopedRenderBufferBinder::dtor", decoder_);
[email protected]8e3e0662010-08-23 18:46:301790 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351791}
1792
1793ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1794 GLuint id)
1795 : decoder_(decoder) {
[email protected]ab09b612013-03-11 22:11:511796 ScopedGLErrorSuppressor suppressor(
1797 "ScopedFrameBufferBinder::ctor", decoder_);
[email protected]6217d392010-03-25 22:08:351798 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
[email protected]70d34263c2013-01-09 00:27:451799 decoder->OnFboChanged();
[email protected]6217d392010-03-25 22:08:351800}
1801
1802ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
[email protected]ab09b612013-03-11 22:11:511803 ScopedGLErrorSuppressor suppressor(
1804 "ScopedFrameBufferBinder::dtor", decoder_);
[email protected]8e3e0662010-08-23 18:46:301805 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351806}
1807
[email protected]34ff8b0c2010-10-01 20:06:021808ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271809 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521810 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021811 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1812 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]e259eb412012-10-13 05:47:241813 (!decoder_->state_.bound_read_framebuffer.get() ||
[email protected]c0701082011-04-20 00:34:521814 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021815 if (!resolve_and_bind_)
1816 return;
1817
[email protected]ab09b612013-03-11 22:11:511818 ScopedGLErrorSuppressor suppressor(
1819 "ScopedResolvedFrameBufferBinder::ctor", decoder_);
[email protected]34ff8b0c2010-10-01 20:06:021820 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1821 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271822 GLuint targetid;
1823 if (internal) {
1824 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1825 decoder_->offscreen_resolved_frame_buffer_.reset(
[email protected]ed9f9cd2013-02-27 21:12:351826 new BackFramebuffer(decoder_));
[email protected]de26b3c2011-08-03 21:54:271827 decoder_->offscreen_resolved_frame_buffer_->Create();
[email protected]ed9f9cd2013-02-27 21:12:351828 decoder_->offscreen_resolved_color_texture_.reset(
1829 new BackTexture(decoder_));
[email protected]de26b3c2011-08-03 21:54:271830 decoder_->offscreen_resolved_color_texture_->Create();
1831
1832 DCHECK(decoder_->offscreen_saved_color_format_);
1833 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:091834 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1835 false);
[email protected]de26b3c2011-08-03 21:54:271836 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1837 decoder_->offscreen_resolved_color_texture_.get());
1838 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1839 GL_FRAMEBUFFER_COMPLETE) {
1840 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1841 << "because offscreen resolved FBO was incomplete.";
1842 return;
1843 }
1844 }
1845 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1846 } else {
1847 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1848 }
1849 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021850 const int width = decoder_->offscreen_size_.width();
1851 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181852 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151853 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021854 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1855 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1856 } else {
1857 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1858 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1859 }
[email protected]de26b3c2011-08-03 21:54:271860 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021861}
1862
1863ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1864 if (!resolve_and_bind_)
1865 return;
1866
[email protected]ab09b612013-03-11 22:11:511867 ScopedGLErrorSuppressor suppressor(
1868 "ScopedResolvedFrameBufferBinder::dtor", decoder_);
[email protected]34ff8b0c2010-10-01 20:06:021869 decoder_->RestoreCurrentFramebufferBindings();
[email protected]f731b9462012-10-30 00:35:221870 if (decoder_->state_.enable_flags.scissor_test) {
[email protected]8c3e68782010-10-27 16:41:181871 glEnable(GL_SCISSOR_TEST);
1872 }
[email protected]34ff8b0c2010-10-01 20:06:021873}
1874
[email protected]63b465922012-09-06 02:04:521875ScopedTextureUploadTimer::ScopedTextureUploadTimer(GLES2DecoderImpl* decoder)
1876 : decoder_(decoder),
1877 begin_time_(base::TimeTicks::HighResNow()) {
1878}
1879
1880ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
1881 decoder_->texture_upload_count_++;
1882 decoder_->total_texture_upload_time_ +=
1883 base::TimeTicks::HighResNow() - begin_time_;
1884}
1885
[email protected]ed9f9cd2013-02-27 21:12:351886BackTexture::BackTexture(GLES2DecoderImpl* decoder)
[email protected]6217d392010-03-25 22:08:351887 : decoder_(decoder),
[email protected]7989c9e2013-01-23 06:39:261888 memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
[email protected]68e81a4a62012-12-13 01:16:481889 bytes_allocated_(0),
[email protected]ff6493f2012-07-31 19:52:251890 id_(0) {
[email protected]6217d392010-03-25 22:08:351891}
1892
[email protected]ed9f9cd2013-02-27 21:12:351893BackTexture::~BackTexture() {
[email protected]6217d392010-03-25 22:08:351894 // This does not destroy the render texture because that would require that
1895 // the associated GL context was current. Just check that it was explicitly
1896 // destroyed.
1897 DCHECK_EQ(id_, 0u);
1898}
1899
[email protected]ed9f9cd2013-02-27 21:12:351900void BackTexture::Create() {
[email protected]ab09b612013-03-11 22:11:511901 ScopedGLErrorSuppressor suppressor("BackTexture::Create", decoder_);
[email protected]6217d392010-03-25 22:08:351902 Destroy();
1903 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581904 ScopedTexture2DBinder binder(decoder_, id_);
1905 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1906 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1907 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1908 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161909
1910 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1911 // never called on an offscreen context, no data will ever be uploaded to the
1912 // saved offscreen color texture (it is deferred until to when SwapBuffers
1913 // is called). My idea is that some nvidia drivers might have a bug where
1914 // deleting a texture that has never been populated might cause a
1915 // crash.
1916 glTexImage2D(
1917 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]68e81a4a62012-12-13 01:16:481918
1919 bytes_allocated_ = 16u * 16u * 4u;
1920 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]6217d392010-03-25 22:08:351921}
1922
[email protected]ed9f9cd2013-02-27 21:12:351923bool BackTexture::AllocateStorage(
1924 const gfx::Size& size, GLenum format, bool zero) {
[email protected]6217d392010-03-25 22:08:351925 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:511926 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage", decoder_);
[email protected]6217d392010-03-25 22:08:351927 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]678a73f2012-12-19 19:22:091928 uint32 image_size = 0;
1929 GLES2Util::ComputeImageDataSizes(
1930 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1931 NULL, NULL);
1932
[email protected]7989c9e2013-01-23 06:39:261933 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1934 return false;
1935 }
1936
[email protected]40d90a22013-04-09 03:39:551937 scoped_ptr<char[]> zero_data;
[email protected]678a73f2012-12-19 19:22:091938 if (zero) {
1939 zero_data.reset(new char[image_size]);
1940 memset(zero_data.get(), 0, image_size);
1941 }
[email protected]6217d392010-03-25 22:08:351942
[email protected]8f1d2aa2013-05-10 23:45:381943 glTexImage2D(GL_TEXTURE_2D,
1944 0, // mip level
1945 format,
1946 size.width(),
1947 size.height(),
1948 0, // border
1949 format,
1950 GL_UNSIGNED_BYTE,
1951 zero_data.get());
[email protected]6217d392010-03-25 22:08:351952
[email protected]d37231fa2010-04-09 21:16:021953 size_ = size;
1954
[email protected]1078f912011-12-23 13:12:141955 bool success = glGetError() == GL_NO_ERROR;
1956 if (success) {
[email protected]68e81a4a62012-12-13 01:16:481957 memory_tracker_.TrackMemFree(bytes_allocated_);
1958 bytes_allocated_ = image_size;
1959 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]1078f912011-12-23 13:12:141960 }
1961 return success;
[email protected]6217d392010-03-25 22:08:351962}
1963
[email protected]ed9f9cd2013-02-27 21:12:351964void BackTexture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351965 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:511966 ScopedGLErrorSuppressor suppressor("BackTexture::Copy", decoder_);
[email protected]6217d392010-03-25 22:08:351967 ScopedTexture2DBinder binder(decoder_, id_);
1968 glCopyTexImage2D(GL_TEXTURE_2D,
1969 0, // level
[email protected]3a4d0c52011-06-29 23:11:581970 format,
[email protected]6217d392010-03-25 22:08:351971 0, 0,
1972 size.width(),
1973 size.height(),
1974 0); // border
1975}
1976
[email protected]ed9f9cd2013-02-27 21:12:351977void BackTexture::Destroy() {
[email protected]6217d392010-03-25 22:08:351978 if (id_ != 0) {
[email protected]ab09b612013-03-11 22:11:511979 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy", decoder_);
[email protected]6217d392010-03-25 22:08:351980 glDeleteTextures(1, &id_);
1981 id_ = 0;
1982 }
[email protected]68e81a4a62012-12-13 01:16:481983 memory_tracker_.TrackMemFree(bytes_allocated_);
1984 bytes_allocated_ = 0;
[email protected]6217d392010-03-25 22:08:351985}
1986
[email protected]ed9f9cd2013-02-27 21:12:351987void BackTexture::Invalidate() {
[email protected]97872062010-11-03 19:07:051988 id_ = 0;
1989}
1990
[email protected]ed9f9cd2013-02-27 21:12:351991BackRenderbuffer::BackRenderbuffer(GLES2DecoderImpl* decoder)
[email protected]6217d392010-03-25 22:08:351992 : decoder_(decoder),
[email protected]7989c9e2013-01-23 06:39:261993 memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
[email protected]68e81a4a62012-12-13 01:16:481994 bytes_allocated_(0),
[email protected]ff6493f2012-07-31 19:52:251995 id_(0) {
[email protected]6217d392010-03-25 22:08:351996}
1997
[email protected]ed9f9cd2013-02-27 21:12:351998BackRenderbuffer::~BackRenderbuffer() {
[email protected]6217d392010-03-25 22:08:351999 // This does not destroy the render buffer because that would require that
2000 // the associated GL context was current. Just check that it was explicitly
2001 // destroyed.
2002 DCHECK_EQ(id_, 0u);
2003}
2004
[email protected]ed9f9cd2013-02-27 21:12:352005void BackRenderbuffer::Create() {
[email protected]ab09b612013-03-11 22:11:512006 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create", decoder_);
[email protected]6217d392010-03-25 22:08:352007 Destroy();
2008 glGenRenderbuffersEXT(1, &id_);
2009}
2010
[email protected]ed9f9cd2013-02-27 21:12:352011bool BackRenderbuffer::AllocateStorage(const gfx::Size& size, GLenum format,
2012 GLsizei samples) {
[email protected]ab09b612013-03-11 22:11:512013 ScopedGLErrorSuppressor suppressor(
2014 "BackRenderbuffer::AllocateStorage", decoder_);
[email protected]6217d392010-03-25 22:08:352015 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]7989c9e2013-01-23 06:39:262016
2017 uint32 estimated_size = 0;
2018 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
2019 size.width(), size.height(), samples, format, &estimated_size)) {
2020 return false;
2021 }
2022
2023 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2024 return false;
2025 }
2026
[email protected]34ff8b0c2010-10-01 20:06:022027 if (samples <= 1) {
2028 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2029 format,
2030 size.width(),
2031 size.height());
2032 } else {
[email protected]57edfdad2012-02-07 04:57:152033 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:022034 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
2035 samples,
2036 format,
2037 size.width(),
2038 size.height());
2039 } else {
2040 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
2041 samples,
2042 format,
2043 size.width(),
2044 size.height());
2045 }
2046 }
[email protected]1078f912011-12-23 13:12:142047 bool success = glGetError() == GL_NO_ERROR;
2048 if (success) {
[email protected]68e81a4a62012-12-13 01:16:482049 memory_tracker_.TrackMemFree(bytes_allocated_);
[email protected]7989c9e2013-01-23 06:39:262050 bytes_allocated_ = estimated_size;
[email protected]68e81a4a62012-12-13 01:16:482051 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]1078f912011-12-23 13:12:142052 }
2053 return success;
[email protected]6217d392010-03-25 22:08:352054}
2055
[email protected]ed9f9cd2013-02-27 21:12:352056void BackRenderbuffer::Destroy() {
[email protected]6217d392010-03-25 22:08:352057 if (id_ != 0) {
[email protected]ab09b612013-03-11 22:11:512058 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy", decoder_);
[email protected]6217d392010-03-25 22:08:352059 glDeleteRenderbuffersEXT(1, &id_);
2060 id_ = 0;
2061 }
[email protected]68e81a4a62012-12-13 01:16:482062 memory_tracker_.TrackMemFree(bytes_allocated_);
2063 bytes_allocated_ = 0;
[email protected]6217d392010-03-25 22:08:352064}
2065
[email protected]ed9f9cd2013-02-27 21:12:352066void BackRenderbuffer::Invalidate() {
[email protected]97872062010-11-03 19:07:052067 id_ = 0;
2068}
2069
[email protected]ed9f9cd2013-02-27 21:12:352070BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
[email protected]6217d392010-03-25 22:08:352071 : decoder_(decoder),
2072 id_(0) {
2073}
2074
[email protected]ed9f9cd2013-02-27 21:12:352075BackFramebuffer::~BackFramebuffer() {
[email protected]6217d392010-03-25 22:08:352076 // This does not destroy the frame buffer because that would require that
2077 // the associated GL context was current. Just check that it was explicitly
2078 // destroyed.
2079 DCHECK_EQ(id_, 0u);
2080}
2081
[email protected]ed9f9cd2013-02-27 21:12:352082void BackFramebuffer::Create() {
[email protected]ab09b612013-03-11 22:11:512083 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create", decoder_);
[email protected]6217d392010-03-25 22:08:352084 Destroy();
2085 glGenFramebuffersEXT(1, &id_);
2086}
2087
[email protected]ed9f9cd2013-02-27 21:12:352088void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
[email protected]6217d392010-03-25 22:08:352089 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:512090 ScopedGLErrorSuppressor suppressor(
2091 "BackFramebuffer::AttachRenderTexture", decoder_);
[email protected]6217d392010-03-25 22:08:352092 ScopedFrameBufferBinder binder(decoder_, id_);
2093 GLuint attach_id = texture ? texture->id() : 0;
2094 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2095 GL_COLOR_ATTACHMENT0,
2096 GL_TEXTURE_2D,
2097 attach_id,
2098 0);
2099}
2100
[email protected]ed9f9cd2013-02-27 21:12:352101void BackFramebuffer::AttachRenderBuffer(GLenum target,
2102 BackRenderbuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:352103 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:512104 ScopedGLErrorSuppressor suppressor(
2105 "BackFramebuffer::AttachRenderBuffer", decoder_);
[email protected]6217d392010-03-25 22:08:352106 ScopedFrameBufferBinder binder(decoder_, id_);
2107 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2108 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:152109 target,
[email protected]6217d392010-03-25 22:08:352110 GL_RENDERBUFFER,
2111 attach_id);
2112}
2113
[email protected]ed9f9cd2013-02-27 21:12:352114void BackFramebuffer::Destroy() {
[email protected]6217d392010-03-25 22:08:352115 if (id_ != 0) {
[email protected]ab09b612013-03-11 22:11:512116 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy", decoder_);
[email protected]6217d392010-03-25 22:08:352117 glDeleteFramebuffersEXT(1, &id_);
2118 id_ = 0;
2119 }
2120}
2121
[email protected]ed9f9cd2013-02-27 21:12:352122void BackFramebuffer::Invalidate() {
[email protected]97872062010-11-03 19:07:052123 id_ = 0;
2124}
2125
[email protected]ed9f9cd2013-02-27 21:12:352126GLenum BackFramebuffer::CheckStatus() {
[email protected]6217d392010-03-25 22:08:352127 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:512128 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus", decoder_);
[email protected]6217d392010-03-25 22:08:352129 ScopedFrameBufferBinder binder(decoder_, id_);
2130 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2131}
2132
[email protected]aa7666122011-09-02 19:45:522133GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2134 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:322135}
2136
[email protected]aa7666122011-09-02 19:45:522137GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:392138 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:572139 group_(group),
[email protected]1d82e822013-04-10 21:32:322140 logger_(&debug_marker_manager_),
[email protected]d3eba342013-04-18 21:11:502141 state_(group_->feature_info(), &logger_),
[email protected]43410e92012-04-20 17:06:282142 unpack_flip_y_(false),
2143 unpack_premultiply_alpha_(false),
[email protected]6c75c712012-06-19 15:43:172144 unpack_unpremultiply_alpha_(false),
[email protected]b1122982010-05-17 23:04:242145 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:492146 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:242147 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:402148 fixed_attrib_buffer_id_(0),
2149 fixed_attrib_buffer_size_(0),
[email protected]88a61bf2012-10-27 13:00:422150 clear_state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:022151 offscreen_target_color_format_(0),
2152 offscreen_target_depth_format_(0),
2153 offscreen_target_stencil_format_(0),
2154 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:562155 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:052156 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:132157 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:462158 back_buffer_has_depth_(false),
2159 back_buffer_has_stencil_(false),
[email protected]60f22d32012-12-12 00:31:582160 backbuffer_needs_clear_bits_(0),
[email protected]473c01ccb2011-06-07 01:33:302161 teximage2d_faster_than_texsubimage2d_(true),
[email protected]a3a93e7b2010-08-28 00:48:562162 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:052163 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:112164 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:002165 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:242166 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:432167 frame_number_(0),
[email protected]706b69f2012-07-27 04:59:302168 has_robustness_extension_(false),
[email protected]75c023c2011-08-22 23:54:512169 reset_status_(GL_NO_ERROR),
[email protected]93a7d98f2013-07-11 00:04:222170 reset_by_robustness_extension_(false),
[email protected]f0d74742011-10-03 16:31:042171 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:102172 derivatives_explicitly_enabled_(false),
[email protected]70dc60932013-06-04 03:33:492173 frag_depth_explicitly_enabled_(false),
[email protected]aff39ac82013-06-08 04:53:132174 draw_buffers_explicitly_enabled_(false),
[email protected]43410e92012-04-20 17:06:282175 compile_shader_always_succeeds_(false),
[email protected]cae20172012-12-07 00:06:192176 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2177 switches::kEnableGPUServiceLoggingGPU)),
[email protected]1868a342012-11-07 15:56:022178 viewport_max_width_(0),
2179 viewport_max_height_(0),
[email protected]63b465922012-09-06 02:04:522180 texture_upload_count_(0) {
[email protected]3b1ecc262011-08-03 22:49:572181 DCHECK(group);
2182
[email protected]b1122982010-05-17 23:04:242183 attrib_0_value_.v[0] = 0.0f;
2184 attrib_0_value_.v[1] = 0.0f;
2185 attrib_0_value_.v[2] = 0.0f;
2186 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:152187
[email protected]c2f8c8402010-12-06 18:07:242188 // The shader translator is used for WebGL even when running on EGL
2189 // because additional restrictions are needed (like only enabling
2190 // GL_OES_standard_derivatives on demand). It is used for the unit
[email protected]4b7eba92013-01-08 02:23:562191 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2192 // the empty string to CompileShader and this is not a valid shader.
2193 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
[email protected]39ba4f02012-03-26 01:16:002194 CommandLine::ForCurrentProcess()->HasSwitch(
2195 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:152196 use_shader_translator_ = false;
2197 }
[email protected]473c01ccb2011-06-07 01:33:302198
[email protected]a39370652012-09-25 21:52:132199 // TODO(gman): Consider setting this based on GPU and/or driver.
[email protected]473c01ccb2011-06-07 01:33:302200 if (IsAngle()) {
2201 teximage2d_faster_than_texsubimage2d_ = false;
[email protected]473c01ccb2011-06-07 01:33:302202 }
[email protected]96449d2c2009-11-25 00:01:322203}
2204
[email protected]80eb6b52012-01-19 00:14:412205GLES2DecoderImpl::~GLES2DecoderImpl() {
2206}
2207
[email protected]c410da802011-03-14 19:17:412208bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:382209 const scoped_refptr<gfx::GLSurface>& surface,
2210 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:232211 bool offscreen,
[email protected]c410da802011-03-14 19:17:412212 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:292213 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:412214 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:242215 const std::vector<int32>& attribs) {
[email protected]3551cb202012-05-24 10:55:322216 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
[email protected]63c9b052012-05-17 18:27:382217 DCHECK(context->IsCurrent(surface.get()));
[email protected]66791e382010-07-14 20:48:302218 DCHECK(!context_.get());
2219
[email protected]55e136f2013-04-03 18:50:062220 set_initialized();
[email protected]fb97b662013-02-20 23:02:142221 gpu_tracer_ = GPUTracer::Create();
2222
[email protected]e844ae22012-01-14 03:36:262223 if (CommandLine::ForCurrentProcess()->HasSwitch(
2224 switches::kEnableGPUDebugging)) {
2225 set_debug(true);
2226 }
2227
[email protected]39ba4f02012-03-26 01:16:002228 if (CommandLine::ForCurrentProcess()->HasSwitch(
2229 switches::kEnableGPUCommandLogging)) {
2230 set_log_commands(true);
2231 }
2232
[email protected]062c38b2012-01-18 03:25:102233 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2234 switches::kCompileShaderAlwaysSucceeds);
2235
[email protected]f62a5ab2011-05-23 20:34:152236
[email protected]63c9b052012-05-17 18:27:382237 // Take ownership of the context and surface. The surface can be replaced with
2238 // SetSurface.
[email protected]fbe20372011-06-01 01:46:382239 context_ = context;
[email protected]63c9b052012-05-17 18:27:382240 surface_ = surface;
[email protected]eb54a562010-01-20 21:55:182241
[email protected]c4485aad62012-12-17 10:19:092242 if (!group_->Initialize(this, disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:222243 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392244 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422245 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]63c9b052012-05-17 18:27:382246 Destroy(true);
[email protected]ae1741092010-11-17 19:16:032247 return false;
[email protected]a3ded6d2010-10-19 06:44:392248 }
[email protected]b64c24952012-04-19 03:20:272249 CHECK_GL_ERROR();
[email protected]43410e92012-04-20 17:06:282250
[email protected]e82fb792011-09-22 00:33:292251 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502252
[email protected]af6380962012-11-29 23:24:132253 state_.attrib_values.resize(group_->max_vertex_attribs());
[email protected]944b62f32012-09-27 02:20:462254 default_vertex_attrib_manager_ = new VertexAttribManager();
2255 default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
2256
[email protected]ab4fd7282012-10-12 16:25:572257 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2258 DoBindVertexArrayOES(0);
[email protected]876f6fee2010-08-02 23:10:322259
[email protected]7cd76fd2013-06-02 21:11:112260 query_manager_.reset(new QueryManager(this, feature_info_.get()));
[email protected]944b62f32012-09-27 02:20:462261 vertex_array_manager_.reset(new VertexArrayManager());
[email protected]882ba1e22012-03-08 19:02:532262
[email protected]302ce6d2011-07-07 23:28:112263 util_.set_num_compressed_texture_formats(
2264 validators_->compressed_texture_format.GetValues().size());
2265
[email protected]1071e572011-02-09 20:00:122266 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2267 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2268 // OpenGL ES 2.0 does not have this issue.
2269 glEnableVertexAttribArray(0);
2270 }
[email protected]b1122982010-05-17 23:04:242271 glGenBuffersARB(1, &attrib_0_buffer_id_);
2272 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2273 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2274 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402275 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082276
[email protected]1868a342012-11-07 15:56:022277 state_.texture_units.resize(group_->max_texture_units());
2278 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492279 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312280 // We want the last bind to be 2D.
[email protected]370eaf12013-05-18 09:19:492281 TextureRef* ref;
[email protected]62e155e2012-10-23 22:43:152282 if (features().oes_egl_image_external) {
[email protected]370eaf12013-05-18 09:19:492283 ref = texture_manager()->GetDefaultTextureInfo(
[email protected]02965c22013-03-09 02:40:072284 GL_TEXTURE_EXTERNAL_OES);
[email protected]370eaf12013-05-18 09:19:492285 state_.texture_units[tt].bound_texture_external_oes = ref;
2286 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
[email protected]61eeb33f2011-07-26 15:30:312287 }
[email protected]62e155e2012-10-23 22:43:152288 if (features().arb_texture_rectangle) {
[email protected]370eaf12013-05-18 09:19:492289 ref = texture_manager()->GetDefaultTextureInfo(
[email protected]02965c22013-03-09 02:40:072290 GL_TEXTURE_RECTANGLE_ARB);
[email protected]370eaf12013-05-18 09:19:492291 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2292 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
[email protected]e51bdf32011-11-23 22:21:462293 }
[email protected]370eaf12013-05-18 09:19:492294 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2295 state_.texture_units[tt].bound_texture_cube_map = ref;
2296 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2297 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2298 state_.texture_units[tt].bound_texture_2d = ref;
2299 glBindTexture(GL_TEXTURE_2D, ref->service_id());
[email protected]1958e0e2010-04-22 05:17:152300 }
[email protected]00f893d2010-08-24 18:55:492301 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502302 CHECK_GL_ERROR();
2303
[email protected]297ca1c2011-06-20 23:08:462304 ContextCreationAttribParser attrib_parser;
2305 if (!attrib_parser.Parse(attribs))
2306 return false;
[email protected]41c56362011-06-14 16:47:432307
[email protected]069944672012-04-25 20:52:232308 if (offscreen) {
[email protected]34ff8b0c2010-10-01 20:06:022309 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]b0609652012-12-14 07:24:542310 features().chromium_framebuffer_multisample) {
[email protected]34ff8b0c2010-10-01 20:06:022311 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432312 // max_sample_count must be initialized to a sane value. If
2313 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2314 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022315 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2316 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2317 max_sample_count);
2318 } else {
2319 offscreen_target_samples_ = 1;
2320 }
[email protected]8a61d872012-01-20 12:43:562321 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022322
2323 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2324 const bool rgb8_supported =
2325 context_->HasExtension("GL_OES_rgb8_rgba8");
2326 // The only available default render buffer formats in GLES2 have very
2327 // little precision. Don't enable multisampling unless 8-bit render
2328 // buffer formats are available--instead fall back to 8-bit textures.
2329 if (rgb8_supported && offscreen_target_samples_ > 1) {
2330 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2331 GL_RGBA8 : GL_RGB8;
2332 } else {
2333 offscreen_target_samples_ = 1;
2334 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2335 GL_RGBA : GL_RGB;
2336 }
2337
2338 // ANGLE only supports packed depth/stencil formats, so use it if it is
2339 // available.
2340 const bool depth24_stencil8_supported =
2341 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272342 VLOG(1) << "GL_OES_packed_depth_stencil "
2343 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002344 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2345 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022346 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2347 offscreen_target_stencil_format_ = 0;
2348 } else {
2349 // It may be the case that this depth/stencil combination is not
2350 // supported, but this will be checked later by CheckFramebufferStatus.
2351 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2352 GL_DEPTH_COMPONENT16 : 0;
2353 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2354 GL_STENCIL_INDEX8 : 0;
2355 }
2356 } else {
2357 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2358 GL_RGBA : GL_RGB;
2359
2360 // If depth is requested at all, use the packed depth stencil format if
2361 // it's available, as some desktop GL drivers don't support any non-packed
2362 // formats for depth attachments.
2363 const bool depth24_stencil8_supported =
2364 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272365 VLOG(1) << "GL_EXT_packed_depth_stencil "
2366 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022367
[email protected]71ee3642010-10-14 18:08:002368 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2369 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022370 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2371 offscreen_target_stencil_format_ = 0;
2372 } else {
2373 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2374 GL_DEPTH_COMPONENT : 0;
2375 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2376 GL_STENCIL_INDEX : 0;
2377 }
2378 }
2379
[email protected]97872062010-11-03 19:07:052380 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2381 GL_RGBA : GL_RGB;
2382
[email protected]6217d392010-03-25 22:08:352383 // Create the target frame buffer. This is the one that the client renders
2384 // directly to.
[email protected]ed9f9cd2013-02-27 21:12:352385 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
[email protected]6217d392010-03-25 22:08:352386 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022387 // Due to GLES2 format limitations, either the color texture (for
2388 // non-multisampling) or the color render buffer (for multisampling) will be
2389 // attached to the offscreen frame buffer. The render buffer has more
2390 // limited formats available to it, but the texture can't do multisampling.
2391 if (IsOffscreenBufferMultisampled()) {
[email protected]ed9f9cd2013-02-27 21:12:352392 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(this));
[email protected]34ff8b0c2010-10-01 20:06:022393 offscreen_target_color_render_buffer_->Create();
2394 } else {
[email protected]ed9f9cd2013-02-27 21:12:352395 offscreen_target_color_texture_.reset(new BackTexture(this));
[email protected]34ff8b0c2010-10-01 20:06:022396 offscreen_target_color_texture_->Create();
2397 }
[email protected]ed9f9cd2013-02-27 21:12:352398 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(this));
[email protected]b9363b22010-06-09 22:06:152399 offscreen_target_depth_render_buffer_->Create();
[email protected]ed9f9cd2013-02-27 21:12:352400 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(this));
[email protected]b9363b22010-06-09 22:06:152401 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352402
2403 // Create the saved offscreen texture. The target frame buffer is copied
2404 // here when SwapBuffers is called.
[email protected]ed9f9cd2013-02-27 21:12:352405 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
[email protected]34ff8b0c2010-10-01 20:06:022406 offscreen_saved_frame_buffer_->Create();
2407 //
[email protected]ed9f9cd2013-02-27 21:12:352408 offscreen_saved_color_texture_.reset(new BackTexture(this));
[email protected]6217d392010-03-25 22:08:352409 offscreen_saved_color_texture_->Create();
2410
[email protected]6217d392010-03-25 22:08:352411 // Allocate the render buffers at their initial size and check the status
2412 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592413 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012414 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]63c9b052012-05-17 18:27:382415 Destroy(true);
[email protected]6217d392010-03-25 22:08:352416 return false;
2417 }
2418
[email protected]678a73f2012-12-19 19:22:092419 // Allocate the offscreen saved color texture.
2420 DCHECK(offscreen_saved_color_format_);
2421 offscreen_saved_color_texture_->AllocateStorage(
2422 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2423
2424 offscreen_saved_frame_buffer_->AttachRenderTexture(
2425 offscreen_saved_color_texture_.get());
2426 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2427 GL_FRAMEBUFFER_COMPLETE) {
2428 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2429 Destroy(true);
2430 return false;
2431 }
2432
[email protected]6217d392010-03-25 22:08:352433 // Bind to the new default frame buffer (the offscreen target frame buffer).
2434 // This should now be associated with ID zero.
2435 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]62e65f02013-05-29 22:28:102436 } else {
2437 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2438 // These are NOT if the back buffer has these proprorties. They are
2439 // if we want the command buffer to enforce them regardless of what
2440 // the real backbuffer is assuming the real back buffer gives us more than
2441 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2442 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2443 // can't do anything about that.
2444
2445 GLint v = 0;
2446 glGetIntegerv(GL_ALPHA_BITS, &v);
2447 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2448 // user requested RGB then RGB. If the user did not specify a preference
2449 // than use whatever we were given. Same for DEPTH and STENCIL.
2450 back_buffer_color_format_ =
2451 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2452 glGetIntegerv(GL_DEPTH_BITS, &v);
2453 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2454 glGetIntegerv(GL_STENCIL_BITS, &v);
2455 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
[email protected]6217d392010-03-25 22:08:352456 }
2457
[email protected]76a0ee102010-04-07 21:03:042458 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2459 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2460 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372461 // mailing list archives. It also implicitly enables the desktop GL
2462 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2463 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152464 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2465 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372466 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152467 }
[email protected]de17df392010-04-23 21:09:412468
[email protected]706b69f2012-07-27 04:59:302469 has_robustness_extension_ =
2470 context->HasExtension("GL_ARB_robustness") ||
2471 context->HasExtension("GL_EXT_robustness");
[email protected]38d139d2011-07-14 00:38:432472
[email protected]c2f8c8402010-12-06 18:07:242473 if (!InitializeShaderTranslator()) {
2474 return false;
[email protected]de17df392010-04-23 21:09:412475 }
[email protected]76a0ee102010-04-07 21:03:042476
[email protected]e259eb412012-10-13 05:47:242477 state_.viewport_width = size.width();
2478 state_.viewport_height = size.height();
[email protected]43410e92012-04-20 17:06:282479
[email protected]5904806b2012-05-08 18:10:222480 GLint viewport_params[4] = { 0 };
[email protected]43410e92012-04-20 17:06:282481 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
[email protected]1868a342012-11-07 15:56:022482 viewport_max_width_ = viewport_params[0];
2483 viewport_max_height_ = viewport_params[1];
[email protected]43410e92012-04-20 17:06:282484
[email protected]88a61bf2012-10-27 13:00:422485 state_.scissor_width = state_.viewport_width;
2486 state_.scissor_height = state_.viewport_height;
2487
[email protected]11f3e702012-06-19 19:00:012488 // Set all the default state because some GL drivers get it wrong.
[email protected]f731b9462012-10-30 00:35:222489 state_.InitCapabilities();
2490 state_.InitState();
[email protected]e259eb412012-10-13 05:47:242491 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]11f3e702012-06-19 19:00:012492
2493 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2494 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2495 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2496 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2497
[email protected]88cfd132013-07-11 00:59:002498 bool call_gl_clear = true;
2499#if defined(OS_ANDROID)
2500 // Temporary workaround for Android WebView because this clear ignores the
2501 // clip and corrupts that external UI of the App. Not calling glClear is ok
2502 // because the system already clears the buffer before each draw. Proper
2503 // fix might be setting the scissor clip properly before initialize. See
2504 // crbug.com/259023 for details.
2505 call_gl_clear = surface_->GetHandle();
2506#endif
2507 if (call_gl_clear) {
2508 // Clear the backbuffer.
2509 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2510 }
[email protected]561cc0a62013-05-07 18:34:452511
[email protected]62e155e2012-10-23 22:43:152512 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
[email protected]dd289a5d62012-06-30 22:05:462513 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2514 }
[email protected]dd289a5d62012-06-30 22:05:462515
[email protected]9b753992013-04-27 02:04:412516 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2517 context_->SetUnbindFboOnMakeCurrent();
[email protected]85cb4682013-04-20 00:54:242518 }
[email protected]85cb4682013-04-20 00:54:242519
[email protected]97419c02013-04-10 02:52:382520 // Only compositor contexts are known to use only the subset of GL
2521 // that can be safely migrated between the iGPU and the dGPU. Mark
2522 // those contexts as safe to forcibly transition between the GPUs.
2523 // http://crbug.com/180876, http://crbug.com/227228
2524 if (!offscreen)
2525 context_->SetSafeToForceGpuSwitch();
2526
[email protected]85a4ac22013-05-31 01:58:472527 async_pixel_transfer_manager_.reset(
[email protected]498b5c072013-06-04 19:30:072528 AsyncPixelTransferManager::Create(context.get()));
2529 async_pixel_transfer_manager_->Initialize(texture_manager());
[email protected]32145a92012-12-17 09:01:592530
[email protected]246a70452010-03-05 21:53:502531 return true;
[email protected]96449d2c2009-11-25 00:01:322532}
2533
[email protected]302ce6d2011-07-07 23:28:112534void GLES2DecoderImpl::UpdateCapabilities() {
2535 util_.set_num_compressed_texture_formats(
2536 validators_->compressed_texture_format.GetValues().size());
2537 util_.set_num_shader_binary_formats(
2538 validators_->shader_binary_format.GetValues().size());
2539}
2540
[email protected]c2f8c8402010-12-06 18:07:242541bool GLES2DecoderImpl::InitializeShaderTranslator() {
[email protected]a5d3dad2012-05-26 04:34:442542 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2543
[email protected]c2f8c8402010-12-06 18:07:242544 if (!use_shader_translator_) {
2545 return true;
2546 }
2547 ShBuiltInResources resources;
2548 ShInitBuiltInResources(&resources);
2549 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2550 resources.MaxVertexUniformVectors =
2551 group_->max_vertex_uniform_vectors();
2552 resources.MaxVaryingVectors = group_->max_varying_vectors();
2553 resources.MaxVertexTextureImageUnits =
2554 group_->max_vertex_texture_image_units();
2555 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2556 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2557 resources.MaxFragmentUniformVectors =
2558 group_->max_fragment_uniform_vectors();
[email protected]2f143d482013-03-14 18:04:492559 resources.MaxDrawBuffers = group_->max_draw_buffers();
[email protected]a0b78142013-05-23 00:47:242560 resources.MaxExpressionComplexity = 256;
2561 resources.MaxCallStackDepth = 256;
[email protected]f0d74742011-10-03 16:31:042562
[email protected]9e98f61b2013-03-05 02:21:142563#if (ANGLE_SH_VERSION >= 110)
[email protected]46c86752013-05-21 05:08:392564 GLint range[2] = { 0, 0 };
[email protected]8dc1bf92013-03-12 03:58:212565 GLint precision = 0;
2566 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2567 range, &precision);
[email protected]448e459e2013-06-12 17:00:412568 resources.FragmentPrecisionHigh =
2569 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
[email protected]9e98f61b2013-03-05 02:21:142570#endif
2571
[email protected]f0d74742011-10-03 16:31:042572 if (force_webgl_glsl_validation_) {
2573 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
[email protected]70dc60932013-06-04 03:33:492574 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
[email protected]aff39ac82013-06-08 04:53:132575 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
[email protected]f0d74742011-10-03 16:31:042576 } else {
2577 resources.OES_standard_derivatives =
[email protected]62e155e2012-10-23 22:43:152578 features().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462579 resources.ARB_texture_rectangle =
[email protected]62e155e2012-10-23 22:43:152580 features().arb_texture_rectangle ? 1 : 0;
[email protected]70e7bb12012-09-29 14:01:062581 resources.OES_EGL_image_external =
[email protected]62e155e2012-10-23 22:43:152582 features().oes_egl_image_external ? 1 : 0;
[email protected]2f143d482013-03-14 18:04:492583 resources.EXT_draw_buffers =
2584 features().ext_draw_buffers ? 1 : 0;
[email protected]70dc60932013-06-04 03:33:492585 resources.EXT_frag_depth =
2586 features().ext_frag_depth ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042587 }
2588
[email protected]26b61442013-03-17 16:12:012589 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2590 : SH_GLES2_SPEC;
[email protected]6aedcdc2013-01-24 01:25:052591 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
[email protected]3d944a82013-02-12 19:09:022592#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
[email protected]6aedcdc2013-01-24 01:25:052593 resources.HashFunction = &CityHashForAngle;
[email protected]3d944a82013-02-12 19:09:022594#else
2595 resources.HashFunction = &CityHash64;
2596#endif
[email protected]6aedcdc2013-01-24 01:25:052597 else
2598 resources.HashFunction = NULL;
[email protected]a2a0fe762011-09-20 00:59:122599 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2600 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2601 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2602 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
[email protected]62e155e2012-10-23 22:43:152603 workarounds().needs_glsl_built_in_function_emulation ?
[email protected]a2a0fe762011-09-20 00:59:122604 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2605 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]87fb6ab2012-06-13 22:28:042606
2607 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2608 vertex_translator_ = cache->GetTranslator(
2609 SH_VERTEX_SHADER, shader_spec, &resources,
2610 implementation_type, function_behavior);
2611 if (!vertex_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242612 LOG(ERROR) << "Could not initialize vertex shader translator.";
[email protected]63c9b052012-05-17 18:27:382613 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242614 return false;
2615 }
[email protected]87fb6ab2012-06-13 22:28:042616
2617 fragment_translator_ = cache->GetTranslator(
2618 SH_FRAGMENT_SHADER, shader_spec, &resources,
2619 implementation_type, function_behavior);
2620 if (!fragment_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242621 LOG(ERROR) << "Could not initialize fragment shader translator.";
[email protected]63c9b052012-05-17 18:27:382622 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242623 return false;
2624 }
2625 return true;
2626}
2627
[email protected]ae51d192010-04-27 00:48:032628bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472629 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352630 if (GetBuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032631 return false;
2632 }
2633 }
[email protected]40d90a22013-04-09 03:39:552634 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032635 glGenBuffersARB(n, service_ids.get());
2636 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352637 CreateBuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032638 }
2639 return true;
2640}
2641
2642bool GLES2DecoderImpl::GenFramebuffersHelper(
2643 GLsizei n, const GLuint* client_ids) {
2644 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352645 if (GetFramebuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032646 return false;
2647 }
2648 }
[email protected]40d90a22013-04-09 03:39:552649 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032650 glGenFramebuffersEXT(n, service_ids.get());
2651 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352652 CreateFramebuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032653 }
2654 return true;
2655}
2656
2657bool GLES2DecoderImpl::GenRenderbuffersHelper(
2658 GLsizei n, const GLuint* client_ids) {
2659 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352660 if (GetRenderbuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032661 return false;
2662 }
2663 }
[email protected]40d90a22013-04-09 03:39:552664 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032665 glGenRenderbuffersEXT(n, service_ids.get());
2666 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352667 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032668 }
2669 return true;
2670}
2671
2672bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2673 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352674 if (GetTexture(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032675 return false;
2676 }
2677 }
[email protected]40d90a22013-04-09 03:39:552678 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032679 glGenTextures(n, service_ids.get());
2680 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352681 CreateTexture(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032682 }
2683 return true;
2684}
2685
2686void GLES2DecoderImpl::DeleteBuffersHelper(
2687 GLsizei n, const GLuint* client_ids) {
2688 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]16ccec12013-02-28 03:40:212689 Buffer* buffer = GetBuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102690 if (buffer && !buffer->IsDeleted()) {
[email protected]e259eb412012-10-13 05:47:242691 state_.vertex_attrib_manager->Unbind(buffer);
[email protected]7cd76fd2013-06-02 21:11:112692 if (state_.bound_array_buffer.get() == buffer) {
[email protected]e259eb412012-10-13 05:47:242693 state_.bound_array_buffer = NULL;
[email protected]a0b78dc2011-11-11 10:43:102694 }
[email protected]ed9f9cd2013-02-27 21:12:352695 RemoveBuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032696 }
[email protected]a93bb842010-02-16 23:03:472697 }
[email protected]07f54fcc2009-12-22 02:46:302698}
2699
[email protected]ae51d192010-04-27 00:48:032700void GLES2DecoderImpl::DeleteFramebuffersHelper(
2701 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452702 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152703 features().chromium_framebuffer_multisample;
[email protected]b177ae22011-11-01 03:29:112704
[email protected]a25fa872010-03-25 02:57:582705 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352706 Framebuffer* framebuffer =
2707 GetFramebuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102708 if (framebuffer && !framebuffer->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:112709 if (framebuffer == state_.bound_draw_framebuffer.get()) {
[email protected]e259eb412012-10-13 05:47:242710 state_.bound_draw_framebuffer = NULL;
[email protected]88a61bf2012-10-27 13:00:422711 clear_state_dirty_ = true;
[email protected]ebfb73c2012-08-15 02:37:452712 GLenum target = supports_separate_framebuffer_binds ?
2713 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]b177ae22011-11-01 03:29:112714 glBindFramebufferEXT(target, GetBackbufferServiceId());
2715 }
[email protected]7cd76fd2013-06-02 21:11:112716 if (framebuffer == state_.bound_read_framebuffer.get()) {
[email protected]e259eb412012-10-13 05:47:242717 state_.bound_read_framebuffer = NULL;
[email protected]ebfb73c2012-08-15 02:37:452718 GLenum target = supports_separate_framebuffer_binds ?
2719 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]b177ae22011-11-01 03:29:112720 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462721 }
[email protected]70d34263c2013-01-09 00:27:452722 OnFboChanged();
[email protected]ed9f9cd2013-02-27 21:12:352723 RemoveFramebuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032724 }
[email protected]a25fa872010-03-25 02:57:582725 }
[email protected]07f54fcc2009-12-22 02:46:302726}
2727
[email protected]ae51d192010-04-27 00:48:032728void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2729 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452730 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152731 features().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582732 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352733 Renderbuffer* renderbuffer =
2734 GetRenderbuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102735 if (renderbuffer && !renderbuffer->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:112736 if (state_.bound_renderbuffer.get() == renderbuffer) {
[email protected]e259eb412012-10-13 05:47:242737 state_.bound_renderbuffer = NULL;
[email protected]a0b78dc2011-11-11 10:43:102738 }
2739 // Unbind from current framebuffers.
[email protected]ebfb73c2012-08-15 02:37:452740 if (supports_separate_framebuffer_binds) {
[email protected]7cd76fd2013-06-02 21:11:112741 if (state_.bound_read_framebuffer.get()) {
2742 state_.bound_read_framebuffer
2743 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102744 }
[email protected]7cd76fd2013-06-02 21:11:112745 if (state_.bound_draw_framebuffer.get()) {
2746 state_.bound_draw_framebuffer
2747 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102748 }
2749 } else {
[email protected]7cd76fd2013-06-02 21:11:112750 if (state_.bound_draw_framebuffer.get()) {
2751 state_.bound_draw_framebuffer
2752 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102753 }
2754 }
[email protected]88a61bf2012-10-27 13:00:422755 clear_state_dirty_ = true;
[email protected]ed9f9cd2013-02-27 21:12:352756 RemoveRenderbuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032757 }
[email protected]a25fa872010-03-25 02:57:582758 }
[email protected]07f54fcc2009-12-22 02:46:302759}
2760
[email protected]ae51d192010-04-27 00:48:032761void GLES2DecoderImpl::DeleteTexturesHelper(
2762 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452763 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152764 features().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472765 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]370eaf12013-05-18 09:19:492766 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2767 if (texture_ref) {
2768 Texture* texture = texture_ref->texture();
[email protected]a0b78dc2011-11-11 10:43:102769 if (texture->IsAttachedToFramebuffer()) {
[email protected]88a61bf2012-10-27 13:00:422770 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:462771 }
[email protected]370eaf12013-05-18 09:19:492772 // Unbind texture_ref from texture_ref units.
[email protected]1868a342012-11-07 15:56:022773 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
[email protected]370eaf12013-05-18 09:19:492774 state_.texture_units[jj].Unbind(texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102775 }
2776 // Unbind from current framebuffers.
[email protected]ebfb73c2012-08-15 02:37:452777 if (supports_separate_framebuffer_binds) {
[email protected]7cd76fd2013-06-02 21:11:112778 if (state_.bound_read_framebuffer.get()) {
2779 state_.bound_read_framebuffer
2780 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102781 }
[email protected]7cd76fd2013-06-02 21:11:112782 if (state_.bound_draw_framebuffer.get()) {
2783 state_.bound_draw_framebuffer
2784 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102785 }
2786 } else {
[email protected]7cd76fd2013-06-02 21:11:112787 if (state_.bound_draw_framebuffer.get()) {
2788 state_.bound_draw_framebuffer
2789 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102790 }
2791 }
[email protected]e51bdf32011-11-23 22:21:462792#if defined(OS_MACOSX)
[email protected]4f9958142013-07-02 03:58:072793 GLuint service_id = texture->service_id();
[email protected]e51bdf32011-11-23 22:21:462794 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2795 ReleaseIOSurfaceForTexture(service_id);
2796 }
2797#endif
[email protected]ed9f9cd2013-02-27 21:12:352798 RemoveTexture(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032799 }
[email protected]a93bb842010-02-16 23:03:472800 }
[email protected]07f54fcc2009-12-22 02:46:302801}
2802
[email protected]43f28f832010-02-03 02:28:482803// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322804
[email protected]eb54a562010-01-20 21:55:182805bool GLES2DecoderImpl::MakeCurrent() {
[email protected]63c9b052012-05-17 18:27:382806 if (!context_.get() || !context_->MakeCurrent(surface_.get()))
2807 return false;
2808
2809 if (WasContextLost()) {
[email protected]38d139d2011-07-14 00:38:432810 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
[email protected]e9f0ca82013-04-01 23:52:292811
2812 // Some D3D drivers cannot recover from device lost in the GPU process
2813 // sandbox. Allow a new GPU process to launch.
2814 if (workarounds().exit_on_context_lost) {
2815 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2816 << " a D3D device in the Chrome GPU process sandbox.";
2817 exit(0);
2818 }
2819
[email protected]63c9b052012-05-17 18:27:382820 return false;
[email protected]38d139d2011-07-14 00:38:432821 }
2822
[email protected]69a8701e2013-03-07 21:31:092823 ProcessFinishedAsyncTransfers();
2824 if (workarounds().flush_on_context_switch)
2825 glFlush();
2826
[email protected]9b753992013-04-27 02:04:412827 // Rebind the FBO if it was unbound by the context.
2828 if (workarounds().unbind_fbo_on_context_switch)
2829 RestoreFramebufferBindings();
2830
[email protected]370eaf12013-05-18 09:19:492831 clear_state_dirty_ = true;
2832
[email protected]69a8701e2013-03-07 21:31:092833 return true;
2834}
2835
2836void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
[email protected]fe8d73c2013-02-16 22:37:322837 if (engine() && query_manager_.get())
2838 query_manager_->ProcessPendingTransferQueries();
2839
[email protected]5b3a8e02013-03-13 05:36:442840 // TODO(epenner): Is there a better place to do this?
2841 // This needs to occur before we execute any batch of commands
2842 // from the client, as the client may have recieved an async
2843 // completion while issuing those commands.
2844 // "DidFlushStart" would be ideal if we had such a callback.
[email protected]b68b100752013-06-05 08:34:482845 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
[email protected]eb54a562010-01-20 21:55:182846}
2847
[email protected]a96a6022011-11-04 00:58:122848void GLES2DecoderImpl::ReleaseCurrent() {
2849 if (context_.get())
2850 context_->ReleaseCurrent(surface_.get());
2851}
2852
[email protected]8e3e0662010-08-23 18:46:302853void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]ed9f9cd2013-02-27 21:12:352854 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:202855 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302856 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202857 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302858}
2859
2860static void RebindCurrentFramebuffer(
2861 GLenum target,
[email protected]4d8f0dd2013-03-09 14:37:062862 Framebuffer* framebuffer,
[email protected]a3783712012-01-20 22:18:242863 GLuint back_buffer_service_id) {
[email protected]4d8f0dd2013-03-09 14:37:062864 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462865
[email protected]a3783712012-01-20 22:18:242866 if (framebuffer_id == 0) {
2867 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302868 }
[email protected]297ca1c2011-06-20 23:08:462869
[email protected]8e3e0662010-08-23 18:46:302870 glBindFramebufferEXT(target, framebuffer_id);
2871}
2872
2873void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]88a61bf2012-10-27 13:00:422874 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:462875
[email protected]62e155e2012-10-23 22:43:152876 if (!features().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302877 RebindCurrentFramebuffer(
2878 GL_FRAMEBUFFER,
[email protected]e259eb412012-10-13 05:47:242879 state_.bound_draw_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242880 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302881 } else {
2882 RebindCurrentFramebuffer(
2883 GL_READ_FRAMEBUFFER_EXT,
[email protected]e259eb412012-10-13 05:47:242884 state_.bound_read_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242885 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302886 RebindCurrentFramebuffer(
2887 GL_DRAW_FRAMEBUFFER_EXT,
[email protected]e259eb412012-10-13 05:47:242888 state_.bound_draw_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242889 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302890 }
[email protected]70d34263c2013-01-09 00:27:452891 OnFboChanged();
[email protected]8e3e0662010-08-23 18:46:302892}
2893
2894void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
[email protected]e259eb412012-10-13 05:47:242895 TextureUnit& info = state_.texture_units[0];
[email protected]8e3e0662010-08-23 18:46:302896 GLuint last_id;
[email protected]7cd76fd2013-06-02 21:11:112897 if (info.bound_texture_2d.get()) {
[email protected]8e3e0662010-08-23 18:46:302898 last_id = info.bound_texture_2d->service_id();
2899 } else {
2900 last_id = 0;
2901 }
2902
2903 glBindTexture(GL_TEXTURE_2D, last_id);
[email protected]e259eb412012-10-13 05:47:242904 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]8e3e0662010-08-23 18:46:302905}
2906
[email protected]0d6bfdc2011-11-02 01:32:202907bool GLES2DecoderImpl::CheckFramebufferValid(
[email protected]ed9f9cd2013-02-27 21:12:352908 Framebuffer* framebuffer,
[email protected]0d6bfdc2011-11-02 01:32:202909 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102910 if (!framebuffer) {
[email protected]60f22d32012-12-12 00:31:582911 if (backbuffer_needs_clear_bits_) {
2912 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2913 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2914 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2915 glClearStencil(0);
2916 glStencilMask(-1);
2917 glClearDepth(1.0f);
2918 glDepthMask(true);
2919 glDisable(GL_SCISSOR_TEST);
2920 glClear(backbuffer_needs_clear_bits_);
2921 backbuffer_needs_clear_bits_ = 0;
2922 RestoreClearState();
2923 }
[email protected]0d6bfdc2011-11-02 01:32:202924 return true;
2925 }
2926
[email protected]968351b2011-12-20 08:26:512927 if (framebuffer_manager()->IsComplete(framebuffer)) {
2928 return true;
2929 }
2930
[email protected]0d6bfdc2011-11-02 01:32:202931 GLenum completeness = framebuffer->IsPossiblyComplete();
2932 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512933 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432934 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
[email protected]3a03a8f2011-03-19 00:51:272935 return false;
2936 }
[email protected]0d6bfdc2011-11-02 01:32:202937
2938 // Are all the attachments cleared?
2939 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2940 texture_manager()->HaveUnclearedMips()) {
2941 if (!framebuffer->IsCleared()) {
2942 // Can we clear them?
[email protected]73276522012-11-09 05:50:202943 if (framebuffer->GetStatus(texture_manager(), target) !=
2944 GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512945 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432946 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2947 "framebuffer incomplete (clear)");
[email protected]0d6bfdc2011-11-02 01:32:202948 return false;
2949 }
2950 ClearUnclearedAttachments(target, framebuffer);
2951 }
2952 }
2953
[email protected]968351b2011-12-20 08:26:512954 if (!framebuffer_manager()->IsComplete(framebuffer)) {
[email protected]73276522012-11-09 05:50:202955 if (framebuffer->GetStatus(texture_manager(), target) !=
2956 GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512957 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432958 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2959 "framebuffer incomplete (check)");
[email protected]968351b2011-12-20 08:26:512960 return false;
2961 }
2962 framebuffer_manager()->MarkAsComplete(framebuffer);
2963 }
2964
[email protected]0d6bfdc2011-11-02 01:32:202965 // NOTE: At this point we don't know if the framebuffer is complete but
2966 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272967 return true;
2968}
2969
[email protected]0d6bfdc2011-11-02 01:32:202970bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
[email protected]62e155e2012-10-23 22:43:152971 if (!features().chromium_framebuffer_multisample) {
[email protected]28718a92013-04-04 12:12:512972 bool valid = CheckFramebufferValid(
[email protected]7cd76fd2013-06-02 21:11:112973 state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT, func_name);
[email protected]28718a92013-04-04 12:12:512974
2975 if (valid)
2976 OnUseFramebuffer();
2977
2978 return valid;
[email protected]0d6bfdc2011-11-02 01:32:202979 }
[email protected]7cd76fd2013-06-02 21:11:112980 return CheckFramebufferValid(state_.bound_draw_framebuffer.get(),
2981 GL_DRAW_FRAMEBUFFER_EXT,
2982 func_name) &&
2983 CheckFramebufferValid(state_.bound_read_framebuffer.get(),
2984 GL_READ_FRAMEBUFFER_EXT,
2985 func_name);
[email protected]0d6bfdc2011-11-02 01:32:202986}
2987
[email protected]8e3e0662010-08-23 18:46:302988gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]ed9f9cd2013-02-27 21:12:352989 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452990 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202991 if (framebuffer != NULL) {
[email protected]ed9f9cd2013-02-27 21:12:352992 const Framebuffer::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202993 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262994 if (attachment) {
2995 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502996 }
[email protected]9edc6b22010-12-23 02:00:262997 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022998 } else if (offscreen_target_frame_buffer_.get()) {
2999 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:353000 } else {
[email protected]f62a5ab2011-05-23 20:34:153001 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:023002 }
[email protected]246a70452010-03-05 21:53:503003}
3004
[email protected]9edc6b22010-12-23 02:00:263005GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]ed9f9cd2013-02-27 21:12:353006 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453007 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203008 if (framebuffer != NULL) {
3009 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:463010 } else if (offscreen_target_frame_buffer_.get()) {
3011 return offscreen_target_color_format_;
3012 } else {
3013 return back_buffer_color_format_;
3014 }
3015}
3016
3017GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]ed9f9cd2013-02-27 21:12:353018 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453019 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203020 if (framebuffer != NULL) {
3021 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:263022 } else if (offscreen_target_frame_buffer_.get()) {
3023 return offscreen_target_color_format_;
3024 } else {
[email protected]32fe9aa2011-01-21 23:47:133025 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:263026 }
3027}
3028
[email protected]9a5afa432011-07-22 18:16:393029void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]2ad674132013-06-05 07:48:513030 if (!offscreen_saved_color_texture_info_.get())
3031 return;
3032 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3033 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3034 texture_manager()->SetLevelInfo(
3035 offscreen_saved_color_texture_info_.get(),
3036 GL_TEXTURE_2D,
3037 0, // level
3038 GL_RGBA,
3039 offscreen_size_.width(),
3040 offscreen_size_.height(),
3041 1, // depth
3042 0, // border
3043 GL_RGBA,
3044 GL_UNSIGNED_BYTE,
3045 true);
3046 texture_manager()->SetParameter(
3047 "UpdateParentTextureInfo",
3048 GetErrorState(),
3049 offscreen_saved_color_texture_info_.get(),
3050 GL_TEXTURE_MAG_FILTER,
3051 GL_NEAREST);
3052 texture_manager()->SetParameter(
3053 "UpdateParentTextureInfo",
3054 GetErrorState(),
3055 offscreen_saved_color_texture_info_.get(),
3056 GL_TEXTURE_MIN_FILTER,
3057 GL_NEAREST);
3058 texture_manager()->SetParameter(
3059 "UpdateParentTextureInfo",
3060 GetErrorState(),
3061 offscreen_saved_color_texture_info_.get(),
3062 GL_TEXTURE_WRAP_S,
3063 GL_CLAMP_TO_EDGE);
3064 texture_manager()->SetParameter(
3065 "UpdateParentTextureInfo",
3066 GetErrorState(),
3067 offscreen_saved_color_texture_info_.get(),
3068 GL_TEXTURE_WRAP_T,
3069 GL_CLAMP_TO_EDGE);
3070 TextureRef* texture_ref = GetTextureInfoForTarget(target);
3071 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
[email protected]6217d392010-03-25 22:08:353072}
3073
[email protected]799b4b22011-08-22 17:09:593074void GLES2DecoderImpl::SetResizeCallback(
[email protected]729c0b42013-05-26 02:05:073075 const base::Callback<void(gfx::Size, float)>& callback) {
[email protected]9d37f062011-11-22 01:24:523076 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:003077}
3078
[email protected]1d82e822013-04-10 21:32:323079Logger* GLES2DecoderImpl::GetLogger() {
3080 return &logger_;
[email protected]6b6e7ee2011-12-13 08:04:523081}
3082
[email protected]d3eba342013-04-18 21:11:503083ErrorState* GLES2DecoderImpl::GetErrorState() {
3084 return state_.GetErrorState();
3085}
3086
[email protected]e3932abb2013-03-13 00:01:373087void GLES2DecoderImpl::SetShaderCacheCallback(
3088 const ShaderCacheCallback& callback) {
3089 shader_cache_callback_ = callback;
3090}
3091
[email protected]840a7e462013-02-27 01:29:513092void GLES2DecoderImpl::SetWaitSyncPointCallback(
3093 const WaitSyncPointCallback& callback) {
3094 wait_sync_point_callback_ = callback;
3095}
3096
[email protected]85a4ac22013-05-31 01:58:473097AsyncPixelTransferManager*
3098 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3099 return async_pixel_transfer_manager_.get();
3100}
3101
3102void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3103 async_pixel_transfer_manager_.reset();
[email protected]32145a92012-12-17 09:01:593104}
3105
[email protected]498b5c072013-06-04 19:30:073106void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3107 AsyncPixelTransferManager* manager) {
3108 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3109}
3110
[email protected]1318e922010-09-17 22:03:163111bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3112 uint32* service_texture_id) {
[email protected]370eaf12013-05-18 09:19:493113 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3114 if (texture_ref) {
3115 *service_texture_id = texture_ref->service_id();
[email protected]1318e922010-09-17 22:03:163116 return true;
3117 }
3118 return false;
3119}
3120
[email protected]63b465922012-09-06 02:04:523121uint32 GLES2DecoderImpl::GetTextureUploadCount() {
[email protected]b9804322013-01-08 17:54:123122 return texture_upload_count_ +
[email protected]b68b100752013-06-05 08:34:483123 async_pixel_transfer_manager_->GetTextureUploadCount();
[email protected]63b465922012-09-06 02:04:523124}
3125
3126base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
[email protected]b9804322013-01-08 17:54:123127 return total_texture_upload_time_ +
[email protected]b68b100752013-06-05 08:34:483128 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
[email protected]63b465922012-09-06 02:04:523129}
3130
3131base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3132 return total_processing_commands_time_;
3133}
3134
[email protected]dc25dda2012-09-27 21:36:303135void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3136 total_processing_commands_time_ += time;
3137}
3138
[email protected]63c9b052012-05-17 18:27:383139void GLES2DecoderImpl::Destroy(bool have_context) {
[email protected]55e136f2013-04-03 18:50:063140 if (!initialized())
3141 return;
3142
[email protected]63c9b052012-05-17 18:27:383143 DCHECK(!have_context || context_->IsCurrent(NULL));
[email protected]97872062010-11-03 19:07:053144
[email protected]80eb6b52012-01-19 00:14:413145 // Unbind everything.
[email protected]e259eb412012-10-13 05:47:243146 state_.vertex_attrib_manager = NULL;
[email protected]944b62f32012-09-27 02:20:463147 default_vertex_attrib_manager_ = NULL;
[email protected]1868a342012-11-07 15:56:023148 state_.texture_units.clear();
[email protected]e259eb412012-10-13 05:47:243149 state_.bound_array_buffer = NULL;
3150 state_.current_query = NULL;
3151 state_.current_program = NULL;
3152 state_.bound_read_framebuffer = NULL;
3153 state_.bound_draw_framebuffer = NULL;
3154 state_.bound_renderbuffer = NULL;
[email protected]80eb6b52012-01-19 00:14:413155
[email protected]cadac622013-06-11 16:46:363156 if (offscreen_saved_color_texture_info_.get()) {
[email protected]2ad674132013-06-05 07:48:513157 DCHECK(offscreen_target_color_texture_);
3158 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3159 offscreen_saved_color_texture_->id());
3160 offscreen_saved_color_texture_->Invalidate();
3161 offscreen_saved_color_texture_info_ = NULL;
3162 }
[email protected]eadc96792010-10-27 19:39:393163 if (have_context) {
[email protected]c322e882012-05-23 18:06:183164 if (copy_texture_CHROMIUM_.get()) {
3165 copy_texture_CHROMIUM_->Destroy();
3166 copy_texture_CHROMIUM_.reset();
3167 }
[email protected]43410e92012-04-20 17:06:283168
[email protected]7cd76fd2013-06-02 21:11:113169 if (state_.current_program.get()) {
3170 program_manager()->UnuseProgram(shader_manager(),
3171 state_.current_program.get());
[email protected]e259eb412012-10-13 05:47:243172 state_.current_program = NULL;
[email protected]ca488e12010-12-13 20:06:143173 }
3174
[email protected]b1122982010-05-17 23:04:243175 if (attrib_0_buffer_id_) {
3176 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3177 }
[email protected]8fbedc02010-11-18 18:43:403178 if (fixed_attrib_buffer_id_) {
3179 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3180 }
[email protected]b1122982010-05-17 23:04:243181
[email protected]97872062010-11-03 19:07:053182 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:543183 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053184 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:543185 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:053186 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:023187 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053188 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:153189 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053190 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:153191 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053192 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:023193 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053194 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:543195 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:273196 if (offscreen_resolved_frame_buffer_.get())
3197 offscreen_resolved_frame_buffer_->Destroy();
3198 if (offscreen_resolved_color_texture_.get())
3199 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:053200 } else {
3201 if (offscreen_target_frame_buffer_.get())
3202 offscreen_target_frame_buffer_->Invalidate();
3203 if (offscreen_target_color_texture_.get())
3204 offscreen_target_color_texture_->Invalidate();
3205 if (offscreen_target_color_render_buffer_.get())
3206 offscreen_target_color_render_buffer_->Invalidate();
3207 if (offscreen_target_depth_render_buffer_.get())
3208 offscreen_target_depth_render_buffer_->Invalidate();
3209 if (offscreen_target_stencil_render_buffer_.get())
3210 offscreen_target_stencil_render_buffer_->Invalidate();
3211 if (offscreen_saved_frame_buffer_.get())
3212 offscreen_saved_frame_buffer_->Invalidate();
3213 if (offscreen_saved_color_texture_.get())
3214 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:273215 if (offscreen_resolved_frame_buffer_.get())
3216 offscreen_resolved_frame_buffer_->Invalidate();
3217 if (offscreen_resolved_color_texture_.get())
3218 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:023219 }
[email protected]43410e92012-04-20 17:06:283220 copy_texture_CHROMIUM_.reset();
[email protected]97872062010-11-03 19:07:053221
[email protected]882ba1e22012-03-08 19:02:533222 if (query_manager_.get()) {
3223 query_manager_->Destroy(have_context);
3224 query_manager_.reset();
3225 }
3226
[email protected]944b62f32012-09-27 02:20:463227 if (vertex_array_manager_ .get()) {
3228 vertex_array_manager_->Destroy(have_context);
3229 vertex_array_manager_.reset();
3230 }
3231
[email protected]97872062010-11-03 19:07:053232 offscreen_target_frame_buffer_.reset();
3233 offscreen_target_color_texture_.reset();
3234 offscreen_target_color_render_buffer_.reset();
3235 offscreen_target_depth_render_buffer_.reset();
3236 offscreen_target_stencil_render_buffer_.reset();
3237 offscreen_saved_frame_buffer_.reset();
3238 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:273239 offscreen_resolved_frame_buffer_.reset();
3240 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:463241
[email protected]85a4ac22013-05-31 01:58:473242 // Should destroy the transfer manager before the texture manager held
3243 // by the context group.
3244 async_pixel_transfer_manager_.reset();
3245
[email protected]7cd76fd2013-06-02 21:11:113246 if (group_.get()) {
[email protected]2d9d3b92013-01-18 01:07:233247 group_->Destroy(this, have_context);
3248 group_ = NULL;
3249 }
3250
3251 if (context_.get()) {
3252 context_->ReleaseCurrent(NULL);
3253 context_ = NULL;
3254 }
3255
[email protected]e51bdf32011-11-23 22:21:463256#if defined(OS_MACOSX)
3257 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3258 it != texture_to_io_surface_map_.end(); ++it) {
3259 CFRelease(it->second);
3260 }
3261 texture_to_io_surface_map_.clear();
3262#endif
[email protected]96449d2c2009-11-25 00:01:323263}
3264
[email protected]63c9b052012-05-17 18:27:383265void GLES2DecoderImpl::SetSurface(
3266 const scoped_refptr<gfx::GLSurface>& surface) {
3267 DCHECK(context_->IsCurrent(NULL));
3268 DCHECK(surface_.get());
3269 surface_ = surface;
3270 RestoreCurrentFramebufferBindings();
3271}
3272
[email protected]2ad674132013-06-05 07:48:513273bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
[email protected]9a5afa432011-07-22 18:16:393274 if (!offscreen_saved_color_texture_.get())
3275 return false;
[email protected]2ad674132013-06-05 07:48:513276 if (!offscreen_saved_color_texture_info_.get()) {
[email protected]3c644d82011-06-20 19:58:243277 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]f46476932013-06-08 05:36:073278 offscreen_saved_color_texture_info_ = TextureRef::Create(
3279 texture_manager(), 0, service_id);
[email protected]2ad674132013-06-05 07:48:513280 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3281 GL_TEXTURE_2D);
[email protected]9a5afa432011-07-22 18:16:393282 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:243283 }
[email protected]2ad674132013-06-05 07:48:513284 gpu::gles2::MailboxName name;
3285 memcpy(name.key, mailbox.name, sizeof(mailbox.name));
3286 return mailbox_manager()->ProduceTexture(
3287 GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture());
[email protected]3c644d82011-06-20 19:58:243288}
3289
[email protected]260ddc4e2012-06-28 00:01:533290size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() {
[email protected]1078f912011-12-23 13:12:143291 size_t total = 0;
3292 if (offscreen_target_frame_buffer_.get()) {
3293 if (offscreen_target_color_texture_.get()) {
3294 total += offscreen_target_color_texture_->estimated_size();
3295 }
3296 if (offscreen_target_color_render_buffer_.get()) {
3297 total += offscreen_target_color_render_buffer_->estimated_size();
3298 }
3299 if (offscreen_target_depth_render_buffer_.get()) {
3300 total += offscreen_target_depth_render_buffer_->estimated_size();
3301 }
3302 if (offscreen_target_stencil_render_buffer_.get()) {
3303 total += offscreen_target_stencil_render_buffer_->estimated_size();
3304 }
3305 if (offscreen_saved_color_texture_.get()) {
3306 total += offscreen_saved_color_texture_->estimated_size();
3307 }
3308 if (offscreen_resolved_color_texture_.get()) {
3309 total += offscreen_resolved_color_texture_->estimated_size();
3310 }
3311 } else {
3312 gfx::Size size = surface_->GetSize();
3313 total += size.width() * size.height() *
3314 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
3315 }
[email protected]260ddc4e2012-06-28 00:01:533316 return total;
[email protected]1078f912011-12-23 13:12:143317}
3318
[email protected]799b4b22011-08-22 17:09:593319bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3320 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3321 if (!is_offscreen) {
3322 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3323 << " with an onscreen framebuffer.";
3324 return false;
3325 }
3326
3327 if (offscreen_size_ == size)
3328 return true;
3329
3330 offscreen_size_ = size;
3331 int w = offscreen_size_.width();
3332 int h = offscreen_size_.height();
3333 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3334 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3335 << "to allocate storage due to excessive dimensions.";
3336 return false;
3337 }
3338
3339 // Reallocate the offscreen target buffers.
3340 DCHECK(offscreen_target_color_format_);
3341 if (IsOffscreenBufferMultisampled()) {
3342 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3343 offscreen_size_, offscreen_target_color_format_,
3344 offscreen_target_samples_)) {
3345 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3346 << "to allocate storage for offscreen target color buffer.";
3347 return false;
3348 }
3349 } else {
3350 if (!offscreen_target_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:093351 offscreen_size_, offscreen_target_color_format_, false)) {
[email protected]799b4b22011-08-22 17:09:593352 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3353 << "to allocate storage for offscreen target color texture.";
3354 return false;
3355 }
3356 }
3357 if (offscreen_target_depth_format_ &&
3358 !offscreen_target_depth_render_buffer_->AllocateStorage(
3359 offscreen_size_, offscreen_target_depth_format_,
3360 offscreen_target_samples_)) {
3361 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3362 << "to allocate storage for offscreen target depth buffer.";
3363 return false;
3364 }
3365 if (offscreen_target_stencil_format_ &&
3366 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3367 offscreen_size_, offscreen_target_stencil_format_,
3368 offscreen_target_samples_)) {
3369 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3370 << "to allocate storage for offscreen target stencil buffer.";
3371 return false;
3372 }
3373
3374 // Attach the offscreen target buffers to the target frame buffer.
3375 if (IsOffscreenBufferMultisampled()) {
3376 offscreen_target_frame_buffer_->AttachRenderBuffer(
3377 GL_COLOR_ATTACHMENT0,
3378 offscreen_target_color_render_buffer_.get());
3379 } else {
3380 offscreen_target_frame_buffer_->AttachRenderTexture(
3381 offscreen_target_color_texture_.get());
3382 }
3383 if (offscreen_target_depth_format_) {
3384 offscreen_target_frame_buffer_->AttachRenderBuffer(
3385 GL_DEPTH_ATTACHMENT,
3386 offscreen_target_depth_render_buffer_.get());
3387 }
3388 const bool packed_depth_stencil =
3389 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3390 if (packed_depth_stencil) {
3391 offscreen_target_frame_buffer_->AttachRenderBuffer(
3392 GL_STENCIL_ATTACHMENT,
3393 offscreen_target_depth_render_buffer_.get());
3394 } else if (offscreen_target_stencil_format_) {
3395 offscreen_target_frame_buffer_->AttachRenderBuffer(
3396 GL_STENCIL_ATTACHMENT,
3397 offscreen_target_stencil_render_buffer_.get());
3398 }
3399
3400 if (offscreen_target_frame_buffer_->CheckStatus() !=
3401 GL_FRAMEBUFFER_COMPLETE) {
3402 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3403 << "because offscreen FBO was incomplete.";
3404 return false;
3405 }
3406
3407 // Clear the target frame buffer.
3408 {
3409 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3410 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3411 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3412 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3413 glClearStencil(0);
3414 glStencilMaskSeparate(GL_FRONT, -1);
3415 glStencilMaskSeparate(GL_BACK, -1);
3416 glClearDepth(0);
3417 glDepthMask(GL_TRUE);
3418 glDisable(GL_SCISSOR_TEST);
3419 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3420 RestoreClearState();
3421 }
[email protected]d85ef76d2011-09-08 22:21:433422
3423 // Destroy the offscreen resolved framebuffers.
3424 if (offscreen_resolved_frame_buffer_.get())
3425 offscreen_resolved_frame_buffer_->Destroy();
3426 if (offscreen_resolved_color_texture_.get())
3427 offscreen_resolved_color_texture_->Destroy();
3428 offscreen_resolved_color_texture_.reset();
3429 offscreen_resolved_frame_buffer_.reset();
3430
[email protected]799b4b22011-08-22 17:09:593431 return true;
[email protected]6217d392010-03-25 22:08:353432}
3433
[email protected]799b4b22011-08-22 17:09:593434error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:353435 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
[email protected]09e17272012-11-30 10:30:443436 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
[email protected]452120872012-09-27 15:21:023437 return error::kDeferCommandUntilLater;
3438
[email protected]799b4b22011-08-22 17:09:593439 GLuint width = static_cast<GLuint>(c.width);
3440 GLuint height = static_cast<GLuint>(c.height);
[email protected]729c0b42013-05-26 02:05:073441 GLfloat scale_factor = c.scale_factor;
[email protected]799b4b22011-08-22 17:09:593442 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]d16aa4b2013-02-14 22:35:413443
3444 width = std::max(1U, width);
3445 height = std::max(1U, height);
3446
[email protected]a0d989162011-11-22 13:15:073447#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3448 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003449 // Make sure that we are done drawing to the back buffer before resizing.
3450 glFinish();
3451#endif
[email protected]799b4b22011-08-22 17:09:593452 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3453 if (is_offscreen) {
[email protected]7794d512012-04-17 20:36:493454 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3455 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3456 << "ResizeOffscreenFrameBuffer failed.";
[email protected]799b4b22011-08-22 17:09:593457 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493458 }
[email protected]7ff86b92010-11-25 17:50:003459 }
[email protected]799b4b22011-08-22 17:09:593460
[email protected]9d37f062011-11-22 01:24:523461 if (!resize_callback_.is_null()) {
[email protected]729c0b42013-05-26 02:05:073462 resize_callback_.Run(gfx::Size(width, height), scale_factor);
[email protected]0e9346b2013-03-16 16:35:443463 DCHECK(context_->IsCurrent(surface_.get()));
[email protected]7794d512012-04-17 20:36:493464 if (!context_->IsCurrent(surface_.get())) {
3465 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3466 << "current after resize callback.";
[email protected]658f7562011-09-09 05:24:053467 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493468 }
[email protected]658f7562011-09-09 05:24:053469 }
[email protected]799b4b22011-08-22 17:09:593470
3471 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393472}
3473
[email protected]96449d2c2009-11-25 00:01:323474const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3475 if (command_id > kStartPoint && command_id < kNumCommands) {
3476 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3477 }
3478 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3479}
3480
3481// Decode command with its arguments, and call the corresponding GL function.
3482// Note: args is a pointer to the command buffer. As such, it could be changed
3483// by a (malicious) client at any time, so if validation has to happen, it
3484// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143485error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323486 unsigned int command,
3487 unsigned int arg_count,
3488 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143489 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263490 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003491 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3492 // LOG(INFO), tried VLOG(1), no luck.
[email protected]1d82e822013-04-10 21:32:323493 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
[email protected]d2a0e1a2012-08-12 02:25:013494 << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193495 }
[email protected]96449d2c2009-11-25 00:01:323496 unsigned int command_index = command - kStartPoint - 1;
3497 if (command_index < arraysize(g_command_info)) {
3498 const CommandInfo& info = g_command_info[command_index];
3499 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3500 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3501 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193502 uint32 immediate_data_size =
3503 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323504 switch (command) {
3505 #define GLES2_CMD_OP(name) \
[email protected]ed9f9cd2013-02-27 21:12:353506 case cmds::name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193507 result = Handle ## name( \
3508 immediate_data_size, \
[email protected]ed9f9cd2013-02-27 21:12:353509 *static_cast<const gles2::cmds::name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193510 break; \
[email protected]96449d2c2009-11-25 00:01:323511
3512 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323513 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383514 }
3515 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303516 GLenum error;
3517 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]1d82e822013-04-10 21:32:323518 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
[email protected]39ba4f02012-03-26 01:16:003519 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3520 << GetCommandName(command);
[email protected]ab09b612013-03-11 22:11:513521 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193522 }
[email protected]96449d2c2009-11-25 00:01:323523 }
3524 } else {
[email protected]f7a64ee2010-02-01 22:24:143525 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323526 }
[email protected]b9849abf2009-11-25 19:13:193527 } else {
3528 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323529 }
[email protected]a3a93e7b2010-08-28 00:48:563530 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3531 result = current_decoder_error_;
3532 current_decoder_error_ = error::kNoError;
3533 }
[email protected]b9849abf2009-11-25 19:13:193534 return result;
[email protected]96449d2c2009-11-25 00:01:323535}
3536
[email protected]ed9f9cd2013-02-27 21:12:353537void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3538 buffer_manager()->RemoveBuffer(client_id);
[email protected]3916c97e2010-02-25 03:20:503539}
3540
[email protected]ae51d192010-04-27 00:48:033541bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:353542 if (GetProgram(client_id)) {
[email protected]ae51d192010-04-27 00:48:033543 return false;
3544 }
[email protected]96449d2c2009-11-25 00:01:323545 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033546 if (service_id != 0) {
[email protected]ed9f9cd2013-02-27 21:12:353547 CreateProgram(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323548 }
[email protected]ae51d192010-04-27 00:48:033549 return true;
[email protected]96449d2c2009-11-25 00:01:323550}
3551
[email protected]ae51d192010-04-27 00:48:033552bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:353553 if (GetShader(client_id)) {
[email protected]ae51d192010-04-27 00:48:033554 return false;
[email protected]96449d2c2009-11-25 00:01:323555 }
[email protected]ae51d192010-04-27 00:48:033556 GLuint service_id = glCreateShader(type);
3557 if (service_id != 0) {
[email protected]ed9f9cd2013-02-27 21:12:353558 CreateShader(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033559 }
3560 return true;
[email protected]96449d2c2009-11-25 00:01:323561}
3562
[email protected]882ba1e22012-03-08 19:02:533563void GLES2DecoderImpl::DoFinish() {
3564 glFinish();
[email protected]22e3f552012-03-13 01:54:193565 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533566}
3567
3568void GLES2DecoderImpl::DoFlush() {
3569 glFlush();
[email protected]22e3f552012-03-13 01:54:193570 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533571}
3572
[email protected]3916c97e2010-02-25 03:20:503573void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453574 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]1868a342012-11-07 15:56:023575 if (texture_index >= state_.texture_units.size()) {
[email protected]ab09b612013-03-11 22:11:513576 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:533577 "glActiveTexture", texture_unit, "texture_unit");
[email protected]3916c97e2010-02-25 03:20:503578 return;
3579 }
[email protected]e259eb412012-10-13 05:47:243580 state_.active_texture_unit = texture_index;
[email protected]36cef8ce2010-03-16 07:34:453581 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503582}
3583
[email protected]051b1372010-04-12 02:42:083584void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]b10492f2013-03-08 05:24:073585 Buffer* buffer = NULL;
[email protected]051b1372010-04-12 02:42:083586 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033587 if (client_id != 0) {
[email protected]b10492f2013-03-08 05:24:073588 buffer = GetBuffer(client_id);
3589 if (!buffer) {
[email protected]bf5a8d132011-08-16 08:39:353590 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153591 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3592 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353593 return;
3594 }
3595
[email protected]b10492f2013-03-08 05:24:073596 // It's a new id so make a buffer buffer for it.
[email protected]ae51d192010-04-27 00:48:033597 glGenBuffersARB(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353598 CreateBuffer(client_id, service_id);
[email protected]b10492f2013-03-08 05:24:073599 buffer = GetBuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573600 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103601 group_->GetIdAllocator(id_namespaces::kBuffers);
3602 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033603 }
[email protected]051b1372010-04-12 02:42:083604 }
[email protected]b10492f2013-03-08 05:24:073605 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3606 if (buffer) {
3607 if (!buffer_manager()->SetTarget(buffer, target)) {
[email protected]ab09b612013-03-11 22:11:513608 LOCAL_SET_GL_ERROR(
3609 GL_INVALID_OPERATION,
3610 "glBindBuffer", "buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473611 return;
3612 }
[email protected]b10492f2013-03-08 05:24:073613 service_id = buffer->service_id();
[email protected]a93bb842010-02-16 23:03:473614 }
[email protected]96449d2c2009-11-25 00:01:323615 switch (target) {
3616 case GL_ARRAY_BUFFER:
[email protected]b10492f2013-03-08 05:24:073617 state_.bound_array_buffer = buffer;
[email protected]96449d2c2009-11-25 00:01:323618 break;
3619 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]b10492f2013-03-08 05:24:073620 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
[email protected]96449d2c2009-11-25 00:01:323621 break;
3622 default:
[email protected]a93bb842010-02-16 23:03:473623 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323624 break;
3625 }
[email protected]051b1372010-04-12 02:42:083626 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323627}
3628
[email protected]f3b191b2013-06-19 03:43:543629bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3630 bool all_draw_buffers) {
3631 Framebuffer* framebuffer =
3632 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3633 if (!all_draw_buffers || !framebuffer) {
3634 return (GLES2Util::GetChannelsForFormat(
3635 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3636 }
3637 return framebuffer->HasAlphaMRT();
[email protected]297ca1c2011-06-20 23:08:463638}
3639
3640bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]ed9f9cd2013-02-27 21:12:353641 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453642 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203643 if (framebuffer) {
3644 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463645 }
3646 if (offscreen_target_frame_buffer_.get()) {
3647 return offscreen_target_depth_format_ != 0;
3648 }
3649 return back_buffer_has_depth_;
3650}
3651
3652bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]ed9f9cd2013-02-27 21:12:353653 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453654 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203655 if (framebuffer) {
3656 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463657 }
3658 if (offscreen_target_frame_buffer_.get()) {
3659 return offscreen_target_stencil_format_ != 0 ||
3660 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3661 }
3662 return back_buffer_has_stencil_;
3663}
3664
3665void GLES2DecoderImpl::ApplyDirtyState() {
[email protected]88a61bf2012-10-27 13:00:423666 if (clear_state_dirty_) {
[email protected]297ca1c2011-06-20 23:08:463667 glColorMask(
[email protected]e259eb412012-10-13 05:47:243668 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3669 state_.color_mask_alpha &&
[email protected]f3b191b2013-06-19 03:43:543670 BoundFramebufferHasColorAttachmentWithAlpha(true));
[email protected]297ca1c2011-06-20 23:08:463671 bool have_depth = BoundFramebufferHasDepthAttachment();
[email protected]e259eb412012-10-13 05:47:243672 glDepthMask(state_.depth_mask && have_depth);
[email protected]f731b9462012-10-30 00:35:223673 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
[email protected]297ca1c2011-06-20 23:08:463674 bool have_stencil = BoundFramebufferHasStencilAttachment();
[email protected]e259eb412012-10-13 05:47:243675 glStencilMaskSeparate(
[email protected]88a61bf2012-10-27 13:00:423676 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
[email protected]e259eb412012-10-13 05:47:243677 glStencilMaskSeparate(
[email protected]88a61bf2012-10-27 13:00:423678 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
[email protected]f731b9462012-10-30 00:35:223679 EnableDisable(
3680 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3681 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3682 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3683 EnableDisable(GL_BLEND, state_.enable_flags.blend);
[email protected]88a61bf2012-10-27 13:00:423684 clear_state_dirty_ = false;
[email protected]297ca1c2011-06-20 23:08:463685 }
3686}
3687
[email protected]1868a342012-11-07 15:56:023688GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
[email protected]7cd76fd2013-06-02 21:11:113689 return (offscreen_target_frame_buffer_.get())
3690 ? offscreen_target_frame_buffer_->id()
3691 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
[email protected]1868a342012-11-07 15:56:023692}
3693
3694void GLES2DecoderImpl::RestoreState() const {
[email protected]962bfbe72013-05-24 11:16:143695 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3696 "context", logger_.GetLogPrefix());
[email protected]29a4d902013-02-26 20:18:063697 // Restore the Framebuffer first because of bugs in Intel drivers.
3698 // Intel drivers incorrectly clip the viewport settings to
3699 // the size of the current framebuffer object.
3700 RestoreFramebufferBindings();
3701 state_.RestoreState();
3702}
3703
3704void GLES2DecoderImpl::RestoreFramebufferBindings() const {
[email protected]7cd76fd2013-06-02 21:11:113705 GLuint service_id = state_.bound_draw_framebuffer.get()
3706 ? state_.bound_draw_framebuffer->service_id()
3707 : GetBackbufferServiceId();
[email protected]29a4d902013-02-26 20:18:063708 if (!features().chromium_framebuffer_multisample) {
3709 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3710 } else {
3711 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
[email protected]7cd76fd2013-06-02 21:11:113712 service_id = state_.bound_read_framebuffer.get()
3713 ? state_.bound_read_framebuffer->service_id()
3714 : GetBackbufferServiceId();
[email protected]29a4d902013-02-26 20:18:063715 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3716 }
[email protected]70d34263c2013-01-09 00:27:453717 OnFboChanged();
[email protected]29a4d902013-02-26 20:18:063718}
3719
3720void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
[email protected]62e65f02013-05-29 22:28:103721 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3722 if (texture) {
[email protected]9bc9a2e82013-04-03 03:56:253723 GLenum target = texture->target();
3724 glBindTexture(target, service_id);
[email protected]29a4d902013-02-26 20:18:063725 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253726 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
[email protected]29a4d902013-02-26 20:18:063727 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253728 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
[email protected]29a4d902013-02-26 20:18:063729 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253730 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
[email protected]29a4d902013-02-26 20:18:063731 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253732 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
[email protected]29a4d902013-02-26 20:18:063733 RestoreTextureUnitBindings(state_.active_texture_unit);
3734 }
[email protected]70d34263c2013-01-09 00:27:453735}
3736
3737void GLES2DecoderImpl::OnFboChanged() const {
3738 if (workarounds().restore_scissor_on_fbo_change)
[email protected]28718a92013-04-04 12:12:513739 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3740}
3741
3742// Called after the FBO is checked for completeness.
3743void GLES2DecoderImpl::OnUseFramebuffer() const {
3744 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3745 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
[email protected]81fc9d02013-03-14 23:53:323746 // The driver forgets the correct scissor when modifying the FBO binding.
[email protected]28718a92013-04-04 12:12:513747 glScissor(state_.scissor_x,
3748 state_.scissor_y,
3749 state_.scissor_width,
3750 state_.scissor_height);
3751
3752 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3753 // it's unclear how this bug works.
3754 glFlush();
3755 }
[email protected]b177ae22011-11-01 03:29:113756}
3757
[email protected]051b1372010-04-12 02:42:083758void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
[email protected]4d8f0dd2013-03-09 14:37:063759 Framebuffer* framebuffer = NULL;
[email protected]051b1372010-04-12 02:42:083760 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033761 if (client_id != 0) {
[email protected]4d8f0dd2013-03-09 14:37:063762 framebuffer = GetFramebuffer(client_id);
3763 if (!framebuffer) {
[email protected]bf5a8d132011-08-16 08:39:353764 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153765 LOG(ERROR)
3766 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3767 current_decoder_error_ = error::kGenericError;
3768 return;
[email protected]bf5a8d132011-08-16 08:39:353769 }
3770
[email protected]4d8f0dd2013-03-09 14:37:063771 // It's a new id so make a framebuffer framebuffer for it.
[email protected]ae51d192010-04-27 00:48:033772 glGenFramebuffersEXT(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353773 CreateFramebuffer(client_id, service_id);
[email protected]4d8f0dd2013-03-09 14:37:063774 framebuffer = GetFramebuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573775 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103776 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3777 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033778 } else {
[email protected]4d8f0dd2013-03-09 14:37:063779 service_id = framebuffer->service_id();
[email protected]051b1372010-04-12 02:42:083780 }
[email protected]4d8f0dd2013-03-09 14:37:063781 framebuffer->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083782 }
[email protected]4d8f0dd2013-03-09 14:37:063783 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
[email protected]8e3e0662010-08-23 18:46:303784
3785 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
[email protected]4d8f0dd2013-03-09 14:37:063786 state_.bound_draw_framebuffer = framebuffer;
[email protected]8e3e0662010-08-23 18:46:303787 }
3788 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]4d8f0dd2013-03-09 14:37:063789 state_.bound_read_framebuffer = framebuffer;
[email protected]8e3e0662010-08-23 18:46:303790 }
[email protected]6217d392010-03-25 22:08:353791
[email protected]88a61bf2012-10-27 13:00:423792 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:463793
[email protected]b177ae22011-11-01 03:29:113794 // If we are rendering to the backbuffer get the FBO id for any simulated
3795 // backbuffer.
[email protected]4d8f0dd2013-03-09 14:37:063796 if (framebuffer == NULL) {
[email protected]b177ae22011-11-01 03:29:113797 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463798 }
[email protected]6217d392010-03-25 22:08:353799
[email protected]051b1372010-04-12 02:42:083800 glBindFramebufferEXT(target, service_id);
[email protected]70d34263c2013-01-09 00:27:453801 OnFboChanged();
[email protected]86093972010-03-11 00:13:563802}
3803
[email protected]051b1372010-04-12 02:42:083804void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
[email protected]ee2a79c32013-03-10 03:50:273805 Renderbuffer* renderbuffer = NULL;
[email protected]051b1372010-04-12 02:42:083806 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033807 if (client_id != 0) {
[email protected]ee2a79c32013-03-10 03:50:273808 renderbuffer = GetRenderbuffer(client_id);
3809 if (!renderbuffer) {
[email protected]bf5a8d132011-08-16 08:39:353810 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153811 LOG(ERROR)
3812 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3813 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353814 return;
3815 }
3816
[email protected]ee2a79c32013-03-10 03:50:273817 // It's a new id so make a renderbuffer renderbuffer for it.
[email protected]ae51d192010-04-27 00:48:033818 glGenRenderbuffersEXT(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353819 CreateRenderbuffer(client_id, service_id);
[email protected]ee2a79c32013-03-10 03:50:273820 renderbuffer = GetRenderbuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573821 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103822 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3823 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033824 } else {
[email protected]ee2a79c32013-03-10 03:50:273825 service_id = renderbuffer->service_id();
[email protected]051b1372010-04-12 02:42:083826 }
[email protected]ee2a79c32013-03-10 03:50:273827 renderbuffer->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083828 }
[email protected]ee2a79c32013-03-10 03:50:273829 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer");
3830 state_.bound_renderbuffer = renderbuffer;
[email protected]051b1372010-04-12 02:42:083831 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563832}
3833
[email protected]051b1372010-04-12 02:42:083834void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]370eaf12013-05-18 09:19:493835 TextureRef* texture_ref = NULL;
[email protected]051b1372010-04-12 02:42:083836 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033837 if (client_id != 0) {
[email protected]370eaf12013-05-18 09:19:493838 texture_ref = GetTexture(client_id);
3839 if (!texture_ref) {
[email protected]bf5a8d132011-08-16 08:39:353840 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153841 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3842 current_decoder_error_ = error::kGenericError;
3843 return;
[email protected]bf5a8d132011-08-16 08:39:353844 }
3845
[email protected]02965c22013-03-09 02:40:073846 // It's a new id so make a texture texture for it.
[email protected]ae51d192010-04-27 00:48:033847 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413848 DCHECK_NE(0u, service_id);
[email protected]ed9f9cd2013-02-27 21:12:353849 CreateTexture(client_id, service_id);
[email protected]370eaf12013-05-18 09:19:493850 texture_ref = GetTexture(client_id);
[email protected]3b1ecc262011-08-03 22:49:573851 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103852 group_->GetIdAllocator(id_namespaces::kTextures);
3853 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033854 }
3855 } else {
[email protected]370eaf12013-05-18 09:19:493856 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083857 }
[email protected]370eaf12013-05-18 09:19:493858 Texture* texture = texture_ref->texture();
[email protected]ae51d192010-04-27 00:48:033859
[email protected]1958e0e2010-04-22 05:17:153860 // Check the texture exists
3861 // Check that we are not trying to bind it to a different target.
[email protected]02965c22013-03-09 02:40:073862 if (texture->target() != 0 && texture->target() != target) {
[email protected]ab09b612013-03-11 22:11:513863 LOCAL_SET_GL_ERROR(
3864 GL_INVALID_OPERATION,
3865 "glBindTexture", "texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153866 return;
3867 }
[email protected]02965c22013-03-09 02:40:073868 if (texture->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
[email protected]ab09b612013-03-11 22:11:513869 LOCAL_SET_GL_ERROR(
3870 GL_INVALID_OPERATION,
3871 "glBindTexture", "illegal target for stream texture.");
[email protected]b0af4f52011-09-28 22:04:423872 return;
3873 }
[email protected]02965c22013-03-09 02:40:073874 LogClientServiceForInfo(texture, client_id, "glBindTexture");
3875 if (texture->target() == 0) {
[email protected]370eaf12013-05-18 09:19:493876 texture_manager()->SetTarget(texture_ref, target);
[email protected]a93bb842010-02-16 23:03:473877 }
[email protected]02965c22013-03-09 02:40:073878 glBindTexture(target, texture->service_id());
[email protected]32145a92012-12-17 09:01:593879
[email protected]e259eb412012-10-13 05:47:243880 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]3916c97e2010-02-25 03:20:503881 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473882 switch (target) {
3883 case GL_TEXTURE_2D:
[email protected]370eaf12013-05-18 09:19:493884 unit.bound_texture_2d = texture_ref;
[email protected]a93bb842010-02-16 23:03:473885 break;
3886 case GL_TEXTURE_CUBE_MAP:
[email protected]370eaf12013-05-18 09:19:493887 unit.bound_texture_cube_map = texture_ref;
[email protected]a93bb842010-02-16 23:03:473888 break;
[email protected]61eeb33f2011-07-26 15:30:313889 case GL_TEXTURE_EXTERNAL_OES:
[email protected]370eaf12013-05-18 09:19:493890 unit.bound_texture_external_oes = texture_ref;
[email protected]02965c22013-03-09 02:40:073891 if (texture->IsStreamTexture()) {
[email protected]4f9958142013-07-02 03:58:073892 DCHECK(stream_texture_manager());
[email protected]b0af4f52011-09-28 22:04:423893 StreamTexture* stream_tex =
[email protected]4f9958142013-07-02 03:58:073894 stream_texture_manager()->LookupStreamTexture(
3895 texture->service_id());
[email protected]b0af4f52011-09-28 22:04:423896 if (stream_tex)
3897 stream_tex->Update();
3898 }
[email protected]61eeb33f2011-07-26 15:30:313899 break;
[email protected]e51bdf32011-11-23 22:21:463900 case GL_TEXTURE_RECTANGLE_ARB:
[email protected]370eaf12013-05-18 09:19:493901 unit.bound_texture_rectangle_arb = texture_ref;
[email protected]e51bdf32011-11-23 22:21:463902 break;
[email protected]a93bb842010-02-16 23:03:473903 default:
3904 NOTREACHED(); // Validation should prevent us getting here.
3905 break;
3906 }
3907}
3908
[email protected]07f54fcc2009-12-22 02:46:303909void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]e259eb412012-10-13 05:47:243910 if (state_.vertex_attrib_manager->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123911 if (index != 0 ||
3912 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243913 glDisableVertexAttribArray(index);
3914 }
[email protected]07f54fcc2009-12-22 02:46:303915 } else {
[email protected]ab09b612013-03-11 22:11:513916 LOCAL_SET_GL_ERROR(
3917 GL_INVALID_VALUE,
3918 "glDisableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303919 }
3920}
3921
[email protected]60f22d32012-12-12 00:31:583922void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
3923 GLsizei numAttachments,
3924 const GLenum* attachments) {
[email protected]ed9f9cd2013-02-27 21:12:353925 Framebuffer* framebuffer =
[email protected]60f22d32012-12-12 00:31:583926 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
3927
3928 // Validates the attachments. If one of them fails
3929 // the whole command fails.
3930 for (GLsizei i = 0; i < numAttachments; ++i) {
3931 if ((framebuffer &&
3932 !validators_->attachment.IsValid(attachments[i])) ||
3933 (!framebuffer &&
3934 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
[email protected]ab09b612013-03-11 22:11:513935 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3936 "glDiscardFramebufferEXT", attachments[i], "attachments");
[email protected]60f22d32012-12-12 00:31:583937 return;
3938 }
3939 }
3940
3941 // Marks each one of them as not cleared
3942 for (GLsizei i = 0; i < numAttachments; ++i) {
3943 if (framebuffer) {
3944 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
3945 texture_manager(),
3946 attachments[i],
3947 false);
3948 } else {
3949 switch (attachments[i]) {
3950 case GL_COLOR_EXT:
3951 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
3952 break;
3953 case GL_DEPTH_EXT:
3954 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
3955 case GL_STENCIL_EXT:
3956 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
3957 break;
3958 default:
3959 NOTREACHED();
3960 break;
3961 }
3962 }
3963 }
3964
3965 glDiscardFramebufferEXT(target, numAttachments, attachments);
3966}
3967
[email protected]07f54fcc2009-12-22 02:46:303968void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]e259eb412012-10-13 05:47:243969 if (state_.vertex_attrib_manager->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303970 glEnableVertexAttribArray(index);
3971 } else {
[email protected]ab09b612013-03-11 22:11:513972 LOCAL_SET_GL_ERROR(
3973 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303974 }
3975}
3976
[email protected]a93bb842010-02-16 23:03:473977void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]370eaf12013-05-18 09:19:493978 TextureRef* texture_ref = GetTextureInfoForTarget(target);
3979 if (!texture_ref ||
3980 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:513981 LOCAL_SET_GL_ERROR(
3982 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
[email protected]a93bb842010-02-16 23:03:473983 return;
3984 }
[email protected]38c0a972012-05-12 00:48:023985
[email protected]12d95352012-12-14 07:23:543986 if (target == GL_TEXTURE_CUBE_MAP) {
3987 for (int i = 0; i < 6; ++i) {
3988 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
[email protected]370eaf12013-05-18 09:19:493989 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
[email protected]ab09b612013-03-11 22:11:513990 LOCAL_SET_GL_ERROR(
3991 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
[email protected]12d95352012-12-14 07:23:543992 return;
3993 }
3994 }
3995 } else {
[email protected]370eaf12013-05-18 09:19:493996 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
[email protected]ab09b612013-03-11 22:11:513997 LOCAL_SET_GL_ERROR(
3998 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
[email protected]12d95352012-12-14 07:23:543999 return;
4000 }
[email protected]7687479c2012-05-14 23:54:044001 }
4002
[email protected]ab09b612013-03-11 22:11:514003 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
[email protected]59f3ca02011-03-26 22:24:194004 // Workaround for Mac driver bug. In the large scheme of things setting
4005 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:564006 // hit so there's probably no need to make this conditional. The bug appears
4007 // to be that if the filtering mode is set to something that doesn't require
4008 // mipmaps for rendering, or is never set to something other than the default,
4009 // then glGenerateMipmap misbehaves.
[email protected]62e155e2012-10-23 22:43:154010 if (workarounds().set_texture_filter_before_generating_mipmap) {
[email protected]c892a4e12012-05-08 18:20:194011 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4012 }
[email protected]a93bb842010-02-16 23:03:474013 glGenerateMipmapEXT(target);
[email protected]62e155e2012-10-23 22:43:154014 if (workarounds().set_texture_filter_before_generating_mipmap) {
[email protected]370eaf12013-05-18 09:19:494015 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4016 texture_ref->texture()->min_filter());
[email protected]c892a4e12012-05-08 18:20:194017 }
[email protected]ab09b612013-03-11 22:11:514018 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
[email protected]38c0a972012-05-12 00:48:024019 if (error == GL_NO_ERROR) {
[email protected]370eaf12013-05-18 09:19:494020 texture_manager()->MarkMipmapsGenerated(texture_ref);
[email protected]38c0a972012-05-12 00:48:024021 }
[email protected]a93bb842010-02-16 23:03:474022}
4023
[email protected]b273e432010-04-12 17:23:584024bool GLES2DecoderImpl::GetHelper(
4025 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:584026 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:154027 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4028 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:434029 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4030 *num_written = 1;
4031 if (params) {
4032 *params = GL_RGBA; // We don't support other formats.
4033 }
4034 return true;
4035 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4036 *num_written = 1;
4037 if (params) {
4038 *params = GL_UNSIGNED_BYTE; // We don't support other types.
4039 }
4040 return true;
4041 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4042 *num_written = 1;
4043 if (params) {
4044 *params = group_->max_fragment_uniform_vectors();
4045 }
4046 return true;
4047 case GL_MAX_VARYING_VECTORS:
4048 *num_written = 1;
4049 if (params) {
4050 *params = group_->max_varying_vectors();
4051 }
4052 return true;
4053 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4054 *num_written = 1;
4055 if (params) {
4056 *params = group_->max_vertex_uniform_vectors();
4057 }
4058 return true;
[email protected]4e8a5b122010-05-08 22:00:104059 }
[email protected]5cb735d2011-10-13 01:37:234060 }
4061 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:244062 case GL_MAX_VIEWPORT_DIMS:
4063 if (offscreen_target_frame_buffer_.get()) {
4064 *num_written = 2;
4065 if (params) {
4066 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4067 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4068 }
4069 return true;
4070 }
[email protected]5cb735d2011-10-13 01:37:234071 return false;
[email protected]84afefa2011-10-19 21:45:534072 case GL_MAX_SAMPLES:
4073 *num_written = 1;
4074 if (params) {
4075 params[0] = renderbuffer_manager()->max_samples();
4076 }
4077 return true;
4078 case GL_MAX_RENDERBUFFER_SIZE:
4079 *num_written = 1;
4080 if (params) {
4081 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4082 }
4083 return true;
[email protected]5cb735d2011-10-13 01:37:234084 case GL_MAX_TEXTURE_SIZE:
4085 *num_written = 1;
4086 if (params) {
4087 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4088 }
4089 return true;
4090 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4091 *num_written = 1;
4092 if (params) {
4093 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4094 }
4095 return true;
[email protected]2f143d482013-03-14 18:04:494096 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4097 *num_written = 1;
4098 if (params) {
4099 params[0] = group_->max_color_attachments();
4100 }
4101 return true;
4102 case GL_MAX_DRAW_BUFFERS_ARB:
4103 *num_written = 1;
4104 if (params) {
4105 params[0] = group_->max_draw_buffers();
4106 }
4107 return true;
[email protected]297ca1c2011-06-20 23:08:464108 case GL_ALPHA_BITS:
4109 *num_written = 1;
4110 if (params) {
4111 GLint v = 0;
4112 glGetIntegerv(GL_ALPHA_BITS, &v);
[email protected]f3b191b2013-06-19 03:43:544113 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
[email protected]297ca1c2011-06-20 23:08:464114 }
4115 return true;
4116 case GL_DEPTH_BITS:
4117 *num_written = 1;
4118 if (params) {
4119 GLint v = 0;
4120 glGetIntegerv(GL_DEPTH_BITS, &v);
4121 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4122 }
4123 return true;
4124 case GL_STENCIL_BITS:
4125 *num_written = 1;
4126 if (params) {
4127 GLint v = 0;
4128 glGetIntegerv(GL_STENCIL_BITS, &v);
4129 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4130 }
4131 return true;
[email protected]656dcaad2010-05-07 17:18:374132 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:114133 *num_written = validators_->compressed_texture_format.GetValues().size();
4134 if (params) {
4135 for (GLint ii = 0; ii < *num_written; ++ii) {
4136 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4137 }
4138 }
[email protected]656dcaad2010-05-07 17:18:374139 return true;
[email protected]b273e432010-04-12 17:23:584140 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4141 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104142 if (params) {
[email protected]302ce6d2011-07-07 23:28:114143 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:104144 }
[email protected]b273e432010-04-12 17:23:584145 return true;
4146 case GL_NUM_SHADER_BINARY_FORMATS:
4147 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104148 if (params) {
[email protected]302ce6d2011-07-07 23:28:114149 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:104150 }
[email protected]b273e432010-04-12 17:23:584151 return true;
4152 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:114153 *num_written = validators_->shader_binary_format.GetValues().size();
4154 if (params) {
4155 for (GLint ii = 0; ii < *num_written; ++ii) {
4156 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4157 }
4158 }
4159 return true;
[email protected]b273e432010-04-12 17:23:584160 case GL_SHADER_COMPILER:
4161 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104162 if (params) {
4163 *params = GL_TRUE;
4164 }
[email protected]b273e432010-04-12 17:23:584165 return true;
[email protected]6b8cf1a2010-05-06 16:13:584166 case GL_ARRAY_BUFFER_BINDING:
4167 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104168 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114169 if (state_.bound_array_buffer.get()) {
[email protected]4e8a5b122010-05-08 22:00:104170 GLuint client_id = 0;
[email protected]e259eb412012-10-13 05:47:244171 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
[email protected]4e8a5b122010-05-08 22:00:104172 &client_id);
4173 *params = client_id;
4174 } else {
4175 *params = 0;
4176 }
[email protected]6b8cf1a2010-05-06 16:13:584177 }
4178 return true;
4179 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4180 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104181 if (params) {
[email protected]e259eb412012-10-13 05:47:244182 if (state_.vertex_attrib_manager->element_array_buffer()) {
[email protected]4e8a5b122010-05-08 22:00:104183 GLuint client_id = 0;
4184 buffer_manager()->GetClientId(
[email protected]b04e24c2013-01-08 18:35:254185 state_.vertex_attrib_manager->element_array_buffer()->
4186 service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104187 *params = client_id;
4188 } else {
4189 *params = 0;
4190 }
[email protected]6b8cf1a2010-05-06 16:13:584191 }
4192 return true;
4193 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:304194 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:584195 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104196 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354197 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:454198 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
[email protected]0d6bfdc2011-11-02 01:32:204199 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:104200 GLuint client_id = 0;
4201 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:204202 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:304203 *params = client_id;
4204 } else {
4205 *params = 0;
4206 }
4207 }
4208 return true;
[email protected]ebfb73c2012-08-15 02:37:454209 case GL_READ_FRAMEBUFFER_BINDING_EXT:
[email protected]8e3e0662010-08-23 18:46:304210 *num_written = 1;
4211 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354212 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:454213 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:204214 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:304215 GLuint client_id = 0;
4216 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:204217 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104218 *params = client_id;
4219 } else {
4220 *params = 0;
4221 }
[email protected]6b8cf1a2010-05-06 16:13:584222 }
4223 return true;
4224 case GL_RENDERBUFFER_BINDING:
4225 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104226 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354227 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:204228 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4229 if (renderbuffer) {
[email protected]62e65f02013-05-29 22:28:104230 *params = renderbuffer->client_id();
[email protected]4e8a5b122010-05-08 22:00:104231 } else {
4232 *params = 0;
4233 }
[email protected]6b8cf1a2010-05-06 16:13:584234 }
4235 return true;
4236 case GL_CURRENT_PROGRAM:
4237 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104238 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114239 if (state_.current_program.get()) {
[email protected]4e8a5b122010-05-08 22:00:104240 GLuint client_id = 0;
4241 program_manager()->GetClientId(
[email protected]e259eb412012-10-13 05:47:244242 state_.current_program->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104243 *params = client_id;
4244 } else {
4245 *params = 0;
4246 }
[email protected]6b8cf1a2010-05-06 16:13:584247 }
4248 return true;
[email protected]bf835842012-11-19 15:21:514249 case GL_VERTEX_ARRAY_BINDING_OES:
4250 *num_written = 1;
4251 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114252 if (state_.vertex_attrib_manager.get() !=
4253 default_vertex_attrib_manager_.get()) {
[email protected]bf835842012-11-19 15:21:514254 GLuint client_id = 0;
4255 vertex_array_manager_->GetClientId(
4256 state_.vertex_attrib_manager->service_id(), &client_id);
4257 *params = client_id;
4258 } else {
4259 *params = 0;
4260 }
4261 }
4262 return true;
[email protected]4e8a5b122010-05-08 22:00:104263 case GL_TEXTURE_BINDING_2D:
4264 *num_written = 1;
4265 if (params) {
[email protected]e259eb412012-10-13 05:47:244266 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114267 if (unit.bound_texture_2d.get()) {
[email protected]62e65f02013-05-29 22:28:104268 *params = unit.bound_texture_2d->client_id();
[email protected]6b8cf1a2010-05-06 16:13:584269 } else {
4270 *params = 0;
4271 }
[email protected]6b8cf1a2010-05-06 16:13:584272 }
[email protected]4e8a5b122010-05-08 22:00:104273 return true;
4274 case GL_TEXTURE_BINDING_CUBE_MAP:
4275 *num_written = 1;
4276 if (params) {
[email protected]e259eb412012-10-13 05:47:244277 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114278 if (unit.bound_texture_cube_map.get()) {
[email protected]62e65f02013-05-29 22:28:104279 *params = unit.bound_texture_cube_map->client_id();
[email protected]6b8cf1a2010-05-06 16:13:584280 } else {
4281 *params = 0;
4282 }
[email protected]6b8cf1a2010-05-06 16:13:584283 }
[email protected]4e8a5b122010-05-08 22:00:104284 return true;
[email protected]61eeb33f2011-07-26 15:30:314285 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4286 *num_written = 1;
4287 if (params) {
[email protected]e259eb412012-10-13 05:47:244288 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114289 if (unit.bound_texture_external_oes.get()) {
[email protected]62e65f02013-05-29 22:28:104290 *params = unit.bound_texture_external_oes->client_id();
[email protected]61eeb33f2011-07-26 15:30:314291 } else {
4292 *params = 0;
4293 }
4294 }
4295 return true;
[email protected]e51bdf32011-11-23 22:21:464296 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4297 *num_written = 1;
4298 if (params) {
[email protected]e259eb412012-10-13 05:47:244299 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114300 if (unit.bound_texture_rectangle_arb.get()) {
[email protected]62e65f02013-05-29 22:28:104301 *params = unit.bound_texture_rectangle_arb->client_id();
[email protected]e51bdf32011-11-23 22:21:464302 } else {
4303 *params = 0;
4304 }
4305 }
4306 return true;
[email protected]6c75c712012-06-19 15:43:174307 case GL_UNPACK_FLIP_Y_CHROMIUM:
4308 *num_written = 1;
4309 if (params) {
4310 params[0] = unpack_flip_y_;
4311 }
4312 return true;
4313 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4314 *num_written = 1;
4315 if (params) {
4316 params[0] = unpack_premultiply_alpha_;
4317 }
4318 return true;
4319 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4320 *num_written = 1;
4321 if (params) {
4322 params[0] = unpack_unpremultiply_alpha_;
4323 }
4324 return true;
[email protected]b273e432010-04-12 17:23:584325 default:
[email protected]2f143d482013-03-14 18:04:494326 if (pname >= GL_DRAW_BUFFER0_ARB &&
4327 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4328 *num_written = 1;
4329 if (params) {
4330 Framebuffer* framebuffer =
4331 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4332 if (framebuffer) {
4333 params[0] = framebuffer->GetDrawBuffer(pname);
4334 } else { // backbuffer
4335 if (pname == GL_DRAW_BUFFER0_ARB)
4336 params[0] = group_->draw_buffer();
4337 else
4338 params[0] = GL_NONE;
4339 }
4340 }
4341 return true;
4342 }
[email protected]4e8a5b122010-05-08 22:00:104343 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:534344 return false;
[email protected]b273e432010-04-12 17:23:584345 }
4346}
4347
[email protected]4e8a5b122010-05-08 22:00:104348bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4349 GLenum pname, GLsizei* num_values) {
[email protected]d058bca2012-11-26 10:27:264350 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
[email protected]f63b1232012-10-31 07:03:534351 return true;
4352 }
[email protected]4e8a5b122010-05-08 22:00:104353 return GetHelper(pname, NULL, num_values);
4354}
4355
[email protected]7d3c36e2013-07-12 14:13:164356GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4357 if (GL_MAX_SAMPLES == pname &&
4358 features().use_img_for_multisampled_render_to_texture) {
4359 return GL_MAX_SAMPLES_IMG;
4360 }
4361 return pname;
4362}
4363
[email protected]b273e432010-04-12 17:23:584364void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4365 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:104366 GLsizei num_written = 0;
[email protected]f63b1232012-10-31 07:03:534367 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
[email protected]40d90a22013-04-09 03:39:554368 scoped_ptr<GLint[]> values(new GLint[num_written]);
[email protected]d058bca2012-11-26 10:27:264369 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
[email protected]f63b1232012-10-31 07:03:534370 GetHelper(pname, values.get(), &num_written);
4371 }
[email protected]b273e432010-04-12 17:23:584372 for (GLsizei ii = 0; ii < num_written; ++ii) {
4373 params[ii] = static_cast<GLboolean>(values[ii]);
4374 }
4375 } else {
[email protected]7d3c36e2013-07-12 14:13:164376 pname = AdjustGetPname(pname);
[email protected]b273e432010-04-12 17:23:584377 glGetBooleanv(pname, params);
4378 }
4379}
4380
4381void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4382 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:104383 GLsizei num_written = 0;
[email protected]d058bca2012-11-26 10:27:264384 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
[email protected]f63b1232012-10-31 07:03:534385 if (GetHelper(pname, NULL, &num_written)) {
[email protected]40d90a22013-04-09 03:39:554386 scoped_ptr<GLint[]> values(new GLint[num_written]);
[email protected]f63b1232012-10-31 07:03:534387 GetHelper(pname, values.get(), &num_written);
4388 for (GLsizei ii = 0; ii < num_written; ++ii) {
4389 params[ii] = static_cast<GLfloat>(values[ii]);
4390 }
4391 } else {
[email protected]7d3c36e2013-07-12 14:13:164392 pname = AdjustGetPname(pname);
[email protected]f63b1232012-10-31 07:03:534393 glGetFloatv(pname, params);
[email protected]b273e432010-04-12 17:23:584394 }
[email protected]b273e432010-04-12 17:23:584395 }
4396}
4397
4398void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4399 DCHECK(params);
4400 GLsizei num_written;
[email protected]d058bca2012-11-26 10:27:264401 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
[email protected]f63b1232012-10-31 07:03:534402 !GetHelper(pname, params, &num_written)) {
[email protected]7d3c36e2013-07-12 14:13:164403 pname = AdjustGetPname(pname);
[email protected]b273e432010-04-12 17:23:584404 glGetIntegerv(pname, params);
4405 }
4406}
4407
[email protected]a0c3e972010-04-21 00:49:134408void GLES2DecoderImpl::DoGetProgramiv(
4409 GLuint program_id, GLenum pname, GLint* params) {
[email protected]df37b9932013-03-08 05:21:424410 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4411 if (!program) {
[email protected]a0c3e972010-04-21 00:49:134412 return;
4413 }
[email protected]df37b9932013-03-08 05:21:424414 program->GetProgramiv(pname, params);
[email protected]a0c3e972010-04-21 00:49:134415}
4416
[email protected]17cfbe0e2013-03-07 01:26:084417void GLES2DecoderImpl::DoGetBufferParameteriv(
4418 GLenum target, GLenum pname, GLint* params) {
4419 Buffer* buffer = GetBufferInfoForTarget(target);
4420 if (!buffer) {
[email protected]ab09b612013-03-11 22:11:514421 LOCAL_SET_GL_ERROR(
[email protected]17cfbe0e2013-03-07 01:26:084422 GL_INVALID_OPERATION, "glGetBufferParameteriv",
4423 "no buffer bound for target");
4424 return;
4425 }
4426 switch (pname) {
4427 case GL_BUFFER_SIZE:
4428 *params = buffer->size();
4429 break;
4430 case GL_BUFFER_USAGE:
4431 *params = buffer->usage();
4432 break;
4433 default:
4434 NOTREACHED();
4435 }
4436}
4437
[email protected]258a3313f2011-10-18 20:13:574438void GLES2DecoderImpl::DoBindAttribLocation(
[email protected]df37b9932013-03-08 05:21:424439 GLuint program_id, GLuint index, const char* name) {
[email protected]258a3313f2011-10-18 20:13:574440 if (!StringIsValidForGLES(name)) {
[email protected]ab09b612013-03-11 22:11:514441 LOCAL_SET_GL_ERROR(
4442 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:574443 return;
4444 }
[email protected]68dcb1f2012-04-07 00:14:564445 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ab09b612013-03-11 22:11:514446 LOCAL_SET_GL_ERROR(
4447 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
[email protected]68dcb1f2012-04-07 00:14:564448 return;
4449 }
4450 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:514451 LOCAL_SET_GL_ERROR(
4452 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
[email protected]68dcb1f2012-04-07 00:14:564453 return;
4454 }
[email protected]df37b9932013-03-08 05:21:424455 Program* program = GetProgramInfoNotShader(
4456 program_id, "glBindAttribLocation");
4457 if (!program) {
[email protected]258a3313f2011-10-18 20:13:574458 return;
[email protected]558847a2010-03-24 07:02:544459 }
[email protected]df37b9932013-03-08 05:21:424460 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4461 glBindAttribLocation(program->service_id(), index, name);
[email protected]258a3313f2011-10-18 20:13:574462}
4463
4464error::Error GLES2DecoderImpl::HandleBindAttribLocation(
[email protected]ed9f9cd2013-02-27 21:12:354465 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
[email protected]258a3313f2011-10-18 20:13:574466 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544467 GLuint index = static_cast<GLuint>(c.index);
4468 uint32 name_size = c.data_size;
4469 const char* name = GetSharedMemoryAs<const char*>(
4470 c.name_shm_id, c.name_shm_offset, name_size);
4471 if (name == NULL) {
4472 return error::kOutOfBounds;
4473 }
4474 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:574475 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544476 return error::kNoError;
4477}
4478
4479error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
[email protected]ed9f9cd2013-02-27 21:12:354480 uint32 immediate_data_size, const cmds::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:584481 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544482 GLuint index = static_cast<GLuint>(c.index);
4483 uint32 name_size = c.data_size;
4484 const char* name = GetImmediateDataAs<const char*>(
4485 c, name_size, immediate_data_size);
4486 if (name == NULL) {
4487 return error::kOutOfBounds;
4488 }
4489 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:574490 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544491 return error::kNoError;
4492}
4493
4494error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:354495 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:584496 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544497 GLuint index = static_cast<GLuint>(c.index);
4498 Bucket* bucket = GetBucket(c.name_bucket_id);
4499 if (!bucket || bucket->size() == 0) {
4500 return error::kInvalidArguments;
4501 }
4502 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184503 if (!bucket->GetAsString(&name_str)) {
4504 return error::kInvalidArguments;
4505 }
[email protected]258a3313f2011-10-18 20:13:574506 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544507 return error::kNoError;
4508}
4509
[email protected]2be6abf32012-06-26 00:28:334510void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
[email protected]df37b9932013-03-08 05:21:424511 GLuint program_id, GLint location, const char* name) {
[email protected]2be6abf32012-06-26 00:28:334512 if (!StringIsValidForGLES(name)) {
[email protected]ab09b612013-03-11 22:11:514513 LOCAL_SET_GL_ERROR(
4514 GL_INVALID_VALUE,
4515 "glBindUniformLocationCHROMIUM", "Invalid character");
[email protected]2be6abf32012-06-26 00:28:334516 return;
4517 }
4518 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ab09b612013-03-11 22:11:514519 LOCAL_SET_GL_ERROR(
4520 GL_INVALID_OPERATION,
4521 "glBindUniformLocationCHROMIUM", "reserved prefix");
[email protected]2be6abf32012-06-26 00:28:334522 return;
4523 }
4524 if (location < 0 || static_cast<uint32>(location) >=
4525 (group_->max_fragment_uniform_vectors() +
4526 group_->max_vertex_uniform_vectors()) * 4) {
[email protected]ab09b612013-03-11 22:11:514527 LOCAL_SET_GL_ERROR(
4528 GL_INVALID_VALUE,
4529 "glBindUniformLocationCHROMIUM", "location out of range");
[email protected]2be6abf32012-06-26 00:28:334530 return;
4531 }
[email protected]df37b9932013-03-08 05:21:424532 Program* program = GetProgramInfoNotShader(
4533 program_id, "glBindUniformLocationCHROMIUM");
4534 if (!program) {
[email protected]2be6abf32012-06-26 00:28:334535 return;
4536 }
[email protected]df37b9932013-03-08 05:21:424537 if (!program->SetUniformLocationBinding(name, location)) {
[email protected]ab09b612013-03-11 22:11:514538 LOCAL_SET_GL_ERROR(
4539 GL_INVALID_VALUE,
4540 "glBindUniformLocationCHROMIUM", "location out of range");
[email protected]2be6abf32012-06-26 00:28:334541 }
4542}
4543
4544error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354545 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
[email protected]2be6abf32012-06-26 00:28:334546 GLuint program = static_cast<GLuint>(c.program);
4547 GLint location = static_cast<GLint>(c.location);
4548 uint32 name_size = c.data_size;
4549 const char* name = GetSharedMemoryAs<const char*>(
4550 c.name_shm_id, c.name_shm_offset, name_size);
4551 if (name == NULL) {
4552 return error::kOutOfBounds;
4553 }
4554 String name_str(name, name_size);
4555 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4556 return error::kNoError;
4557}
4558
4559error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMImmediate(
4560 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:354561 const cmds::BindUniformLocationCHROMIUMImmediate& c) {
[email protected]2be6abf32012-06-26 00:28:334562 GLuint program = static_cast<GLuint>(c.program);
4563 GLint location = static_cast<GLint>(c.location);
4564 uint32 name_size = c.data_size;
4565 const char* name = GetImmediateDataAs<const char*>(
4566 c, name_size, immediate_data_size);
4567 if (name == NULL) {
4568 return error::kOutOfBounds;
4569 }
4570 String name_str(name, name_size);
4571 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4572 return error::kNoError;
4573}
4574
4575error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4576 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:354577 const cmds::BindUniformLocationCHROMIUMBucket& c) {
[email protected]2be6abf32012-06-26 00:28:334578 GLuint program = static_cast<GLuint>(c.program);
4579 GLint location = static_cast<GLint>(c.location);
4580 Bucket* bucket = GetBucket(c.name_bucket_id);
4581 if (!bucket || bucket->size() == 0) {
4582 return error::kInvalidArguments;
4583 }
4584 std::string name_str;
4585 if (!bucket->GetAsString(&name_str)) {
4586 return error::kInvalidArguments;
4587 }
4588 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4589 return error::kNoError;
4590}
4591
[email protected]f7a64ee2010-02-01 22:24:144592error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ed9f9cd2013-02-27 21:12:354593 uint32 immediate_data_size, const cmds::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:034594 GLuint client_id = c.shader;
4595 if (client_id) {
[email protected]df37b9932013-03-08 05:21:424596 Shader* shader = GetShader(client_id);
4597 if (shader) {
4598 if (!shader->IsDeleted()) {
4599 glDeleteShader(shader->service_id());
4600 shader_manager()->MarkAsDeleted(shader);
[email protected]ca488e12010-12-13 20:06:144601 }
[email protected]ae51d192010-04-27 00:48:034602 } else {
[email protected]ab09b612013-03-11 22:11:514603 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
[email protected]ae51d192010-04-27 00:48:034604 }
[email protected]96449d2c2009-11-25 00:01:324605 }
[email protected]f7a64ee2010-02-01 22:24:144606 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324607}
4608
[email protected]f7a64ee2010-02-01 22:24:144609error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ed9f9cd2013-02-27 21:12:354610 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:034611 GLuint client_id = c.program;
4612 if (client_id) {
[email protected]df37b9932013-03-08 05:21:424613 Program* program = GetProgram(client_id);
4614 if (program) {
4615 if (!program->IsDeleted()) {
4616 program_manager()->MarkAsDeleted(shader_manager(), program);
[email protected]ca488e12010-12-13 20:06:144617 }
[email protected]ae51d192010-04-27 00:48:034618 } else {
[email protected]ab09b612013-03-11 22:11:514619 LOCAL_SET_GL_ERROR(
4620 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
[email protected]ae51d192010-04-27 00:48:034621 }
[email protected]96449d2c2009-11-25 00:01:324622 }
[email protected]f7a64ee2010-02-01 22:24:144623 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324624}
4625
[email protected]269200b12010-11-18 22:53:064626void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104627 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574628 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104629 for (GLsizei ii = 0; ii < n; ++ii) {
4630 id_allocator->FreeID(ids[ii]);
4631 }
4632}
4633
[email protected]269200b12010-11-18 22:53:064634error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354635 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104636 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4637 GLsizei n = static_cast<GLsizei>(c.n);
4638 uint32 data_size;
4639 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4640 return error::kOutOfBounds;
4641 }
4642 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4643 c.ids_shm_id, c.ids_shm_offset, data_size);
4644 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514645 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104646 return error::kNoError;
4647 }
4648 if (ids == NULL) {
4649 return error::kOutOfBounds;
4650 }
[email protected]269200b12010-11-18 22:53:064651 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104652 return error::kNoError;
4653}
4654
[email protected]269200b12010-11-18 22:53:064655void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104656 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574657 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104658 if (id_offset == 0) {
4659 for (GLsizei ii = 0; ii < n; ++ii) {
4660 ids[ii] = id_allocator->AllocateID();
4661 }
4662 } else {
4663 for (GLsizei ii = 0; ii < n; ++ii) {
4664 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4665 id_offset = ids[ii] + 1;
4666 }
4667 }
4668}
4669
[email protected]269200b12010-11-18 22:53:064670error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354671 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104672 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4673 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4674 GLsizei n = static_cast<GLsizei>(c.n);
4675 uint32 data_size;
4676 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4677 return error::kOutOfBounds;
4678 }
4679 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4680 c.ids_shm_id, c.ids_shm_offset, data_size);
4681 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514682 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104683 return error::kNoError;
4684 }
4685 if (ids == NULL) {
4686 return error::kOutOfBounds;
4687 }
[email protected]269200b12010-11-18 22:53:064688 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:104689 return error::kNoError;
4690}
4691
[email protected]269200b12010-11-18 22:53:064692void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104693 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574694 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104695 for (GLsizei ii = 0; ii < n; ++ii) {
4696 if (!id_allocator->MarkAsUsed(ids[ii])) {
4697 for (GLsizei jj = 0; jj < ii; ++jj) {
4698 id_allocator->FreeID(ids[jj]);
4699 }
[email protected]ab09b612013-03-11 22:11:514700 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:434701 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4702 "attempt to register id that already exists");
[email protected]066849e32010-05-03 19:14:104703 return;
4704 }
4705 }
4706}
4707
[email protected]269200b12010-11-18 22:53:064708error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354709 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104710 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4711 GLsizei n = static_cast<GLsizei>(c.n);
4712 uint32 data_size;
4713 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4714 return error::kOutOfBounds;
4715 }
4716 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4717 c.ids_shm_id, c.ids_shm_offset, data_size);
4718 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514719 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104720 return error::kNoError;
4721 }
4722 if (ids == NULL) {
4723 return error::kOutOfBounds;
4724 }
[email protected]269200b12010-11-18 22:53:064725 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104726 return error::kNoError;
4727}
4728
[email protected]a7266a92012-06-28 02:11:084729error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]09e17272012-11-30 10:30:444730 DCHECK(!ShouldDeferDraws());
[email protected]0d6bfdc2011-11-02 01:32:204731 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]297ca1c2011-06-20 23:08:464732 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:274733 glClear(mask);
4734 }
[email protected]a7266a92012-06-28 02:11:084735 return error::kNoError;
4736}
4737
[email protected]36cef8ce2010-03-16 07:34:454738void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4739 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034740 GLuint client_renderbuffer_id) {
[email protected]4d8f0dd2013-03-09 14:37:064741 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4742 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514743 LOCAL_SET_GL_ERROR(
4744 GL_INVALID_OPERATION,
4745 "glFramebufferRenderbuffer", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454746 return;
4747 }
[email protected]ae51d192010-04-27 00:48:034748 GLuint service_id = 0;
[email protected]ee2a79c32013-03-10 03:50:274749 Renderbuffer* renderbuffer = NULL;
[email protected]ae51d192010-04-27 00:48:034750 if (client_renderbuffer_id) {
[email protected]ee2a79c32013-03-10 03:50:274751 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4752 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:514753 LOCAL_SET_GL_ERROR(
4754 GL_INVALID_OPERATION,
4755 "glFramebufferRenderbuffer", "unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034756 return;
4757 }
[email protected]ee2a79c32013-03-10 03:50:274758 service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:034759 }
[email protected]ab09b612013-03-11 22:11:514760 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
[email protected]ae51d192010-04-27 00:48:034761 glFramebufferRenderbufferEXT(
4762 target, attachment, renderbuffertarget, service_id);
[email protected]ab09b612013-03-11 22:11:514763 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
[email protected]9edc6b22010-12-23 02:00:264764 if (error == GL_NO_ERROR) {
[email protected]ee2a79c32013-03-10 03:50:274765 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
[email protected]3a2e7c7b2010-08-06 01:12:284766 }
[email protected]7cd76fd2013-06-02 21:11:114767 if (framebuffer == state_.bound_draw_framebuffer.get()) {
[email protected]88a61bf2012-10-27 13:00:424768 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:464769 }
[email protected]81fc9d02013-03-14 23:53:324770 OnFboChanged();
[email protected]3a2e7c7b2010-08-06 01:12:284771}
4772
[email protected]3a2e7c7b2010-08-06 01:12:284773void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464774 if (SetCapabilityState(cap, false)) {
4775 glDisable(cap);
4776 }
[email protected]3a2e7c7b2010-08-06 01:12:284777}
4778
4779void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464780 if (SetCapabilityState(cap, true)) {
4781 glEnable(cap);
4782 }
[email protected]3a2e7c7b2010-08-06 01:12:284783}
4784
[email protected]88a61bf2012-10-27 13:00:424785void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4786 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4787 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4788 glDepthRange(znear, zfar);
[email protected]3a2e7c7b2010-08-06 01:12:284789}
4790
[email protected]b04e24c2013-01-08 18:35:254791void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
[email protected]88a61bf2012-10-27 13:00:424792 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4793 state_.sample_coverage_invert = (invert != 0);
4794 glSampleCoverage(state_.sample_coverage_value, invert);
[email protected]3a2e7c7b2010-08-06 01:12:284795}
4796
[email protected]0d6bfdc2011-11-02 01:32:204797// Assumes framebuffer is complete.
4798void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]4d8f0dd2013-03-09 14:37:064799 GLenum target, Framebuffer* framebuffer) {
[email protected]8e3e0662010-08-23 18:46:304800 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204801 // bind this to the DRAW point, clear then bind back to READ
4802 // TODO(gman): I don't think there is any guarantee that an FBO that
4803 // is complete on the READ attachment will be complete as a DRAW
4804 // attachment.
4805 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
[email protected]4d8f0dd2013-03-09 14:37:064806 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
[email protected]8e3e0662010-08-23 18:46:304807 }
[email protected]3a2e7c7b2010-08-06 01:12:284808 GLbitfield clear_bits = 0;
[email protected]4d8f0dd2013-03-09 14:37:064809 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464810 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204811 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464812 (GLES2Util::GetChannelsForFormat(
[email protected]4d8f0dd2013-03-09 14:37:064813 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4814 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284815 glColorMask(true, true, true, true);
4816 clear_bits |= GL_COLOR_BUFFER_BIT;
4817 }
4818
[email protected]4d8f0dd2013-03-09 14:37:064819 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4820 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
[email protected]3a2e7c7b2010-08-06 01:12:284821 glClearStencil(0);
4822 glStencilMask(-1);
4823 clear_bits |= GL_STENCIL_BUFFER_BIT;
4824 }
4825
[email protected]4d8f0dd2013-03-09 14:37:064826 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4827 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
[email protected]3a2e7c7b2010-08-06 01:12:284828 glClearDepth(1.0f);
4829 glDepthMask(true);
4830 clear_bits |= GL_DEPTH_BUFFER_BIT;
4831 }
4832
4833 glDisable(GL_SCISSOR_TEST);
4834 glClear(clear_bits);
4835
[email protected]968351b2011-12-20 08:26:514836 framebuffer_manager()->MarkAttachmentsAsCleared(
[email protected]4d8f0dd2013-03-09 14:37:064837 framebuffer, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284838
[email protected]c007aa02010-09-02 22:22:404839 RestoreClearState();
4840
4841 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]4d8f0dd2013-03-09 14:37:064842 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4843 Framebuffer* draw_framebuffer =
[email protected]87d1a3fe2011-12-01 04:25:484844 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]4d8f0dd2013-03-09 14:37:064845 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4846 GetBackbufferServiceId();
[email protected]87d1a3fe2011-12-01 04:25:484847 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404848 }
4849}
4850
4851void GLES2DecoderImpl::RestoreClearState() {
[email protected]88a61bf2012-10-27 13:00:424852 clear_state_dirty_ = true;
[email protected]e259eb412012-10-13 05:47:244853 glClearColor(
4854 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4855 state_.color_clear_alpha);
4856 glClearStencil(state_.stencil_clear);
4857 glClearDepth(state_.depth_clear);
[email protected]f731b9462012-10-30 00:35:224858 if (state_.enable_flags.scissor_test) {
[email protected]3a2e7c7b2010-08-06 01:12:284859 glEnable(GL_SCISSOR_TEST);
4860 }
[email protected]36cef8ce2010-03-16 07:34:454861}
4862
4863GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]ed9f9cd2013-02-27 21:12:354864 Framebuffer* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304865 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204866 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454867 return GL_FRAMEBUFFER_COMPLETE;
4868 }
[email protected]0d6bfdc2011-11-02 01:32:204869 GLenum completeness = framebuffer->IsPossiblyComplete();
4870 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4871 return completeness;
4872 }
[email protected]73276522012-11-09 05:50:204873 return framebuffer->GetStatus(texture_manager(), target);
[email protected]36cef8ce2010-03-16 07:34:454874}
4875
4876void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034877 GLenum target, GLenum attachment, GLenum textarget,
4878 GLuint client_texture_id, GLint level) {
[email protected]7d3c36e2013-07-12 14:13:164879 DoFramebufferTexture2DCommon(
4880 "glFramebufferTexture2D", target, attachment,
4881 textarget, client_texture_id, level, 0);
4882}
4883
4884void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
4885 GLenum target, GLenum attachment, GLenum textarget,
4886 GLuint client_texture_id, GLint level, GLsizei samples) {
4887 if (!features().multisampled_render_to_texture) {
4888 LOCAL_SET_GL_ERROR(
4889 GL_INVALID_OPERATION,
4890 "glFramebufferTexture2DMultisample", "function not available");
4891 return;
4892 }
4893 DoFramebufferTexture2DCommon(
4894 "glFramebufferTexture2DMultisample", target, attachment,
4895 textarget, client_texture_id, level, samples);
4896}
4897
4898void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
4899 const char* name, GLenum target, GLenum attachment, GLenum textarget,
4900 GLuint client_texture_id, GLint level, GLsizei samples) {
4901 if (samples > renderbuffer_manager()->max_samples()) {
4902 LOCAL_SET_GL_ERROR(
4903 GL_INVALID_VALUE,
4904 "glFramebufferTexture2DMultisample", "samples too large");
4905 return;
4906 }
[email protected]4d8f0dd2013-03-09 14:37:064907 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4908 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514909 LOCAL_SET_GL_ERROR(
4910 GL_INVALID_OPERATION,
[email protected]7d3c36e2013-07-12 14:13:164911 name, "no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454912 return;
4913 }
[email protected]ae51d192010-04-27 00:48:034914 GLuint service_id = 0;
[email protected]370eaf12013-05-18 09:19:494915 TextureRef* texture_ref = NULL;
[email protected]ae51d192010-04-27 00:48:034916 if (client_texture_id) {
[email protected]370eaf12013-05-18 09:19:494917 texture_ref = GetTexture(client_texture_id);
4918 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:514919 LOCAL_SET_GL_ERROR(
4920 GL_INVALID_OPERATION,
[email protected]7d3c36e2013-07-12 14:13:164921 name, "unknown texture_ref");
[email protected]ae51d192010-04-27 00:48:034922 return;
4923 }
[email protected]370eaf12013-05-18 09:19:494924 service_id = texture_ref->service_id();
[email protected]ae51d192010-04-27 00:48:034925 }
[email protected]0d6bfdc2011-11-02 01:32:204926
[email protected]80eb6b52012-01-19 00:14:414927 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]ab09b612013-03-11 22:11:514928 LOCAL_SET_GL_ERROR(
4929 GL_INVALID_VALUE,
[email protected]7d3c36e2013-07-12 14:13:164930 name, "level out of range");
[email protected]0d6bfdc2011-11-02 01:32:204931 return;
4932 }
4933
[email protected]7d3c36e2013-07-12 14:13:164934 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
4935 if (0 == samples) {
4936 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
4937 } else {
4938 if (features().use_img_for_multisampled_render_to_texture) {
4939 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
4940 service_id, level, samples);
4941 } else {
4942 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
4943 service_id, level, samples);
4944 }
4945 }
4946 GLenum error = LOCAL_PEEK_GL_ERROR(name);
[email protected]9edc6b22010-12-23 02:00:264947 if (error == GL_NO_ERROR) {
[email protected]7d3c36e2013-07-12 14:13:164948 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
4949 samples);
[email protected]3a2e7c7b2010-08-06 01:12:284950 }
[email protected]7cd76fd2013-06-02 21:11:114951 if (framebuffer == state_.bound_draw_framebuffer.get()) {
[email protected]88a61bf2012-10-27 13:00:424952 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:464953 }
[email protected]81fc9d02013-03-14 23:53:324954 OnFboChanged();
[email protected]36cef8ce2010-03-16 07:34:454955}
4956
4957void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4958 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]4d8f0dd2013-03-09 14:37:064959 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4960 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514961 LOCAL_SET_GL_ERROR(
4962 GL_INVALID_OPERATION,
4963 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454964 return;
4965 }
[email protected]74c1ec42010-08-12 01:55:574966 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
[email protected]62e65f02013-05-29 22:28:104967 const Framebuffer::Attachment* attachment_object =
4968 framebuffer->GetAttachment(attachment);
4969 *params = attachment_object ? attachment_object->object_name() : 0;
4970 } else {
[email protected]7d3c36e2013-07-12 14:13:164971 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
4972 features().use_img_for_multisampled_render_to_texture) {
4973 pname = GL_TEXTURE_SAMPLES_IMG;
4974 }
[email protected]62e65f02013-05-29 22:28:104975 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574976 }
[email protected]36cef8ce2010-03-16 07:34:454977}
4978
4979void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4980 GLenum target, GLenum pname, GLint* params) {
[email protected]ed9f9cd2013-02-27 21:12:354981 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:204982 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4983 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:514984 LOCAL_SET_GL_ERROR(
4985 GL_INVALID_OPERATION,
4986 "glGetRenderbufferParameteriv", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454987 return;
4988 }
[email protected]3a03a8f2011-03-19 00:51:274989 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:434990 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4991 *params = renderbuffer->internal_format();
4992 break;
4993 case GL_RENDERBUFFER_WIDTH:
4994 *params = renderbuffer->width();
4995 break;
4996 case GL_RENDERBUFFER_HEIGHT:
4997 *params = renderbuffer->height();
4998 break;
[email protected]7d3c36e2013-07-12 14:13:164999 case GL_RENDERBUFFER_SAMPLES_EXT:
5000 if (features().use_img_for_multisampled_render_to_texture) {
5001 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5002 params);
5003 } else {
5004 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5005 params);
5006 }
[email protected]ad84a3a2012-06-08 21:42:435007 default:
5008 glGetRenderbufferParameterivEXT(target, pname, params);
5009 break;
[email protected]b71f52c2010-06-18 22:20:205010 }
[email protected]36cef8ce2010-03-16 07:34:455011}
5012
[email protected]8e3e0662010-08-23 18:46:305013void GLES2DecoderImpl::DoBlitFramebufferEXT(
5014 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5015 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5016 GLbitfield mask, GLenum filter) {
[email protected]09e17272012-11-30 10:30:445017 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
[email protected]62e155e2012-10-23 22:43:155018 if (!features().chromium_framebuffer_multisample) {
[email protected]ab09b612013-03-11 22:11:515019 LOCAL_SET_GL_ERROR(
5020 GL_INVALID_OPERATION,
5021 "glBlitFramebufferEXT", "function not available");
[email protected]8e3e0662010-08-23 18:46:305022 }
[email protected]0c16343f2013-03-08 20:40:165023
5024 if (!CheckBoundFramebuffersValid("glBlitFramebufferEXT")) {
5025 return;
5026 }
5027
[email protected]d058bca2012-11-26 10:27:265028 glDisable(GL_SCISSOR_TEST);
[email protected]5094b0f2010-11-09 19:45:245029 if (IsAngle()) {
5030 glBlitFramebufferANGLE(
5031 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5032 } else {
5033 glBlitFramebufferEXT(
5034 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5035 }
[email protected]d058bca2012-11-26 10:27:265036 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
[email protected]8e3e0662010-08-23 18:46:305037}
5038
5039void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
5040 GLenum target, GLsizei samples, GLenum internalformat,
5041 GLsizei width, GLsizei height) {
[email protected]7d3c36e2013-07-12 14:13:165042 if (!features().chromium_framebuffer_multisample &&
5043 !features().multisampled_render_to_texture) {
[email protected]ab09b612013-03-11 22:11:515044 LOCAL_SET_GL_ERROR(
5045 GL_INVALID_OPERATION,
5046 "glRenderbufferStorageMultisample", "function not available");
[email protected]8e3e0662010-08-23 18:46:305047 return;
5048 }
[email protected]8e3e0662010-08-23 18:46:305049
[email protected]ed9f9cd2013-02-27 21:12:355050 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:205051 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5052 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:515053 LOCAL_SET_GL_ERROR(
5054 GL_INVALID_OPERATION,
5055 "glRenderbufferStorageMultisample", "no renderbuffer bound");
[email protected]0d6bfdc2011-11-02 01:32:205056 return;
5057 }
5058
[email protected]84afefa2011-10-19 21:45:535059 if (samples > renderbuffer_manager()->max_samples()) {
[email protected]ab09b612013-03-11 22:11:515060 LOCAL_SET_GL_ERROR(
5061 GL_INVALID_VALUE,
5062 "glRenderbufferStorageMultisample", "samples too large");
[email protected]84afefa2011-10-19 21:45:535063 return;
5064 }
5065
5066 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5067 height > renderbuffer_manager()->max_renderbuffer_size()) {
[email protected]ab09b612013-03-11 22:11:515068 LOCAL_SET_GL_ERROR(
5069 GL_INVALID_VALUE,
5070 "glRenderbufferStorageMultisample", "dimensions too large");
[email protected]84afefa2011-10-19 21:45:535071 return;
5072 }
5073
[email protected]7989c9e2013-01-23 06:39:265074 uint32 estimated_size = 0;
5075 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
5076 width, height, samples, internalformat, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515077 LOCAL_SET_GL_ERROR(
5078 GL_OUT_OF_MEMORY,
5079 "glRenderbufferStorageMultsample", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:265080 return;
[email protected]8e3e0662010-08-23 18:46:305081 }
5082
[email protected]7989c9e2013-01-23 06:39:265083 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515084 LOCAL_SET_GL_ERROR(
5085 GL_OUT_OF_MEMORY,
5086 "glRenderbufferStorageMultsample", "out of memory");
[email protected]7989c9e2013-01-23 06:39:265087 return;
5088 }
5089
5090 GLenum impl_format = RenderbufferManager::
5091 InternalRenderbufferFormatToImplFormat(internalformat);
[email protected]ab09b612013-03-11 22:11:515092 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisample");
[email protected]866b91c52011-03-23 14:38:085093 if (IsAngle()) {
5094 glRenderbufferStorageMultisampleANGLE(
5095 target, samples, impl_format, width, height);
[email protected]7d3c36e2013-07-12 14:13:165096 } else if (features().use_img_for_multisampled_render_to_texture) {
5097 glRenderbufferStorageMultisampleIMG(
5098 target, samples, impl_format, width, height);
[email protected]866b91c52011-03-23 14:38:085099 } else {
5100 glRenderbufferStorageMultisampleEXT(
5101 target, samples, impl_format, width, height);
5102 }
[email protected]ab09b612013-03-11 22:11:515103 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisample");
[email protected]9edc6b22010-12-23 02:00:265104 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:515105 // TODO(gman): If renderbuffers tracked which framebuffers they were
5106 // attached to we could just mark those framebuffers as not complete.
5107 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:205108 renderbuffer_manager()->SetInfo(
5109 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:265110 }
[email protected]8e3e0662010-08-23 18:46:305111}
5112
[email protected]36cef8ce2010-03-16 07:34:455113void GLES2DecoderImpl::DoRenderbufferStorage(
5114 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]ed9f9cd2013-02-27 21:12:355115 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:205116 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5117 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:515118 LOCAL_SET_GL_ERROR(
5119 GL_INVALID_OPERATION,
5120 "glRenderbufferStorage", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:455121 return;
5122 }
[email protected]876f6fee2010-08-02 23:10:325123
[email protected]84afefa2011-10-19 21:45:535124 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5125 height > renderbuffer_manager()->max_renderbuffer_size()) {
[email protected]ab09b612013-03-11 22:11:515126 LOCAL_SET_GL_ERROR(
5127 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
[email protected]84afefa2011-10-19 21:45:535128 return;
5129 }
5130
[email protected]7989c9e2013-01-23 06:39:265131 uint32 estimated_size = 0;
5132 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
5133 width, height, 1, internalformat, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515134 LOCAL_SET_GL_ERROR(
5135 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:265136 return;
5137 }
5138
5139 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515140 LOCAL_SET_GL_ERROR(
5141 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
[email protected]7989c9e2013-01-23 06:39:265142 return;
[email protected]b71f52c2010-06-18 22:20:205143 }
[email protected]876f6fee2010-08-02 23:10:325144
[email protected]ab09b612013-03-11 22:11:515145 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
[email protected]7989c9e2013-01-23 06:39:265146 glRenderbufferStorageEXT(
5147 target, RenderbufferManager::
5148 InternalRenderbufferFormatToImplFormat(internalformat),
5149 width, height);
[email protected]ab09b612013-03-11 22:11:515150 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
[email protected]9edc6b22010-12-23 02:00:265151 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:515152 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5153 // we could just mark those framebuffers as not complete.
5154 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:205155 renderbuffer_manager()->SetInfo(
[email protected]7989c9e2013-01-23 06:39:265156 renderbuffer, 1, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:265157 }
[email protected]36cef8ce2010-03-16 07:34:455158}
5159
[email protected]df37b9932013-03-08 05:21:425160void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
[email protected]43ed3a72012-05-30 22:55:385161 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]df37b9932013-03-08 05:21:425162 Program* program = GetProgramInfoNotShader(
5163 program_id, "glLinkProgram");
5164 if (!program) {
[email protected]a93bb842010-02-16 23:03:475165 return;
5166 }
[email protected]05afda12011-01-20 00:17:345167
[email protected]df37b9932013-03-08 05:21:425168 LogClientServiceForInfo(program, program_id, "glLinkProgram");
[email protected]65dfc602012-07-23 20:39:395169 ShaderTranslator* vertex_translator = NULL;
5170 ShaderTranslator* fragment_translator = NULL;
5171 if (use_shader_translator_) {
[email protected]7cd76fd2013-06-02 21:11:115172 vertex_translator = vertex_translator_.get();
5173 fragment_translator = fragment_translator_.get();
[email protected]65dfc602012-07-23 20:39:395174 }
[email protected]df37b9932013-03-08 05:21:425175 if (program->Link(shader_manager(),
[email protected]7cd76fd2013-06-02 21:11:115176 vertex_translator,
5177 fragment_translator,
5178 feature_info_.get(),
5179 shader_cache_callback_)) {
[email protected]df37b9932013-03-08 05:21:425180 if (program == state_.current_program.get()) {
[email protected]62e155e2012-10-23 22:43:155181 if (workarounds().use_current_program_after_successful_link) {
[email protected]df37b9932013-03-08 05:21:425182 glUseProgram(program->service_id());
[email protected]c2a3caf12012-10-23 19:32:005183 }
[email protected]df37b9932013-03-08 05:21:425184 program_manager()->ClearUniforms(program);
[email protected]2df73892012-04-28 01:09:545185 }
5186 }
[email protected]07f54fcc2009-12-22 02:46:305187};
5188
[email protected]3916c97e2010-02-25 03:20:505189void GLES2DecoderImpl::DoTexParameterf(
5190 GLenum target, GLenum pname, GLfloat param) {
[email protected]370eaf12013-05-18 09:19:495191 TextureRef* texture = GetTextureInfoForTarget(target);
[email protected]02965c22013-03-09 02:40:075192 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515193 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245194 return;
[email protected]07f54fcc2009-12-22 02:46:305195 }
[email protected]cbb22e42011-05-12 23:36:245196
[email protected]02965c22013-03-09 02:40:075197 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505198 "glTexParameterf", GetErrorState(), texture, pname,
5199 static_cast<GLint>(param));
[email protected]07f54fcc2009-12-22 02:46:305200}
5201
[email protected]3916c97e2010-02-25 03:20:505202void GLES2DecoderImpl::DoTexParameteri(
5203 GLenum target, GLenum pname, GLint param) {
[email protected]370eaf12013-05-18 09:19:495204 TextureRef* texture = GetTextureInfoForTarget(target);
[email protected]02965c22013-03-09 02:40:075205 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515206 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245207 return;
[email protected]3916c97e2010-02-25 03:20:505208 }
[email protected]cbb22e42011-05-12 23:36:245209
[email protected]02965c22013-03-09 02:40:075210 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505211 "glTexParameteri", GetErrorState(), texture, pname, param);
[email protected]3916c97e2010-02-25 03:20:505212}
5213
5214void GLES2DecoderImpl::DoTexParameterfv(
5215 GLenum target, GLenum pname, const GLfloat* params) {
[email protected]370eaf12013-05-18 09:19:495216 TextureRef* texture = GetTextureInfoForTarget(target);
[email protected]02965c22013-03-09 02:40:075217 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515218 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245219 return;
[email protected]3916c97e2010-02-25 03:20:505220 }
[email protected]cbb22e42011-05-12 23:36:245221
[email protected]02965c22013-03-09 02:40:075222 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505223 "glTexParameterfv", GetErrorState(), texture, pname,
5224 static_cast<GLint>(params[0]));
[email protected]3916c97e2010-02-25 03:20:505225}
5226
5227void GLES2DecoderImpl::DoTexParameteriv(
5228 GLenum target, GLenum pname, const GLint* params) {
[email protected]370eaf12013-05-18 09:19:495229 TextureRef* texture = GetTextureInfoForTarget(target);
[email protected]02965c22013-03-09 02:40:075230 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515231 LOCAL_SET_GL_ERROR(
5232 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245233 return;
[email protected]3916c97e2010-02-25 03:20:505234 }
[email protected]cbb22e42011-05-12 23:36:245235
[email protected]02965c22013-03-09 02:40:075236 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505237 "glTexParameteriv", GetErrorState(), texture, pname, *params);
[email protected]3916c97e2010-02-25 03:20:505238}
5239
[email protected]939e7362010-05-13 20:49:105240bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]7cd76fd2013-06-02 21:11:115241 if (!state_.current_program.get()) {
[email protected]ad84a3a2012-06-08 21:42:435242 // The program does not exist.
[email protected]ab09b612013-03-11 22:11:515243 LOCAL_SET_GL_ERROR(
5244 GL_INVALID_OPERATION, function_name, "no program in use");
[email protected]ad84a3a2012-06-08 21:42:435245 return false;
[email protected]939e7362010-05-13 20:49:105246 }
[email protected]e259eb412012-10-13 05:47:245247 if (!state_.current_program->InUse()) {
[email protected]ab09b612013-03-11 22:11:515248 LOCAL_SET_GL_ERROR(
5249 GL_INVALID_OPERATION, function_name, "program not linked");
[email protected]939e7362010-05-13 20:49:105250 return false;
5251 }
5252 return true;
5253}
5254
5255bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5256 GLint location, const char* function_name) {
5257 if (!CheckCurrentProgram(function_name)) {
5258 return false;
5259 }
5260 return location != -1;
5261}
5262
[email protected]476ccb72012-12-06 15:52:525263namespace {
5264
5265static const GLenum valid_int_vec1_types_list[] = {
5266 GL_INT,
5267 GL_BOOL,
5268 GL_SAMPLER_2D,
5269 GL_SAMPLER_2D_RECT_ARB,
5270 GL_SAMPLER_CUBE,
5271 GL_SAMPLER_EXTERNAL_OES,
5272};
5273
5274static const GLenum valid_int_vec2_types_list[] = {
5275 GL_INT_VEC2,
5276 GL_BOOL_VEC2,
5277};
5278
5279static const GLenum valid_int_vec3_types_list[] = {
5280 GL_INT_VEC3,
5281 GL_BOOL_VEC3,
5282};
5283
5284static const GLenum valid_int_vec4_types_list[] = {
5285 GL_INT_VEC4,
5286 GL_BOOL_VEC4,
5287};
5288
5289static const GLenum valid_float_vec1_types_list[] = {
5290 GL_FLOAT,
5291 GL_BOOL,
5292};
5293
5294static const GLenum valid_float_vec2_types_list[] = {
5295 GL_FLOAT_VEC2,
5296 GL_BOOL_VEC2,
5297};
5298
5299static const GLenum valid_float_vec3_types_list[] = {
5300 GL_FLOAT_VEC3,
5301 GL_BOOL_VEC3,
5302};
5303
5304static const GLenum valid_float_vec4_types_list[] = {
5305 GL_FLOAT_VEC4,
5306 GL_BOOL_VEC4,
5307};
5308
5309static const GLenum valid_float_mat2_types_list[] = {
5310 GL_FLOAT_MAT2,
5311};
5312
5313static const GLenum valid_float_mat3_types_list[] = {
5314 GL_FLOAT_MAT3,
5315};
5316
5317static const GLenum valid_float_mat4_types_list[] = {
5318 GL_FLOAT_MAT4,
5319};
5320
5321static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info = {
5322 valid_int_vec1_types_list,
5323 arraysize(valid_int_vec1_types_list),
5324};
5325
5326static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info = {
5327 valid_int_vec2_types_list,
5328 arraysize(valid_int_vec2_types_list),
5329};
5330
5331static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info = {
5332 valid_int_vec3_types_list,
5333 arraysize(valid_int_vec3_types_list),
5334};
5335
5336static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info = {
5337 valid_int_vec4_types_list,
5338 arraysize(valid_int_vec4_types_list),
5339};
5340
5341static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info = {
5342 valid_float_vec1_types_list,
5343 arraysize(valid_float_vec1_types_list),
5344};
5345
5346static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info = {
5347 valid_float_vec2_types_list,
5348 arraysize(valid_float_vec2_types_list),
5349};
5350
5351static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info = {
5352 valid_float_vec3_types_list,
5353 arraysize(valid_float_vec3_types_list),
5354};
5355
5356static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info = {
5357 valid_float_vec4_types_list,
5358 arraysize(valid_float_vec4_types_list),
5359};
5360
5361static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info = {
5362 valid_float_mat2_types_list,
5363 arraysize(valid_float_mat2_types_list),
5364};
5365
5366static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info = {
5367 valid_float_mat3_types_list,
5368 arraysize(valid_float_mat3_types_list),
5369};
5370
5371static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info = {
5372 valid_float_mat4_types_list,
5373 arraysize(valid_float_mat4_types_list),
5374};
5375
5376} // anonymous namespace.
5377
[email protected]43c2f1f2011-03-25 18:35:365378bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:125379 GLint fake_location, const char* function_name,
[email protected]476ccb72012-12-06 15:52:525380 const GLES2DecoderImpl::BaseUniformInfo& base_info,
[email protected]1b0a6752012-02-22 03:44:125381 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:365382 DCHECK(type);
5383 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:125384 DCHECK(real_location);
[email protected]476ccb72012-12-06 15:52:525385
[email protected]1b0a6752012-02-22 03:44:125386 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:105387 return false;
5388 }
[email protected]43c2f1f2011-03-25 18:35:365389 GLint array_index = -1;
[email protected]ed9f9cd2013-02-27 21:12:355390 const Program::UniformInfo* info =
[email protected]e259eb412012-10-13 05:47:245391 state_.current_program->GetUniformInfoByFakeLocation(
[email protected]1b0a6752012-02-22 03:44:125392 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:365393 if (!info) {
[email protected]ab09b612013-03-11 22:11:515394 LOCAL_SET_GL_ERROR(
5395 GL_INVALID_OPERATION, function_name, "unknown location");
[email protected]939e7362010-05-13 20:49:105396 return false;
5397 }
[email protected]476ccb72012-12-06 15:52:525398 bool okay = false;
5399 for (size_t ii = 0; ii < base_info.num_valid_types; ++ii) {
5400 if (base_info.valid_types[ii] == info->type) {
5401 okay = true;
5402 break;
5403 }
5404 }
5405 if (!okay) {
[email protected]ab09b612013-03-11 22:11:515406 LOCAL_SET_GL_ERROR(
5407 GL_INVALID_OPERATION, function_name,
5408 "wrong uniform function for type");
[email protected]476ccb72012-12-06 15:52:525409 return false;
5410 }
[email protected]43c2f1f2011-03-25 18:35:365411 if (*count > 1 && !info->is_array) {
[email protected]ab09b612013-03-11 22:11:515412 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:435413 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
[email protected]43c2f1f2011-03-25 18:35:365414 return false;
5415 }
5416 *count = std::min(info->size - array_index, *count);
5417 if (*count <= 0) {
5418 return false;
5419 }
5420 *type = info->type;
[email protected]939e7362010-05-13 20:49:105421 return true;
5422}
5423
[email protected]1b0a6752012-02-22 03:44:125424void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5425 GLenum type = 0;
5426 GLsizei count = 1;
5427 GLint real_location = -1;
5428 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525429 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5430 &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:505431 return;
5432 }
[email protected]e259eb412012-10-13 05:47:245433 if (!state_.current_program->SetSamplers(
[email protected]1868a342012-11-07 15:56:025434 state_.texture_units.size(), fake_location, 1, &v0)) {
[email protected]ab09b612013-03-11 22:11:515435 LOCAL_SET_GL_ERROR(
5436 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:465437 return;
5438 }
[email protected]1b0a6752012-02-22 03:44:125439 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:505440}
5441
5442void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:125443 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:365444 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125445 GLint real_location = -1;
5446 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525447 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5448 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365449 return;
5450 }
[email protected]74727112012-06-13 21:18:085451 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5452 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]e259eb412012-10-13 05:47:245453 if (!state_.current_program->SetSamplers(
[email protected]1868a342012-11-07 15:56:025454 state_.texture_units.size(), fake_location, count, value)) {
[email protected]ab09b612013-03-11 22:11:515455 LOCAL_SET_GL_ERROR(
5456 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:465457 return;
5458 }
[email protected]43c2f1f2011-03-25 18:35:365459 }
[email protected]1b0a6752012-02-22 03:44:125460 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:505461}
5462
[email protected]939e7362010-05-13 20:49:105463void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:125464 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365465 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125466 GLint real_location = -1;
5467 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525468 fake_location, "glUniform1fv", valid_float_vec1_base_info,
5469 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105470 return;
5471 }
5472 if (type == GL_BOOL) {
[email protected]40d90a22013-04-09 03:39:555473 scoped_ptr<GLint[]> temp(new GLint[count]);
[email protected]939e7362010-05-13 20:49:105474 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:535475 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105476 }
[email protected]1b0a6752012-02-22 03:44:125477 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105478 } else {
[email protected]1b0a6752012-02-22 03:44:125479 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105480 }
5481}
5482
5483void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:125484 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365485 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125486 GLint real_location = -1;
5487 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525488 fake_location, "glUniform2fv", valid_float_vec2_base_info,
5489 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105490 return;
5491 }
5492 if (type == GL_BOOL_VEC2) {
5493 GLsizei num_values = count * 2;
[email protected]40d90a22013-04-09 03:39:555494 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105495 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535496 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105497 }
[email protected]1b0a6752012-02-22 03:44:125498 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105499 } else {
[email protected]1b0a6752012-02-22 03:44:125500 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105501 }
5502}
5503
5504void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:125505 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365506 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125507 GLint real_location = -1;
5508 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525509 fake_location, "glUniform3fv", valid_float_vec3_base_info,
5510 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105511 return;
5512 }
5513 if (type == GL_BOOL_VEC3) {
5514 GLsizei num_values = count * 3;
[email protected]40d90a22013-04-09 03:39:555515 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105516 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535517 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105518 }
[email protected]1b0a6752012-02-22 03:44:125519 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105520 } else {
[email protected]1b0a6752012-02-22 03:44:125521 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105522 }
5523}
5524
5525void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:125526 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365527 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125528 GLint real_location = -1;
5529 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525530 fake_location, "glUniform4fv", valid_float_vec4_base_info,
5531 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105532 return;
5533 }
5534 if (type == GL_BOOL_VEC4) {
5535 GLsizei num_values = count * 4;
[email protected]40d90a22013-04-09 03:39:555536 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105537 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535538 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105539 }
[email protected]1b0a6752012-02-22 03:44:125540 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105541 } else {
[email protected]1b0a6752012-02-22 03:44:125542 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105543 }
5544}
5545
[email protected]43c2f1f2011-03-25 18:35:365546void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:125547 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365548 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125549 GLint real_location = -1;
5550 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525551 fake_location, "glUniform2iv", valid_int_vec2_base_info,
5552 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365553 return;
5554 }
[email protected]1b0a6752012-02-22 03:44:125555 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365556}
5557
5558void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:125559 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365560 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125561 GLint real_location = -1;
5562 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525563 fake_location, "glUniform3iv", valid_int_vec3_base_info,
5564 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365565 return;
5566 }
[email protected]1b0a6752012-02-22 03:44:125567 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365568}
5569
5570void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:125571 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365572 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125573 GLint real_location = -1;
5574 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525575 fake_location, "glUniform4iv", valid_int_vec4_base_info,
5576 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365577 return;
5578 }
[email protected]1b0a6752012-02-22 03:44:125579 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365580}
5581
5582void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:125583 GLint fake_location, GLsizei count, GLboolean transpose,
5584 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365585 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125586 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365587 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525588 fake_location, "glUniformMatrix2fv", valid_float_mat2_base_info,
5589 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365590 return;
5591 }
[email protected]1b0a6752012-02-22 03:44:125592 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365593}
5594
5595void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:125596 GLint fake_location, GLsizei count, GLboolean transpose,
5597 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365598 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125599 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365600 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525601 fake_location, "glUniformMatrix3fv", valid_float_mat3_base_info,
5602 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365603 return;
5604 }
[email protected]1b0a6752012-02-22 03:44:125605 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365606}
5607
5608void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:125609 GLint fake_location, GLsizei count, GLboolean transpose,
5610 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365611 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125612 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365613 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525614 fake_location, "glUniformMatrix4fv", valid_float_mat4_base_info,
5615 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365616 return;
5617 }
[email protected]1b0a6752012-02-22 03:44:125618 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365619}
5620
[email protected]df37b9932013-03-08 05:21:425621void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
[email protected]ae51d192010-04-27 00:48:035622 GLuint service_id = 0;
[email protected]df37b9932013-03-08 05:21:425623 Program* program = NULL;
5624 if (program_id) {
5625 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5626 if (!program) {
[email protected]ae51d192010-04-27 00:48:035627 return;
5628 }
[email protected]df37b9932013-03-08 05:21:425629 if (!program->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:505630 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ab09b612013-03-11 22:11:515631 LOCAL_SET_GL_ERROR(
5632 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
[email protected]3916c97e2010-02-25 03:20:505633 return;
5634 }
[email protected]df37b9932013-03-08 05:21:425635 service_id = program->service_id();
[email protected]3916c97e2010-02-25 03:20:505636 }
[email protected]7cd76fd2013-06-02 21:11:115637 if (state_.current_program.get()) {
5638 program_manager()->UnuseProgram(shader_manager(),
5639 state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:145640 }
[email protected]df37b9932013-03-08 05:21:425641 state_.current_program = program;
5642 LogClientServiceMapping("glUseProgram", program_id, service_id);
[email protected]2df73892012-04-28 01:09:545643 glUseProgram(service_id);
[email protected]7cd76fd2013-06-02 21:11:115644 if (state_.current_program.get()) {
5645 program_manager()->UseProgram(state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:145646 }
[email protected]3916c97e2010-02-25 03:20:505647}
5648
[email protected]ab09b612013-03-11 22:11:515649void GLES2DecoderImpl::RenderWarning(
5650 const char* filename, int line, const std::string& msg) {
[email protected]1d82e822013-04-10 21:32:325651 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
[email protected]0f8afe82012-05-14 23:43:015652}
5653
[email protected]ab09b612013-03-11 22:11:515654void GLES2DecoderImpl::PerformanceWarning(
5655 const char* filename, int line, const std::string& msg) {
[email protected]d3eba342013-04-18 21:11:505656 logger_.LogMessage(filename, line,
5657 std::string("PERFORMANCE WARNING: ") + msg);
[email protected]0f8afe82012-05-14 23:43:015658}
5659
[email protected]df37b9932013-03-08 05:21:425660void GLES2DecoderImpl::ForceCompileShaderIfPending(Shader* shader) {
5661 if (shader->compilation_status() ==
[email protected]ed9f9cd2013-02-27 21:12:355662 Shader::PENDING_DEFERRED_COMPILE) {
[email protected]c447acd2012-07-23 23:48:415663 ShaderTranslator* translator = NULL;
5664 if (use_shader_translator_) {
[email protected]df37b9932013-03-08 05:21:425665 translator = shader->shader_type() == GL_VERTEX_SHADER ?
[email protected]c447acd2012-07-23 23:48:415666 vertex_translator_.get() : fragment_translator_.get();
5667 }
5668 // We know there will be no errors, because we only defer compilation on
5669 // shaders that were previously compiled successfully.
[email protected]df37b9932013-03-08 05:21:425670 program_manager()->ForceCompileShader(shader->deferred_compilation_source(),
5671 shader,
[email protected]c447acd2012-07-23 23:48:415672 translator,
[email protected]7cd76fd2013-06-02 21:11:115673 feature_info_.get());
[email protected]c447acd2012-07-23 23:48:415674 }
5675}
5676
[email protected]ef526492010-06-02 23:12:255677bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]7cd76fd2013-06-02 21:11:115678 DCHECK(state_.current_program.get());
[email protected]ef526492010-06-02 23:12:255679 // Only check if there are some unrenderable textures.
5680 if (!texture_manager()->HaveUnrenderableTextures()) {
5681 return false;
5682 }
[email protected]e2367b42013-05-31 03:37:215683
[email protected]ef526492010-06-02 23:12:255684 bool textures_set = false;
[email protected]ed9f9cd2013-02-27 21:12:355685 const Program::SamplerIndices& sampler_indices =
[email protected]e259eb412012-10-13 05:47:245686 state_.current_program->sampler_indices();
[email protected]3916c97e2010-02-25 03:20:505687 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355688 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245689 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]3916c97e2010-02-25 03:20:505690 DCHECK(uniform_info);
5691 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5692 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025693 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245694 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]370eaf12013-05-18 09:19:495695 TextureRef* texture =
[email protected]cadac622013-06-11 16:46:365696 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
[email protected]02965c22013-03-09 02:40:075697 if (!texture || !texture_manager()->CanRender(texture)) {
[email protected]ef526492010-06-02 23:12:255698 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:505699 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5700 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:315701 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:495702 texture_manager()->black_texture_id(uniform_info->type));
[email protected]ab09b612013-03-11 22:11:515703 LOCAL_RENDER_WARNING(
[email protected]0f8afe82012-05-14 23:43:015704 std::string("texture bound to texture unit ") +
5705 base::IntToString(texture_unit_index) +
[email protected]ad9b7f8b2013-06-17 07:36:295706 " is not renderable. It maybe non-power-of-2 and have"
5707 " incompatible texture filtering or is not"
5708 " 'texture complete'");
[email protected]3916c97e2010-02-25 03:20:505709 }
5710 }
5711 // else: should this be an error?
5712 }
5713 }
[email protected]ef526492010-06-02 23:12:255714 return textures_set;
[email protected]3916c97e2010-02-25 03:20:505715}
5716
5717void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
[email protected]7cd76fd2013-06-02 21:11:115718 DCHECK(state_.current_program.get());
[email protected]ed9f9cd2013-02-27 21:12:355719 const Program::SamplerIndices& sampler_indices =
[email protected]7cd76fd2013-06-02 21:11:115720 state_.current_program->sampler_indices();
[email protected]3916c97e2010-02-25 03:20:505721 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355722 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245723 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]3916c97e2010-02-25 03:20:505724 DCHECK(uniform_info);
5725 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5726 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025727 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245728 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]7cd76fd2013-06-02 21:11:115729 TextureRef* texture_ref =
5730 uniform_info->type == GL_SAMPLER_2D
5731 ? texture_unit.bound_texture_2d.get()
5732 : texture_unit.bound_texture_cube_map.get();
[email protected]370eaf12013-05-18 09:19:495733 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
[email protected]3916c97e2010-02-25 03:20:505734 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
[email protected]370eaf12013-05-18 09:19:495735 // Get the texture_ref info that was previously bound here.
[email protected]7cd76fd2013-06-02 21:11:115736 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
5737 ? texture_unit.bound_texture_2d.get()
5738 : texture_unit.bound_texture_cube_map.get();
[email protected]3916c97e2010-02-25 03:20:505739 glBindTexture(texture_unit.bind_target,
[email protected]370eaf12013-05-18 09:19:495740 texture_ref ? texture_ref->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:505741 }
5742 }
5743 }
5744 }
5745 // Set the active texture back to whatever the user had it as.
[email protected]e259eb412012-10-13 05:47:245746 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]07f54fcc2009-12-22 02:46:305747}
5748
[email protected]0d6bfdc2011-11-02 01:32:205749bool GLES2DecoderImpl::ClearUnclearedTextures() {
5750 // Only check if there are some uncleared textures.
5751 if (!texture_manager()->HaveUnsafeTextures()) {
5752 return true;
5753 }
5754
5755 // 1: Check all textures we are about to render with.
[email protected]7cd76fd2013-06-02 21:11:115756 if (state_.current_program.get()) {
[email protected]ed9f9cd2013-02-27 21:12:355757 const Program::SamplerIndices& sampler_indices =
[email protected]7cd76fd2013-06-02 21:11:115758 state_.current_program->sampler_indices();
[email protected]0d6bfdc2011-11-02 01:32:205759 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355760 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245761 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]0d6bfdc2011-11-02 01:32:205762 DCHECK(uniform_info);
5763 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5764 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025765 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245766 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]370eaf12013-05-18 09:19:495767 TextureRef* texture_ref =
[email protected]cadac622013-06-11 16:46:365768 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
[email protected]370eaf12013-05-18 09:19:495769 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
5770 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
[email protected]0d6bfdc2011-11-02 01:32:205771 return false;
5772 }
5773 }
5774 }
5775 }
5776 }
5777 }
5778 return true;
5779}
5780
[email protected]c6aef902012-02-14 03:31:425781bool GLES2DecoderImpl::IsDrawValid(
[email protected]ad84a3a2012-06-08 21:42:435782 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:035783 // NOTE: We specifically do not check current_program->IsValid() because
5784 // it could never be invalid since glUseProgram would have failed. While
5785 // glLinkProgram could later mark the program as invalid the previous
5786 // valid program will still function if it is still the current program.
[email protected]7cd76fd2013-06-02 21:11:115787 if (!state_.current_program.get()) {
[email protected]3916c97e2010-02-25 03:20:505788 // The program does not exist.
5789 // But GL says no ERROR.
[email protected]ab09b612013-03-11 22:11:515790 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
[email protected]3916c97e2010-02-25 03:20:505791 return false;
5792 }
[email protected]c6aef902012-02-14 03:31:425793
[email protected]7cd76fd2013-06-02 21:11:115794 return state_.vertex_attrib_manager
5795 ->ValidateBindings(function_name,
5796 this,
5797 feature_info_.get(),
5798 state_.current_program.get(),
5799 max_vertex_accessed,
5800 primcount);
[email protected]b1122982010-05-17 23:04:245801}
5802
[email protected]c13e1da62011-09-09 21:48:305803bool GLES2DecoderImpl::SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:435804 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
[email protected]c13e1da62011-09-09 21:48:305805 DCHECK(simulated);
5806 *simulated = false;
5807
[email protected]876f6fee2010-08-02 23:10:325808 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:305809 return true;
[email protected]876f6fee2010-08-02 23:10:325810
[email protected]ac77603c72013-03-08 13:52:065811 const VertexAttrib* attrib =
[email protected]ed9f9cd2013-02-27 21:12:355812 state_.vertex_attrib_manager->GetVertexAttrib(0);
[email protected]b1122982010-05-17 23:04:245813 // If it's enabled or it's not used then we don't need to do anything.
[email protected]e259eb412012-10-13 05:47:245814 bool attrib_0_used =
5815 state_.current_program->GetAttribInfoByLocation(0) != NULL;
[email protected]ac77603c72013-03-08 13:52:065816 if (attrib->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:305817 return true;
[email protected]b1122982010-05-17 23:04:245818 }
5819
[email protected]b1122982010-05-17 23:04:245820 // Make a buffer with a single repeated vec4 value enough to
5821 // simulate the constant value that is supposed to be here.
5822 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:305823 GLuint num_vertices = max_vertex_accessed + 1;
[email protected]3aad1a32012-09-07 20:54:475824 uint32 size_needed = 0;
[email protected]c13e1da62011-09-09 21:48:305825
5826 if (num_vertices == 0 ||
[email protected]3aad1a32012-09-07 20:54:475827 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
[email protected]c13e1da62011-09-09 21:48:305828 size_needed > 0x7FFFFFFFU) {
[email protected]ab09b612013-03-11 22:11:515829 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305830 return false;
5831 }
5832
[email protected]ab09b612013-03-11 22:11:515833 LOCAL_PERFORMANCE_WARNING(
[email protected]0f8afe82012-05-14 23:43:015834 "Attribute 0 is disabled. This has signficant performance penalty");
5835
[email protected]ab09b612013-03-11 22:11:515836 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
[email protected]c13e1da62011-09-09 21:48:305837 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5838
[email protected]8f0b86c2f2012-04-10 05:48:285839 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5840 if (new_buffer) {
[email protected]fc753442011-02-04 19:49:495841 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305842 GLenum error = glGetError();
5843 if (error != GL_NO_ERROR) {
[email protected]ab09b612013-03-11 22:11:515844 LOCAL_SET_GL_ERROR(
5845 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305846 return false;
5847 }
[email protected]fc753442011-02-04 19:49:495848 }
[email protected]af6380962012-11-29 23:24:135849
5850 const Vec4& value = state_.attrib_values[0];
[email protected]8f0b86c2f2012-04-10 05:48:285851 if (new_buffer ||
5852 (attrib_0_used &&
5853 (!attrib_0_buffer_matches_value_ ||
[email protected]af6380962012-11-29 23:24:135854 (value.v[0] != attrib_0_value_.v[0] ||
5855 value.v[1] != attrib_0_value_.v[1] ||
5856 value.v[2] != attrib_0_value_.v[2] ||
5857 value.v[3] != attrib_0_value_.v[3])))) {
5858 std::vector<Vec4> temp(num_vertices, value);
[email protected]fc753442011-02-04 19:49:495859 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5860 attrib_0_buffer_matches_value_ = true;
[email protected]af6380962012-11-29 23:24:135861 attrib_0_value_ = value;
[email protected]b1122982010-05-17 23:04:245862 attrib_0_size_ = size_needed;
5863 }
5864
5865 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5866
[email protected]ac77603c72013-03-08 13:52:065867 if (attrib->divisor())
[email protected]c6aef902012-02-14 03:31:425868 glVertexAttribDivisorANGLE(0, 0);
5869
[email protected]c13e1da62011-09-09 21:48:305870 *simulated = true;
[email protected]b1122982010-05-17 23:04:245871 return true;
[email protected]b1122982010-05-17 23:04:245872}
5873
[email protected]ac77603c72013-03-08 13:52:065874void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
5875 const VertexAttrib* attrib =
5876 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
5877 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
5878 Buffer* buffer = attrib->buffer();
[email protected]b10492f2013-03-08 05:24:075879 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
[email protected]b1122982010-05-17 23:04:245880 glVertexAttribPointer(
[email protected]ac77603c72013-03-08 13:52:065881 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
5882 attrib->gl_stride(), ptr);
5883 if (attrib->divisor())
5884 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
[email protected]e259eb412012-10-13 05:47:245885 glBindBuffer(
5886 GL_ARRAY_BUFFER,
[email protected]7cd76fd2013-06-02 21:11:115887 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
5888 : 0);
[email protected]43410e92012-04-20 17:06:285889
[email protected]265f8992012-07-20 01:03:145890 // Never touch vertex attribute 0's state (in particular, never
5891 // disable it) when running on desktop GL because it will never be
5892 // re-enabled.
[email protected]ac77603c72013-03-08 13:52:065893 if (attrib_index != 0 ||
[email protected]265f8992012-07-20 01:03:145894 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]ac77603c72013-03-08 13:52:065895 if (attrib->enabled()) {
5896 glEnableVertexAttribArray(attrib_index);
[email protected]265f8992012-07-20 01:03:145897 } else {
[email protected]ac77603c72013-03-08 13:52:065898 glDisableVertexAttribArray(attrib_index);
[email protected]265f8992012-07-20 01:03:145899 }
[email protected]43410e92012-04-20 17:06:285900 }
[email protected]b1122982010-05-17 23:04:245901}
[email protected]07f54fcc2009-12-22 02:46:305902
[email protected]8fbedc02010-11-18 18:43:405903bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:435904 const char* function_name,
[email protected]c6aef902012-02-14 03:31:425905 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405906 DCHECK(simulated);
5907 *simulated = false;
5908 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5909 return true;
5910
[email protected]e259eb412012-10-13 05:47:245911 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405912 return true;
5913 }
5914
[email protected]ab09b612013-03-11 22:11:515915 LOCAL_PERFORMANCE_WARNING(
[email protected]0f8afe82012-05-14 23:43:015916 "GL_FIXED attributes have a signficant performance penalty");
5917
[email protected]8fbedc02010-11-18 18:43:405918 // NOTE: we could be smart and try to check if a buffer is used
5919 // twice in 2 different attribs, find the overlapping parts and therefore
5920 // duplicate the minimum amount of data but this whole code path is not meant
5921 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5922 // tests so we just add to the buffer attrib used.
5923
[email protected]c13e1da62011-09-09 21:48:305924 GLuint elements_needed = 0;
[email protected]ac77603c72013-03-08 13:52:065925 const VertexAttribManager::VertexAttribList& enabled_attribs =
5926 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
5927 for (VertexAttribManager::VertexAttribList::const_iterator it =
5928 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
5929 const VertexAttrib* attrib = *it;
[email protected]ed9f9cd2013-02-27 21:12:355930 const Program::VertexAttrib* attrib_info =
[email protected]ac77603c72013-03-08 13:52:065931 state_.current_program->GetAttribInfoByLocation(attrib->index());
5932 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
5933 max_vertex_accessed);
[email protected]c6aef902012-02-14 03:31:425934 GLuint num_vertices = max_accessed + 1;
5935 if (num_vertices == 0) {
[email protected]ab09b612013-03-11 22:11:515936 LOCAL_SET_GL_ERROR(
5937 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:425938 return false;
5939 }
[email protected]8fbedc02010-11-18 18:43:405940 if (attrib_info &&
[email protected]ac77603c72013-03-08 13:52:065941 attrib->CanAccess(max_accessed) &&
5942 attrib->type() == GL_FIXED) {
[email protected]3aad1a32012-09-07 20:54:475943 uint32 elements_used = 0;
[email protected]ac77603c72013-03-08 13:52:065944 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
[email protected]3aad1a32012-09-07 20:54:475945 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
[email protected]ab09b612013-03-11 22:11:515946 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:435947 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:405948 return false;
5949 }
5950 }
5951 }
5952
[email protected]3aad1a32012-09-07 20:54:475953 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
5954 uint32 size_needed = 0;
5955 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
[email protected]c13e1da62011-09-09 21:48:305956 size_needed > 0x7FFFFFFFU) {
[email protected]ab09b612013-03-11 22:11:515957 LOCAL_SET_GL_ERROR(
5958 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:405959 return false;
5960 }
5961
[email protected]ab09b612013-03-11 22:11:515962 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
[email protected]8fbedc02010-11-18 18:43:405963
5964 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305965 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405966 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305967 GLenum error = glGetError();
5968 if (error != GL_NO_ERROR) {
[email protected]ab09b612013-03-11 22:11:515969 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:435970 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]c13e1da62011-09-09 21:48:305971 return false;
5972 }
[email protected]8fbedc02010-11-18 18:43:405973 }
5974
5975 // Copy the elements and convert to float
5976 GLintptr offset = 0;
[email protected]ac77603c72013-03-08 13:52:065977 for (VertexAttribManager::VertexAttribList::const_iterator it =
5978 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
5979 const VertexAttrib* attrib = *it;
[email protected]ed9f9cd2013-02-27 21:12:355980 const Program::VertexAttrib* attrib_info =
[email protected]ac77603c72013-03-08 13:52:065981 state_.current_program->GetAttribInfoByLocation(attrib->index());
5982 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
[email protected]c6aef902012-02-14 03:31:425983 max_vertex_accessed);
5984 GLuint num_vertices = max_accessed + 1;
5985 if (num_vertices == 0) {
[email protected]ab09b612013-03-11 22:11:515986 LOCAL_SET_GL_ERROR(
5987 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:425988 return false;
5989 }
[email protected]8fbedc02010-11-18 18:43:405990 if (attrib_info &&
[email protected]ac77603c72013-03-08 13:52:065991 attrib->CanAccess(max_accessed) &&
5992 attrib->type() == GL_FIXED) {
5993 int num_elements = attrib->size() * kSizeOfFloat;
[email protected]8fbedc02010-11-18 18:43:405994 int size = num_elements * num_vertices;
[email protected]40d90a22013-04-09 03:39:555995 scoped_ptr<float[]> data(new float[size]);
[email protected]8fbedc02010-11-18 18:43:405996 const int32* src = reinterpret_cast<const int32 *>(
[email protected]ac77603c72013-03-08 13:52:065997 attrib->buffer()->GetRange(attrib->offset(), size));
[email protected]8fbedc02010-11-18 18:43:405998 const int32* end = src + num_elements;
5999 float* dst = data.get();
6000 while (src != end) {
6001 *dst++ = static_cast<float>(*src++) / 65536.0f;
6002 }
6003 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6004 glVertexAttribPointer(
[email protected]ac77603c72013-03-08 13:52:066005 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
[email protected]8fbedc02010-11-18 18:43:406006 reinterpret_cast<GLvoid*>(offset));
6007 offset += size;
6008 }
6009 }
6010 *simulated = true;
6011 return true;
6012}
6013
6014void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6015 // There's no need to call glVertexAttribPointer because we shadow all the
6016 // settings and passing GL_FIXED to it will not work.
[email protected]e259eb412012-10-13 05:47:246017 glBindBuffer(
6018 GL_ARRAY_BUFFER,
[email protected]7cd76fd2013-06-02 21:11:116019 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6020 : 0);
[email protected]8fbedc02010-11-18 18:43:406021}
6022
[email protected]ad84a3a2012-06-08 21:42:436023error::Error GLES2DecoderImpl::DoDrawArrays(
6024 const char* function_name,
6025 bool instanced,
6026 GLenum mode,
6027 GLint first,
6028 GLsizei count,
6029 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:086030 if (ShouldDeferDraws())
6031 return error::kDeferCommandUntilLater;
[email protected]38d139d2011-07-14 00:38:436032 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ab09b612013-03-11 22:11:516033 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
[email protected]38d139d2011-07-14 00:38:436034 return error::kNoError;
6035 }
6036 if (count < 0) {
[email protected]ab09b612013-03-11 22:11:516037 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]38d139d2011-07-14 00:38:436038 return error::kNoError;
6039 }
[email protected]c6aef902012-02-14 03:31:426040 if (primcount < 0) {
[email protected]ab09b612013-03-11 22:11:516041 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:426042 return error::kNoError;
6043 }
[email protected]ad84a3a2012-06-08 21:42:436044 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]38d139d2011-07-14 00:38:436045 return error::kNoError;
6046 }
6047 // We have to check this here because the prototype for glDrawArrays
6048 // is GLint not GLsizei.
6049 if (first < 0) {
[email protected]ab09b612013-03-11 22:11:516050 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
[email protected]38d139d2011-07-14 00:38:436051 return error::kNoError;
6052 }
6053
[email protected]c6aef902012-02-14 03:31:426054 if (count == 0 || (instanced && primcount == 0)) {
[email protected]ab09b612013-03-11 22:11:516055 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
[email protected]38d139d2011-07-14 00:38:436056 return error::kNoError;
6057 }
6058
6059 GLuint max_vertex_accessed = first + count - 1;
[email protected]ad84a3a2012-06-08 21:42:436060 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:206061 if (!ClearUnclearedTextures()) {
[email protected]ab09b612013-03-11 22:11:516062 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:206063 return error::kNoError;
6064 }
[email protected]c13e1da62011-09-09 21:48:306065 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:436066 if (!SimulateAttrib0(
6067 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:306068 return error::kNoError;
6069 }
[email protected]38d139d2011-07-14 00:38:436070 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:436071 if (SimulateFixedAttribs(
6072 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6073 primcount)) {
[email protected]38d139d2011-07-14 00:38:436074 bool textures_set = SetBlackTextureForNonRenderableTextures();
6075 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:426076 if (!instanced) {
6077 glDrawArrays(mode, first, count);
6078 } else {
6079 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6080 }
[email protected]22e3f552012-03-13 01:54:196081 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:436082 if (textures_set) {
6083 RestoreStateForNonRenderableTextures();
6084 }
6085 if (simulated_fixed_attribs) {
6086 RestoreStateForSimulatedFixedAttribs();
6087 }
6088 }
6089 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:286090 RestoreStateForAttrib(0);
[email protected]38d139d2011-07-14 00:38:436091 }
[email protected]38d139d2011-07-14 00:38:436092 }
6093 return error::kNoError;
6094}
6095
[email protected]c6aef902012-02-14 03:31:426096error::Error GLES2DecoderImpl::HandleDrawArrays(
[email protected]ed9f9cd2013-02-27 21:12:356097 uint32 immediate_data_size, const cmds::DrawArrays& c) {
[email protected]ad84a3a2012-06-08 21:42:436098 return DoDrawArrays("glDrawArrays",
6099 false,
[email protected]c6aef902012-02-14 03:31:426100 static_cast<GLenum>(c.mode),
6101 static_cast<GLint>(c.first),
6102 static_cast<GLsizei>(c.count),
6103 0);
6104}
6105
6106error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356107 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156108 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516109 LOCAL_SET_GL_ERROR(
6110 GL_INVALID_OPERATION,
6111 "glDrawArraysInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426112 return error::kNoError;
6113 }
[email protected]ad84a3a2012-06-08 21:42:436114 return DoDrawArrays("glDrawArraysIntancedANGLE",
6115 true,
[email protected]c6aef902012-02-14 03:31:426116 static_cast<GLenum>(c.mode),
6117 static_cast<GLint>(c.first),
6118 static_cast<GLsizei>(c.count),
6119 static_cast<GLsizei>(c.primcount));
6120}
6121
[email protected]ad84a3a2012-06-08 21:42:436122error::Error GLES2DecoderImpl::DoDrawElements(
6123 const char* function_name,
6124 bool instanced,
6125 GLenum mode,
6126 GLsizei count,
6127 GLenum type,
6128 int32 offset,
6129 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:086130 if (ShouldDeferDraws())
6131 return error::kDeferCommandUntilLater;
[email protected]e259eb412012-10-13 05:47:246132 if (!state_.vertex_attrib_manager->element_array_buffer()) {
[email protected]ab09b612013-03-11 22:11:516133 LOCAL_SET_GL_ERROR(
6134 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
[email protected]8eee29c2010-04-29 03:38:296135 return error::kNoError;
6136 }
6137
[email protected]8eee29c2010-04-29 03:38:296138 if (count < 0) {
[email protected]ab09b612013-03-11 22:11:516139 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]8eee29c2010-04-29 03:38:296140 return error::kNoError;
6141 }
6142 if (offset < 0) {
[email protected]ab09b612013-03-11 22:11:516143 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296144 return error::kNoError;
6145 }
[email protected]9438b012010-06-15 22:55:056146 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ab09b612013-03-11 22:11:516147 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
[email protected]8eee29c2010-04-29 03:38:296148 return error::kNoError;
6149 }
[email protected]9438b012010-06-15 22:55:056150 if (!validators_->index_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:516151 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
[email protected]8eee29c2010-04-29 03:38:296152 return error::kNoError;
6153 }
[email protected]c6aef902012-02-14 03:31:426154 if (primcount < 0) {
[email protected]ab09b612013-03-11 22:11:516155 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:426156 return error::kNoError;
6157 }
[email protected]8eee29c2010-04-29 03:38:296158
[email protected]ad84a3a2012-06-08 21:42:436159 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]3a03a8f2011-03-19 00:51:276160 return error::kNoError;
6161 }
6162
[email protected]c6aef902012-02-14 03:31:426163 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:316164 return error::kNoError;
6165 }
6166
[email protected]8eee29c2010-04-29 03:38:296167 GLuint max_vertex_accessed;
[email protected]17cfbe0e2013-03-07 01:26:086168 Buffer* element_array_buffer =
6169 state_.vertex_attrib_manager->element_array_buffer();
6170
6171 if (!element_array_buffer->GetMaxValueForRange(
6172 offset, count, type, &max_vertex_accessed)) {
[email protected]ab09b612013-03-11 22:11:516173 LOCAL_SET_GL_ERROR(
6174 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
[email protected]8eee29c2010-04-29 03:38:296175 return error::kNoError;
6176 }
6177
[email protected]ad84a3a2012-06-08 21:42:436178 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:206179 if (!ClearUnclearedTextures()) {
[email protected]ab09b612013-03-11 22:11:516180 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:206181 return error::kNoError;
6182 }
[email protected]c13e1da62011-09-09 21:48:306183 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:436184 if (!SimulateAttrib0(
6185 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:306186 return error::kNoError;
6187 }
[email protected]8fbedc02010-11-18 18:43:406188 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:436189 if (SimulateFixedAttribs(
6190 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6191 primcount)) {
[email protected]8fbedc02010-11-18 18:43:406192 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:466193 ApplyDirtyState();
[email protected]17cfbe0e2013-03-07 01:26:086194 // TODO(gman): Refactor to hide these details in BufferManager or
6195 // VertexAttribManager.
[email protected]8fbedc02010-11-18 18:43:406196 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]17cfbe0e2013-03-07 01:26:086197 bool used_client_side_array = false;
6198 if (element_array_buffer->IsClientSideArray()) {
6199 used_client_side_array = true;
6200 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6201 indices = element_array_buffer->GetRange(offset, 0);
6202 }
6203
[email protected]c6aef902012-02-14 03:31:426204 if (!instanced) {
6205 glDrawElements(mode, count, type, indices);
6206 } else {
6207 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6208 }
[email protected]17cfbe0e2013-03-07 01:26:086209
6210 if (used_client_side_array) {
6211 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6212 element_array_buffer->service_id());
6213 }
6214
[email protected]22e3f552012-03-13 01:54:196215 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:406216 if (textures_set) {
6217 RestoreStateForNonRenderableTextures();
6218 }
6219 if (simulated_fixed_attribs) {
6220 RestoreStateForSimulatedFixedAttribs();
6221 }
[email protected]ba3176a2009-12-16 18:19:466222 }
[email protected]b1122982010-05-17 23:04:246223 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:286224 RestoreStateForAttrib(0);
[email protected]b1122982010-05-17 23:04:246225 }
[email protected]96449d2c2009-11-25 00:01:326226 }
[email protected]f7a64ee2010-02-01 22:24:146227 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326228}
6229
[email protected]c6aef902012-02-14 03:31:426230error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]ed9f9cd2013-02-27 21:12:356231 uint32 immediate_data_size, const cmds::DrawElements& c) {
[email protected]ad84a3a2012-06-08 21:42:436232 return DoDrawElements("glDrawElements",
6233 false,
[email protected]c6aef902012-02-14 03:31:426234 static_cast<GLenum>(c.mode),
6235 static_cast<GLsizei>(c.count),
6236 static_cast<GLenum>(c.type),
6237 static_cast<int32>(c.index_offset),
6238 0);
6239}
6240
6241error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356242 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156243 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516244 LOCAL_SET_GL_ERROR(
6245 GL_INVALID_OPERATION,
6246 "glDrawElementsInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426247 return error::kNoError;
6248 }
[email protected]ad84a3a2012-06-08 21:42:436249 return DoDrawElements("glDrawElementsInstancedANGLE",
6250 true,
[email protected]c6aef902012-02-14 03:31:426251 static_cast<GLenum>(c.mode),
6252 static_cast<GLsizei>(c.count),
6253 static_cast<GLenum>(c.type),
6254 static_cast<int32>(c.index_offset),
6255 static_cast<GLsizei>(c.primcount));
6256}
6257
[email protected]269200b12010-11-18 22:53:066258GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:236259 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6260 GLuint max_vertex_accessed = 0;
[email protected]b10492f2013-03-08 05:24:076261 Buffer* buffer = GetBuffer(buffer_id);
6262 if (!buffer) {
[email protected]ae51d192010-04-27 00:48:036263 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]ab09b612013-03-11 22:11:516264 LOCAL_SET_GL_ERROR(
6265 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
[email protected]29a9eb52010-04-13 09:04:236266 } else {
[email protected]b10492f2013-03-08 05:24:076267 if (!buffer->GetMaxValueForRange(
6268 offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:036269 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]ab09b612013-03-11 22:11:516270 LOCAL_SET_GL_ERROR(
[email protected]269200b12010-11-18 22:53:066271 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436272 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:236273 }
6274 }
6275 return max_vertex_accessed;
6276}
6277
[email protected]96449d2c2009-11-25 00:01:326278// Calls glShaderSource for the various versions of the ShaderSource command.
6279// Assumes that data / data_size points to a piece of memory that is in range
6280// of whatever context it came from (shared memory, immediate memory, bucket
6281// memory.)
[email protected]45bf5152010-02-12 00:11:316282error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:036283 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:576284 std::string str(data, data + data_size);
[email protected]df37b9932013-03-08 05:21:426285 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6286 if (!shader) {
[email protected]45bf5152010-02-12 00:11:316287 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326288 }
[email protected]45bf5152010-02-12 00:11:316289 // Note: We don't actually call glShaderSource here. We wait until
6290 // the call to glCompileShader.
[email protected]df37b9932013-03-08 05:21:426291 shader->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:146292 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326293}
6294
[email protected]f7a64ee2010-02-01 22:24:146295error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]ed9f9cd2013-02-27 21:12:356296 uint32 immediate_data_size, const cmds::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:326297 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:316298 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:326299 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:466300 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146301 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:326302 }
[email protected]ae51d192010-04-27 00:48:036303 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:326304}
6305
[email protected]f7a64ee2010-02-01 22:24:146306error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]ed9f9cd2013-02-27 21:12:356307 uint32 immediate_data_size, const cmds::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:326308 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:316309 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:306310 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466311 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146312 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:326313 }
[email protected]ae51d192010-04-27 00:48:036314 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:316315}
6316
[email protected]558847a2010-03-24 07:02:546317error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
[email protected]ed9f9cd2013-02-27 21:12:356318 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:546319 Bucket* bucket = GetBucket(c.data_bucket_id);
6320 if (!bucket || bucket->size() == 0) {
6321 return error::kInvalidArguments;
6322 }
6323 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:036324 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:546325 bucket->size() - 1);
6326}
6327
[email protected]ae51d192010-04-27 00:48:036328void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]43ed3a72012-05-30 22:55:386329 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]df37b9932013-03-08 05:21:426330 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6331 if (!shader) {
[email protected]45bf5152010-02-12 00:11:316332 return;
6333 }
[email protected]f57bb282010-11-12 00:51:346334 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:186335 if (use_shader_translator_) {
[email protected]df37b9932013-03-08 05:21:426336 translator = shader->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:456337 vertex_translator_.get() : fragment_translator_.get();
[email protected]de17df392010-04-23 21:09:416338 }
[email protected]de17df392010-04-23 21:09:416339
[email protected]7cd76fd2013-06-02 21:11:116340 program_manager()->DoCompileShader(shader, translator, feature_info_.get());
[email protected]45bf5152010-02-12 00:11:316341};
6342
[email protected]ddd968b82010-03-02 00:44:296343void GLES2DecoderImpl::DoGetShaderiv(
[email protected]df37b9932013-03-08 05:21:426344 GLuint shader_id, GLenum pname, GLint* params) {
6345 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6346 if (!shader) {
[email protected]ddd968b82010-03-02 00:44:296347 return;
6348 }
[email protected]8f1ccdac2010-05-19 21:01:486349 switch (pname) {
6350 case GL_SHADER_SOURCE_LENGTH:
[email protected]df37b9932013-03-08 05:21:426351 *params = shader->source() ? shader->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:486352 return;
6353 case GL_COMPILE_STATUS:
[email protected]df37b9932013-03-08 05:21:426354 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
[email protected]e5186162010-06-14 18:54:416355 return;
[email protected]8f1ccdac2010-05-19 21:01:486356 case GL_INFO_LOG_LENGTH:
[email protected]df37b9932013-03-08 05:21:426357 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:416358 return;
[email protected]d6a53e42011-10-05 00:09:366359 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
[email protected]df37b9932013-03-08 05:21:426360 ForceCompileShaderIfPending(shader);
6361 *params = shader->translated_source() ?
6362 shader->translated_source()->size() + 1 : 0;
[email protected]d6a53e42011-10-05 00:09:366363 return;
[email protected]8f1ccdac2010-05-19 21:01:486364 default:
6365 break;
[email protected]ddd968b82010-03-02 00:44:296366 }
[email protected]df37b9932013-03-08 05:21:426367 glGetShaderiv(shader->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:296368}
6369
[email protected]ae51d192010-04-27 00:48:036370error::Error GLES2DecoderImpl::HandleGetShaderSource(
[email protected]ed9f9cd2013-02-27 21:12:356371 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
[email protected]df37b9932013-03-08 05:21:426372 GLuint shader_id = c.shader;
[email protected]ae51d192010-04-27 00:48:036373 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6374 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426375 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6376 if (!shader || !shader->source()) {
[email protected]8eee29c2010-04-29 03:38:296377 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:296378 return error::kNoError;
6379 }
[email protected]df37b9932013-03-08 05:21:426380 bucket->SetFromString(shader->source()->c_str());
[email protected]ae51d192010-04-27 00:48:036381 return error::kNoError;
6382}
6383
[email protected]d6a53e42011-10-05 00:09:366384error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6385 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:356386 const cmds::GetTranslatedShaderSourceANGLE& c) {
[email protected]df37b9932013-03-08 05:21:426387 GLuint shader_id = c.shader;
[email protected]d6a53e42011-10-05 00:09:366388 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6389 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426390 Shader* shader = GetShaderInfoNotProgram(
6391 shader_id, "glTranslatedGetShaderSourceANGLE");
6392 if (!shader) {
[email protected]d6a53e42011-10-05 00:09:366393 bucket->SetSize(0);
6394 return error::kNoError;
6395 }
[email protected]df37b9932013-03-08 05:21:426396 ForceCompileShaderIfPending(shader);
[email protected]d6a53e42011-10-05 00:09:366397
[email protected]df37b9932013-03-08 05:21:426398 bucket->SetFromString(shader->translated_source() ?
6399 shader->translated_source()->c_str() : NULL);
[email protected]d6a53e42011-10-05 00:09:366400 return error::kNoError;
6401}
6402
[email protected]ae51d192010-04-27 00:48:036403error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
[email protected]ed9f9cd2013-02-27 21:12:356404 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
[email protected]df37b9932013-03-08 05:21:426405 GLuint program_id = c.program;
[email protected]6b8cf1a2010-05-06 16:13:586406 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6407 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426408 Program* program = GetProgramInfoNotShader(
6409 program_id, "glGetProgramInfoLog");
6410 if (!program || !program->log_info()) {
[email protected]9a14ae612011-08-08 17:51:466411 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:036412 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:316413 }
[email protected]df37b9932013-03-08 05:21:426414 bucket->SetFromString(program->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:036415 return error::kNoError;
6416}
6417
6418error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
[email protected]ed9f9cd2013-02-27 21:12:356419 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
[email protected]df37b9932013-03-08 05:21:426420 GLuint shader_id = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:586421 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6422 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426423 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6424 if (!shader || !shader->log_info()) {
[email protected]9a14ae612011-08-08 17:51:466425 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:036426 return error::kNoError;
6427 }
[email protected]df37b9932013-03-08 05:21:426428 bucket->SetFromString(shader->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:036429 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326430}
6431
[email protected]d058bca2012-11-26 10:27:266432bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6433 return state_.GetEnabled(cap);
6434}
6435
[email protected]1958e0e2010-04-22 05:17:156436bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]16ccec12013-02-28 03:40:216437 const Buffer* buffer = GetBuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106438 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156439}
6440
6441bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:356442 const Framebuffer* framebuffer =
6443 GetFramebuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106444 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156445}
6446
6447bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:366448 // IsProgram is true for programs as soon as they are created, until they are
6449 // deleted and no longer in use.
[email protected]ed9f9cd2013-02-27 21:12:356450 const Program* program = GetProgram(client_id);
[email protected]a0b78dc2011-11-11 10:43:106451 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156452}
6453
6454bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:356455 const Renderbuffer* renderbuffer =
6456 GetRenderbuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106457 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156458}
6459
6460bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:366461 // IsShader is true for shaders as soon as they are created, until they
6462 // are deleted and not attached to any programs.
[email protected]ed9f9cd2013-02-27 21:12:356463 const Shader* shader = GetShader(client_id);
[email protected]a0b78dc2011-11-11 10:43:106464 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156465}
6466
6467bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]370eaf12013-05-18 09:19:496468 const TextureRef* texture_ref = GetTexture(client_id);
6469 return texture_ref && texture_ref->texture()->IsValid();
[email protected]ae51d192010-04-27 00:48:036470}
6471
6472void GLES2DecoderImpl::DoAttachShader(
6473 GLuint program_client_id, GLint shader_client_id) {
[email protected]df37b9932013-03-08 05:21:426474 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586475 program_client_id, "glAttachShader");
[email protected]df37b9932013-03-08 05:21:426476 if (!program) {
[email protected]ae51d192010-04-27 00:48:036477 return;
[email protected]1958e0e2010-04-22 05:17:156478 }
[email protected]df37b9932013-03-08 05:21:426479 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6480 if (!shader) {
[email protected]ae51d192010-04-27 00:48:036481 return;
6482 }
[email protected]df37b9932013-03-08 05:21:426483 if (!program->AttachShader(shader_manager(), shader)) {
[email protected]ab09b612013-03-11 22:11:516484 LOCAL_SET_GL_ERROR(
6485 GL_INVALID_OPERATION,
6486 "glAttachShader",
6487 "can not attach more than one shader of the same type.");
[email protected]fb96c8e2010-08-12 04:10:316488 return;
6489 }
[email protected]df37b9932013-03-08 05:21:426490 glAttachShader(program->service_id(), shader->service_id());
[email protected]ae51d192010-04-27 00:48:036491}
6492
6493void GLES2DecoderImpl::DoDetachShader(
6494 GLuint program_client_id, GLint shader_client_id) {
[email protected]df37b9932013-03-08 05:21:426495 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586496 program_client_id, "glDetachShader");
[email protected]df37b9932013-03-08 05:21:426497 if (!program) {
[email protected]ae51d192010-04-27 00:48:036498 return;
6499 }
[email protected]df37b9932013-03-08 05:21:426500 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6501 if (!shader) {
[email protected]ae51d192010-04-27 00:48:036502 return;
6503 }
[email protected]df37b9932013-03-08 05:21:426504 if (!program->DetachShader(shader_manager(), shader)) {
[email protected]ab09b612013-03-11 22:11:516505 LOCAL_SET_GL_ERROR(
6506 GL_INVALID_OPERATION,
6507 "glDetachShader", "shader not attached to program");
[email protected]9a0ccd42011-03-16 23:58:226508 return;
6509 }
[email protected]df37b9932013-03-08 05:21:426510 glDetachShader(program->service_id(), shader->service_id());
[email protected]ae51d192010-04-27 00:48:036511}
6512
6513void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]df37b9932013-03-08 05:21:426514 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586515 program_client_id, "glValidateProgram");
[email protected]df37b9932013-03-08 05:21:426516 if (!program) {
[email protected]ae51d192010-04-27 00:48:036517 return;
6518 }
[email protected]df37b9932013-03-08 05:21:426519 program->Validate();
[email protected]1958e0e2010-04-22 05:17:156520}
6521
[email protected]ac77603c72013-03-08 13:52:066522void GLES2DecoderImpl::GetVertexAttribHelper(
6523 const VertexAttrib* attrib, GLenum pname, GLint* params) {
[email protected]b1122982010-05-17 23:04:246524 switch (pname) {
6525 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
[email protected]ac77603c72013-03-08 13:52:066526 Buffer* buffer = attrib->buffer();
[email protected]b1122982010-05-17 23:04:246527 if (buffer && !buffer->IsDeleted()) {
6528 GLuint client_id;
6529 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6530 *params = client_id;
6531 }
6532 break;
6533 }
6534 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
[email protected]ac77603c72013-03-08 13:52:066535 *params = attrib->enabled();
[email protected]b1122982010-05-17 23:04:246536 break;
6537 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
[email protected]ac77603c72013-03-08 13:52:066538 *params = attrib->size();
[email protected]b1122982010-05-17 23:04:246539 break;
6540 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
[email protected]ac77603c72013-03-08 13:52:066541 *params = attrib->gl_stride();
[email protected]b1122982010-05-17 23:04:246542 break;
6543 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
[email protected]ac77603c72013-03-08 13:52:066544 *params = attrib->type();
[email protected]b1122982010-05-17 23:04:246545 break;
6546 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
[email protected]ac77603c72013-03-08 13:52:066547 *params = attrib->normalized();
[email protected]b1122982010-05-17 23:04:246548 break;
[email protected]c6aef902012-02-14 03:31:426549 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
[email protected]ac77603c72013-03-08 13:52:066550 *params = attrib->divisor();
[email protected]c6aef902012-02-14 03:31:426551 break;
[email protected]ac77603c72013-03-08 13:52:066552 default:
6553 NOTREACHED();
6554 break;
6555 }
6556}
6557
6558void GLES2DecoderImpl::DoGetVertexAttribfv(
6559 GLuint index, GLenum pname, GLfloat* params) {
6560 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6561 if (!attrib) {
[email protected]ab09b612013-03-11 22:11:516562 LOCAL_SET_GL_ERROR(
6563 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
[email protected]ac77603c72013-03-08 13:52:066564 return;
6565 }
6566 switch (pname) {
6567 case GL_CURRENT_VERTEX_ATTRIB: {
6568 const Vec4& value = state_.attrib_values[index];
6569 params[0] = value.v[0];
6570 params[1] = value.v[1];
6571 params[2] = value.v[2];
6572 params[3] = value.v[3];
6573 break;
6574 }
6575 default: {
6576 GLint value = 0;
6577 GetVertexAttribHelper(attrib, pname, &value);
6578 *params = static_cast<GLfloat>(value);
6579 break;
6580 }
6581 }
6582}
6583
6584void GLES2DecoderImpl::DoGetVertexAttribiv(
6585 GLuint index, GLenum pname, GLint* params) {
6586 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6587 if (!attrib) {
[email protected]ab09b612013-03-11 22:11:516588 LOCAL_SET_GL_ERROR(
6589 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
[email protected]ac77603c72013-03-08 13:52:066590 return;
6591 }
6592 switch (pname) {
[email protected]af6380962012-11-29 23:24:136593 case GL_CURRENT_VERTEX_ATTRIB: {
6594 const Vec4& value = state_.attrib_values[index];
6595 params[0] = static_cast<GLint>(value.v[0]);
6596 params[1] = static_cast<GLint>(value.v[1]);
6597 params[2] = static_cast<GLint>(value.v[2]);
6598 params[3] = static_cast<GLint>(value.v[3]);
[email protected]b1122982010-05-17 23:04:246599 break;
[email protected]af6380962012-11-29 23:24:136600 }
[email protected]b1122982010-05-17 23:04:246601 default:
[email protected]ac77603c72013-03-08 13:52:066602 GetVertexAttribHelper(attrib, pname, params);
[email protected]b1122982010-05-17 23:04:246603 break;
6604 }
6605}
6606
[email protected]af6380962012-11-29 23:24:136607bool GLES2DecoderImpl::SetVertexAttribValue(
6608 const char* function_name, GLuint index, const GLfloat* value) {
6609 if (index >= state_.attrib_values.size()) {
[email protected]ab09b612013-03-11 22:11:516610 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
[email protected]af6380962012-11-29 23:24:136611 return false;
[email protected]b1122982010-05-17 23:04:246612 }
[email protected]af6380962012-11-29 23:24:136613 Vec4& v = state_.attrib_values[index];
6614 v.v[0] = value[0];
6615 v.v[1] = value[1];
6616 v.v[2] = value[2];
6617 v.v[3] = value[3];
6618 return true;
6619}
6620
6621void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6622 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6623 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6624 glVertexAttrib1f(index, v0);
6625 }
[email protected]b1122982010-05-17 23:04:246626}
6627
6628void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
[email protected]af6380962012-11-29 23:24:136629 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6630 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6631 glVertexAttrib2f(index, v0, v1);
[email protected]b1122982010-05-17 23:04:246632 }
[email protected]b1122982010-05-17 23:04:246633}
6634
6635void GLES2DecoderImpl::DoVertexAttrib3f(
6636 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
[email protected]af6380962012-11-29 23:24:136637 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6638 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6639 glVertexAttrib3f(index, v0, v1, v2);
[email protected]b1122982010-05-17 23:04:246640 }
[email protected]b1122982010-05-17 23:04:246641}
6642
6643void GLES2DecoderImpl::DoVertexAttrib4f(
6644 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
[email protected]af6380962012-11-29 23:24:136645 GLfloat v[4] = { v0, v1, v2, v3, };
6646 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6647 glVertexAttrib4f(index, v0, v1, v2, v3);
[email protected]b1122982010-05-17 23:04:246648 }
[email protected]b1122982010-05-17 23:04:246649}
6650
6651void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136652 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6653 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6654 glVertexAttrib1fv(index, v);
[email protected]b1122982010-05-17 23:04:246655 }
[email protected]b1122982010-05-17 23:04:246656}
6657
6658void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136659 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6660 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6661 glVertexAttrib2fv(index, v);
[email protected]b1122982010-05-17 23:04:246662 }
[email protected]b1122982010-05-17 23:04:246663}
6664
6665void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136666 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
6667 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
6668 glVertexAttrib3fv(index, v);
[email protected]b1122982010-05-17 23:04:246669 }
[email protected]b1122982010-05-17 23:04:246670}
6671
6672void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136673 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
6674 glVertexAttrib4fv(index, v);
[email protected]b1122982010-05-17 23:04:246675 }
[email protected]b1122982010-05-17 23:04:246676}
6677
[email protected]f7a64ee2010-02-01 22:24:146678error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]ed9f9cd2013-02-27 21:12:356679 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
[email protected]944b62f32012-09-27 02:20:466680
[email protected]7cd76fd2013-06-02 21:11:116681 if (!state_.bound_array_buffer.get() ||
6682 state_.bound_array_buffer->IsDeleted()) {
6683 if (state_.vertex_attrib_manager.get() ==
6684 default_vertex_attrib_manager_.get()) {
[email protected]ab09b612013-03-11 22:11:516685 LOCAL_SET_GL_ERROR(
6686 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
[email protected]944b62f32012-09-27 02:20:466687 return error::kNoError;
6688 } else if (c.offset != 0) {
[email protected]ab09b612013-03-11 22:11:516689 LOCAL_SET_GL_ERROR(
6690 GL_INVALID_VALUE,
6691 "glVertexAttribPointer", "client side arrays are not allowed");
[email protected]944b62f32012-09-27 02:20:466692 return error::kNoError;
6693 }
[email protected]96449d2c2009-11-25 00:01:326694 }
[email protected]8eee29c2010-04-29 03:38:296695
6696 GLuint indx = c.indx;
6697 GLint size = c.size;
6698 GLenum type = c.type;
6699 GLboolean normalized = c.normalized;
6700 GLsizei stride = c.stride;
6701 GLsizei offset = c.offset;
6702 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:056703 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:516704 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
[email protected]8eee29c2010-04-29 03:38:296705 return error::kNoError;
6706 }
[email protected]9438b012010-06-15 22:55:056707 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ab09b612013-03-11 22:11:516708 LOCAL_SET_GL_ERROR(
6709 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
[email protected]8eee29c2010-04-29 03:38:296710 return error::kNoError;
6711 }
6712 if (indx >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:516713 LOCAL_SET_GL_ERROR(
6714 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
[email protected]8eee29c2010-04-29 03:38:296715 return error::kNoError;
6716 }
6717 if (stride < 0) {
[email protected]ab09b612013-03-11 22:11:516718 LOCAL_SET_GL_ERROR(
6719 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
[email protected]8eee29c2010-04-29 03:38:296720 return error::kNoError;
6721 }
6722 if (stride > 255) {
[email protected]ab09b612013-03-11 22:11:516723 LOCAL_SET_GL_ERROR(
6724 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
[email protected]8eee29c2010-04-29 03:38:296725 return error::kNoError;
6726 }
6727 if (offset < 0) {
[email protected]ab09b612013-03-11 22:11:516728 LOCAL_SET_GL_ERROR(
6729 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296730 return error::kNoError;
6731 }
6732 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:316733 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:296734 if (offset % component_size > 0) {
[email protected]ab09b612013-03-11 22:11:516735 LOCAL_SET_GL_ERROR(
6736 GL_INVALID_OPERATION,
6737 "glVertexAttribPointer", "offset not valid for type");
[email protected]ff81c192011-01-07 23:04:316738 return error::kNoError;
6739 }
6740 if (stride % component_size > 0) {
[email protected]ab09b612013-03-11 22:11:516741 LOCAL_SET_GL_ERROR(
6742 GL_INVALID_OPERATION,
6743 "glVertexAttribPointer", "stride not valid for type");
[email protected]8eee29c2010-04-29 03:38:296744 return error::kNoError;
6745 }
[email protected]7cd76fd2013-06-02 21:11:116746 state_.vertex_attrib_manager
6747 ->SetAttribInfo(indx,
6748 state_.bound_array_buffer.get(),
6749 size,
6750 type,
6751 normalized,
6752 stride,
6753 stride != 0 ? stride : component_size * size,
6754 offset);
[email protected]8fbedc02010-11-18 18:43:406755 if (type != GL_FIXED) {
6756 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6757 }
[email protected]f7a64ee2010-02-01 22:24:146758 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326759}
6760
[email protected]43410e92012-04-20 17:06:286761void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6762 GLsizei height) {
[email protected]e259eb412012-10-13 05:47:246763 state_.viewport_x = x;
6764 state_.viewport_y = y;
[email protected]1868a342012-11-07 15:56:026765 state_.viewport_width = std::min(width, viewport_max_width_);
6766 state_.viewport_height = std::min(height, viewport_max_height_);
[email protected]43410e92012-04-20 17:06:286767 glViewport(x, y, width, height);
6768}
6769
[email protected]c6aef902012-02-14 03:31:426770error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356771 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156772 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516773 LOCAL_SET_GL_ERROR(
6774 GL_INVALID_OPERATION,
6775 "glVertexAttribDivisorANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426776 }
6777 GLuint index = c.index;
6778 GLuint divisor = c.divisor;
6779 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:516780 LOCAL_SET_GL_ERROR(
6781 GL_INVALID_VALUE,
6782 "glVertexAttribDivisorANGLE", "index out of range");
[email protected]c6aef902012-02-14 03:31:426783 return error::kNoError;
6784 }
6785
[email protected]e259eb412012-10-13 05:47:246786 state_.vertex_attrib_manager->SetDivisor(
[email protected]c6aef902012-02-14 03:31:426787 index,
6788 divisor);
6789 glVertexAttribDivisorANGLE(index, divisor);
6790 return error::kNoError;
6791}
6792
[email protected]f7a64ee2010-02-01 22:24:146793error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]ed9f9cd2013-02-27 21:12:356794 uint32 immediate_data_size, const cmds::ReadPixels& c) {
[email protected]09e17272012-11-30 10:30:446795 if (ShouldDeferReads())
6796 return error::kDeferCommandUntilLater;
[email protected]612d2f82009-12-08 20:49:316797 GLint x = c.x;
6798 GLint y = c.y;
6799 GLsizei width = c.width;
6800 GLsizei height = c.height;
6801 GLenum format = c.format;
6802 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:566803 if (width < 0 || height < 0) {
[email protected]ab09b612013-03-11 22:11:516804 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
[email protected]57f223832010-03-19 01:57:566805 return error::kNoError;
6806 }
[email protected]ed9f9cd2013-02-27 21:12:356807 typedef cmds::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:186808 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:346809 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246810 width, height, format, type, state_.pack_alignment, &pixels_size,
6811 NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:186812 return error::kOutOfBounds;
6813 }
[email protected]612d2f82009-12-08 20:49:316814 void* pixels = GetSharedMemoryAs<void*>(
6815 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]de43f082013-04-02 01:16:106816 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146817 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466818 }
[email protected]de43f082013-04-02 01:16:106819 Result* result = NULL;
6820 if (c.result_shm_id != 0) {
6821 result = GetSharedMemoryAs<Result*>(
6822 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6823 if (!result) {
6824 return error::kOutOfBounds;
6825 }
6826 }
[email protected]a51788e2010-02-24 21:54:256827
[email protected]9438b012010-06-15 22:55:056828 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:516829 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
[email protected]8eee29c2010-04-29 03:38:296830 return error::kNoError;
6831 }
[email protected]9438b012010-06-15 22:55:056832 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:516833 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
[email protected]d2cf0a2d2010-02-25 21:36:126834 return error::kNoError;
6835 }
[email protected]57f223832010-03-19 01:57:566836 if (width == 0 || height == 0) {
6837 return error::kNoError;
6838 }
6839
[email protected]57f223832010-03-19 01:57:566840 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:306841 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:566842
[email protected]3aad1a32012-09-07 20:54:476843 int32 max_x;
6844 int32 max_y;
6845 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
[email protected]ab09b612013-03-11 22:11:516846 LOCAL_SET_GL_ERROR(
6847 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:146848 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:316849 }
[email protected]57f223832010-03-19 01:57:566850
[email protected]0d6bfdc2011-11-02 01:32:206851 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6852 return error::kNoError;
6853 }
6854
[email protected]ab09b612013-03-11 22:11:516855 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
[email protected]a0b78dc2011-11-11 10:43:106856
6857 ScopedResolvedFrameBufferBinder binder(this, false, true);
6858
[email protected]d37231fa2010-04-09 21:16:026859 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:566860 // The user requested an out of range area. Get the results 1 line
6861 // at a time.
6862 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346863 uint32 unpadded_row_size;
6864 uint32 padded_row_size;
6865 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246866 width, 2, format, type, state_.pack_alignment, &temp_size,
[email protected]3458a64a2012-04-10 17:39:346867 &unpadded_row_size, &padded_row_size)) {
[email protected]ab09b612013-03-11 22:11:516868 LOCAL_SET_GL_ERROR(
6869 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:566870 return error::kNoError;
6871 }
6872
6873 GLint dest_x_offset = std::max(-x, 0);
6874 uint32 dest_row_offset;
[email protected]3458a64a2012-04-10 17:39:346875 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246876 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
6877 NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:516878 LOCAL_SET_GL_ERROR(
6879 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:566880 return error::kNoError;
6881 }
6882
6883 // Copy each row into the larger dest rect.
6884 int8* dst = static_cast<int8*>(pixels);
6885 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:026886 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:566887 GLint read_width = read_end_x - read_x;
6888 for (GLint yy = 0; yy < height; ++yy) {
6889 GLint ry = y + yy;
6890
6891 // Clear the row.
6892 memset(dst, 0, unpadded_row_size);
6893
6894 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:026895 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:566896 glReadPixels(
6897 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6898 }
6899 dst += padded_row_size;
6900 }
6901 } else {
[email protected]57f223832010-03-19 01:57:566902 glReadPixels(x, y, width, height, format, type, pixels);
6903 }
[email protected]ab09b612013-03-11 22:11:516904 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
[email protected]a51788e2010-02-24 21:54:256905 if (error == GL_NO_ERROR) {
[email protected]de43f082013-04-02 01:16:106906 if (result != NULL) {
6907 *result = true;
6908 }
[email protected]744329c2013-07-12 00:54:256909
6910 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6911 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6912 if ((channels_exist & 0x0008) == 0 &&
6913 workarounds().clear_alpha_in_readpixels) {
6914 // Set the alpha to 255 because some drivers are buggy in this regard.
6915 uint32 temp_size;
6916
6917 uint32 unpadded_row_size;
6918 uint32 padded_row_size;
6919 if (!GLES2Util::ComputeImageDataSizes(
6920 width, 2, format, type, state_.pack_alignment, &temp_size,
6921 &unpadded_row_size, &padded_row_size)) {
6922 LOCAL_SET_GL_ERROR(
6923 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
6924 return error::kNoError;
6925 }
6926 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6927 // of this implementation.
6928 if (type != GL_UNSIGNED_BYTE) {
6929 LOCAL_SET_GL_ERROR(
6930 GL_INVALID_OPERATION, "glReadPixels",
6931 "unsupported readPixel format");
6932 return error::kNoError;
6933 }
6934 switch (format) {
6935 case GL_RGBA:
6936 case GL_BGRA_EXT:
6937 case GL_ALPHA: {
6938 int offset = (format == GL_ALPHA) ? 0 : 3;
6939 int step = (format == GL_ALPHA) ? 1 : 4;
6940 uint8* dst = static_cast<uint8*>(pixels) + offset;
6941 for (GLint yy = 0; yy < height; ++yy) {
6942 uint8* end = dst + unpadded_row_size;
6943 for (uint8* d = dst; d < end; d += step) {
6944 *d = 255;
6945 }
6946 dst += padded_row_size;
6947 }
6948 break;
6949 }
6950 default:
6951 break;
6952 }
6953 }
[email protected]a51788e2010-02-24 21:54:256954 }
[email protected]4848b9f82011-03-10 18:37:566955
[email protected]f7a64ee2010-02-01 22:24:146956 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326957}
6958
[email protected]f7a64ee2010-02-01 22:24:146959error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]ed9f9cd2013-02-27 21:12:356960 uint32 immediate_data_size, const cmds::PixelStorei& c) {
[email protected]b9849abf2009-11-25 19:13:196961 GLenum pname = c.pname;
6962 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:056963 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]ab09b612013-03-11 22:11:516964 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
[email protected]d2cf0a2d2010-02-25 21:36:126965 return error::kNoError;
6966 }
[email protected]222471d2011-11-30 18:06:396967 switch (pname) {
6968 case GL_PACK_ALIGNMENT:
6969 case GL_UNPACK_ALIGNMENT:
6970 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]ab09b612013-03-11 22:11:516971 LOCAL_SET_GL_ERROR(
6972 GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE");
[email protected]222471d2011-11-30 18:06:396973 return error::kNoError;
6974 }
[email protected]164d6d52012-05-05 00:55:036975 break;
[email protected]0a1e9ad2012-05-04 21:13:036976 case GL_UNPACK_FLIP_Y_CHROMIUM:
6977 unpack_flip_y_ = (param != 0);
6978 return error::kNoError;
6979 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
6980 unpack_premultiply_alpha_ = (param != 0);
6981 return error::kNoError;
[email protected]6c75c712012-06-19 15:43:176982 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
6983 unpack_unpremultiply_alpha_ = (param != 0);
6984 return error::kNoError;
[email protected]222471d2011-11-30 18:06:396985 default:
6986 break;
[email protected]b9849abf2009-11-25 19:13:196987 }
6988 glPixelStorei(pname, param);
6989 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:436990 case GL_PACK_ALIGNMENT:
[email protected]e259eb412012-10-13 05:47:246991 state_.pack_alignment = param;
[email protected]ad84a3a2012-06-08 21:42:436992 break;
6993 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
[email protected]88a61bf2012-10-27 13:00:426994 state_.pack_reverse_row_order = (param != 0);
[email protected]ad84a3a2012-06-08 21:42:436995 break;
6996 case GL_UNPACK_ALIGNMENT:
[email protected]e259eb412012-10-13 05:47:246997 state_.unpack_alignment = param;
[email protected]ad84a3a2012-06-08 21:42:436998 break;
6999 default:
7000 // Validation should have prevented us from getting here.
7001 NOTREACHED();
7002 break;
[email protected]b9849abf2009-11-25 19:13:197003 }
[email protected]f7a64ee2010-02-01 22:24:147004 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197005}
7006
[email protected]1c75a3702011-11-11 14:15:287007error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:357008 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
[email protected]43ed3a72012-05-30 22:55:387009 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]6f5fac9d12012-06-26 21:02:457010 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]ab09b612013-03-11 22:11:517011 LOCAL_SET_GL_ERROR(
7012 GL_INVALID_OPERATION,
7013 "glPostSubBufferCHROMIUM", "command not supported by surface");
[email protected]1c75a3702011-11-11 14:15:287014 return error::kNoError;
7015 }
[email protected]7794d512012-04-17 20:36:497016 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
[email protected]1c75a3702011-11-11 14:15:287017 return error::kNoError;
[email protected]7794d512012-04-17 20:36:497018 } else {
7019 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
[email protected]1c75a3702011-11-11 14:15:287020 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:497021 }
[email protected]1c75a3702011-11-11 14:15:287022}
7023
[email protected]558847a2010-03-24 07:02:547024error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7025 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7026 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:577027 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ab09b612013-03-11 22:11:517028 LOCAL_SET_GL_ERROR(
7029 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:577030 return error::kNoError;
7031 }
[email protected]df37b9932013-03-08 05:21:427032 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:587033 client_id, "glGetAttribLocation");
[email protected]df37b9932013-03-08 05:21:427034 if (!program) {
[email protected]f7a64ee2010-02-01 22:24:147035 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197036 }
[email protected]df37b9932013-03-08 05:21:427037 if (!program->IsValid()) {
[email protected]ab09b612013-03-11 22:11:517038 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437039 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:257040 return error::kNoError;
7041 }
[email protected]b9849abf2009-11-25 19:13:197042 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:547043 location_shm_id, location_shm_offset, sizeof(GLint));
7044 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:147045 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197046 }
[email protected]558847a2010-03-24 07:02:547047 // Require the client to init this incase the context is lost and we are no
7048 // longer executing commands.
7049 if (*location != -1) {
7050 return error::kGenericError;
7051 }
[email protected]df37b9932013-03-08 05:21:427052 *location = program->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:147053 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197054}
7055
[email protected]558847a2010-03-24 07:02:547056error::Error GLES2DecoderImpl::HandleGetAttribLocation(
[email protected]ed9f9cd2013-02-27 21:12:357057 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
[email protected]558847a2010-03-24 07:02:547058 uint32 name_size = c.data_size;
7059 const char* name = GetSharedMemoryAs<const char*>(
7060 c.name_shm_id, c.name_shm_offset, name_size);
7061 if (!name) {
7062 return error::kOutOfBounds;
7063 }
7064 String name_str(name, name_size);
7065 return GetAttribLocationHelper(
7066 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7067}
7068
[email protected]f7a64ee2010-02-01 22:24:147069error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357070 uint32 immediate_data_size, const cmds::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:547071 uint32 name_size = c.data_size;
7072 const char* name = GetImmediateDataAs<const char*>(
7073 c, name_size, immediate_data_size);
7074 if (!name) {
7075 return error::kOutOfBounds;
7076 }
7077 String name_str(name, name_size);
7078 return GetAttribLocationHelper(
7079 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7080}
7081
7082error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:357083 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
[email protected]558847a2010-03-24 07:02:547084 Bucket* bucket = GetBucket(c.name_bucket_id);
7085 if (!bucket) {
7086 return error::kInvalidArguments;
7087 }
7088 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:187089 if (!bucket->GetAsString(&name_str)) {
7090 return error::kInvalidArguments;
7091 }
[email protected]558847a2010-03-24 07:02:547092 return GetAttribLocationHelper(
7093 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7094}
7095
7096error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7097 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7098 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:577099 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ab09b612013-03-11 22:11:517100 LOCAL_SET_GL_ERROR(
7101 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:577102 return error::kNoError;
7103 }
[email protected]df37b9932013-03-08 05:21:427104 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:587105 client_id, "glUniformLocation");
[email protected]df37b9932013-03-08 05:21:427106 if (!program) {
[email protected]f7a64ee2010-02-01 22:24:147107 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197108 }
[email protected]df37b9932013-03-08 05:21:427109 if (!program->IsValid()) {
[email protected]ab09b612013-03-11 22:11:517110 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437111 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:257112 return error::kNoError;
7113 }
[email protected]b9849abf2009-11-25 19:13:197114 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:547115 location_shm_id, location_shm_offset, sizeof(GLint));
7116 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:147117 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197118 }
[email protected]558847a2010-03-24 07:02:547119 // Require the client to init this incase the context is lost an we are no
7120 // longer executing commands.
7121 if (*location != -1) {
7122 return error::kGenericError;
7123 }
[email protected]df37b9932013-03-08 05:21:427124 *location = program->GetUniformFakeLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:147125 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197126}
7127
[email protected]f7a64ee2010-02-01 22:24:147128error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]ed9f9cd2013-02-27 21:12:357129 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:197130 uint32 name_size = c.data_size;
7131 const char* name = GetSharedMemoryAs<const char*>(
7132 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:547133 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:147134 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197135 }
7136 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:547137 return GetUniformLocationHelper(
7138 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:197139}
7140
[email protected]f7a64ee2010-02-01 22:24:147141error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357142 uint32 immediate_data_size, const cmds::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:197143 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:307144 const char* name = GetImmediateDataAs<const char*>(
7145 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:547146 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:147147 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197148 }
7149 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:547150 return GetUniformLocationHelper(
7151 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7152}
7153
7154error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:357155 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
[email protected]558847a2010-03-24 07:02:547156 Bucket* bucket = GetBucket(c.name_bucket_id);
7157 if (!bucket) {
7158 return error::kInvalidArguments;
7159 }
7160 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:187161 if (!bucket->GetAsString(&name_str)) {
7162 return error::kInvalidArguments;
7163 }
[email protected]558847a2010-03-24 07:02:547164 return GetUniformLocationHelper(
7165 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:197166}
7167
[email protected]ddd968b82010-03-02 00:44:297168error::Error GLES2DecoderImpl::HandleGetString(
[email protected]ed9f9cd2013-02-27 21:12:357169 uint32 immediate_data_size, const cmds::GetString& c) {
[email protected]ddd968b82010-03-02 00:44:297170 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:057171 if (!validators_->string_type.IsValid(name)) {
[email protected]ab09b612013-03-11 22:11:517172 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
[email protected]ddd968b82010-03-02 00:44:297173 return error::kNoError;
7174 }
[email protected]1958e0e2010-04-22 05:17:157175 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
7176 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:047177 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:157178 switch (name) {
7179 case GL_VERSION:
7180 str = "OpenGL ES 2.0 Chromium";
7181 break;
7182 case GL_SHADING_LANGUAGE_VERSION:
7183 str = "OpenGL ES GLSL ES 1.0 Chromium";
7184 break;
[email protected]32939602012-05-09 06:25:167185 case GL_RENDERER:
7186 str = "Chromium";
7187 break;
7188 case GL_VENDOR:
7189 str = "Chromium";
7190 break;
[email protected]1958e0e2010-04-22 05:17:157191 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:047192 {
[email protected]70dc60932013-06-04 03:33:497193 // For WebGL contexts, strip out the OES derivatives and
7194 // EXT frag depth extensions if they have not been enabled.
7195 if (force_webgl_glsl_validation_) {
[email protected]f0d74742011-10-03 16:31:047196 extensions = feature_info_->extensions();
[email protected]70dc60932013-06-04 03:33:497197 if (!derivatives_explicitly_enabled_) {
7198 size_t offset = extensions.find(kOESDerivativeExtension);
7199 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097200 extensions.replace(offset, arraysize(kOESDerivativeExtension),
[email protected]70dc60932013-06-04 03:33:497201 std::string());
7202 }
7203 }
7204 if (!frag_depth_explicitly_enabled_) {
7205 size_t offset = extensions.find(kEXTFragDepthExtension);
7206 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097207 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
[email protected]70dc60932013-06-04 03:33:497208 std::string());
7209 }
[email protected]f0d74742011-10-03 16:31:047210 }
[email protected]aff39ac82013-06-08 04:53:137211 if (!draw_buffers_explicitly_enabled_) {
7212 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7213 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097214 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
[email protected]aff39ac82013-06-08 04:53:137215 std::string());
7216 }
7217 }
[email protected]f0d74742011-10-03 16:31:047218 } else {
[email protected]6f5fac9d12012-06-26 21:02:457219 extensions = feature_info_->extensions().c_str();
[email protected]f0d74742011-10-03 16:31:047220 }
[email protected]6f5fac9d12012-06-26 21:02:457221 std::string surface_extensions = surface_->GetExtensions();
7222 if (!surface_extensions.empty())
7223 extensions += " " + surface_extensions;
7224 str = extensions.c_str();
[email protected]f0d74742011-10-03 16:31:047225 }
[email protected]1958e0e2010-04-22 05:17:157226 break;
7227 default:
7228 str = gl_str;
7229 break;
7230 }
[email protected]ddd968b82010-03-02 00:44:297231 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:157232 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:297233 return error::kNoError;
7234}
7235
[email protected]0c86dbf2010-03-05 08:14:117236void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:157237 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:057238 if (!validators_->buffer_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:517239 LOCAL_SET_GL_ERROR_INVALID_ENUM("glBufferData", target, "target");
[email protected]8eee29c2010-04-29 03:38:297240 return;
7241 }
[email protected]9438b012010-06-15 22:55:057242 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]ab09b612013-03-11 22:11:517243 LOCAL_SET_GL_ERROR_INVALID_ENUM("glBufferData", usage, "usage");
[email protected]0c86dbf2010-03-05 08:14:117244 return;
[email protected]3b6ec202010-03-05 05:16:237245 }
7246 if (size < 0) {
[email protected]ab09b612013-03-11 22:11:517247 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glBufferData", "size < 0");
[email protected]037896bd2010-04-21 19:07:287248 return;
[email protected]3b6ec202010-03-05 05:16:237249 }
[email protected]17cfbe0e2013-03-07 01:26:087250 Buffer* buffer = GetBufferInfoForTarget(target);
7251 if (!buffer) {
[email protected]ab09b612013-03-11 22:11:517252 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glBufferData", "unknown buffer");
[email protected]037896bd2010-04-21 19:07:287253 return;
[email protected]3b6ec202010-03-05 05:16:237254 }
[email protected]7989c9e2013-01-23 06:39:267255
7256 if (!EnsureGPUMemoryAvailable(size)) {
[email protected]ab09b612013-03-11 22:11:517257 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glBufferData", "out of memory");
[email protected]7989c9e2013-01-23 06:39:267258 return;
7259 }
7260
[email protected]d3eba342013-04-18 21:11:507261 buffer_manager()->DoBufferData(GetErrorState(), buffer, size, usage, data);
[email protected]0c86dbf2010-03-05 08:14:117262}
7263
7264error::Error GLES2DecoderImpl::HandleBufferData(
[email protected]ed9f9cd2013-02-27 21:12:357265 uint32 immediate_data_size, const cmds::BufferData& c) {
[email protected]0c86dbf2010-03-05 08:14:117266 GLenum target = static_cast<GLenum>(c.target);
7267 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7268 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7269 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7270 GLenum usage = static_cast<GLenum>(c.usage);
7271 const void* data = NULL;
7272 if (data_shm_id != 0 || data_shm_offset != 0) {
7273 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7274 if (!data) {
7275 return error::kOutOfBounds;
7276 }
7277 }
7278 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:147279 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197280}
7281
[email protected]f7a64ee2010-02-01 22:24:147282error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357283 uint32 immediate_data_size, const cmds::BufferDataImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:197284 GLenum target = static_cast<GLenum>(c.target);
7285 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:307286 const void* data = GetImmediateDataAs<const void*>(
7287 c, size, immediate_data_size);
7288 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147289 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:307290 }
[email protected]b9849abf2009-11-25 19:13:197291 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:117292 DoBufferData(target, size, data, usage);
7293 return error::kNoError;
7294}
7295
7296void GLES2DecoderImpl::DoBufferSubData(
7297 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]17cfbe0e2013-03-07 01:26:087298 Buffer* buffer = GetBufferInfoForTarget(target);
7299 if (!buffer) {
[email protected]ab09b612013-03-11 22:11:517300 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glBufferSubData", "unknown buffer");
[email protected]037896bd2010-04-21 19:07:287301 return;
[email protected]a93bb842010-02-16 23:03:477302 }
[email protected]17cfbe0e2013-03-07 01:26:087303
[email protected]d3eba342013-04-18 21:11:507304 buffer_manager()->DoBufferSubData(GetErrorState(), buffer, offset, size,
7305 data);
[email protected]b9849abf2009-11-25 19:13:197306}
7307
[email protected]0d6bfdc2011-11-02 01:32:207308bool GLES2DecoderImpl::ClearLevel(
7309 unsigned service_id,
7310 unsigned bind_target,
7311 unsigned target,
7312 int level,
7313 unsigned format,
7314 unsigned type,
7315 int width,
[email protected]4502e6492011-12-14 19:39:157316 int height,
7317 bool is_texture_immutable) {
[email protected]81375742012-06-08 00:04:007318 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7319 if (IsAngle() && (channels & GLES2Util::kDepth) != 0) {
7320 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7321 // on depth formats.
7322 GLuint fb = 0;
7323 glGenFramebuffersEXT(1, &fb);
7324 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7325
7326 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7327 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7328 GL_DEPTH_ATTACHMENT;
7329
7330 glFramebufferTexture2DEXT(
7331 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7332 // ANGLE promises a depth only attachment ok.
7333 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7334 GL_FRAMEBUFFER_COMPLETE) {
7335 return false;
7336 }
7337 glClearStencil(0);
7338 glStencilMask(-1);
7339 glClearDepth(1.0f);
7340 glDepthMask(true);
7341 glDisable(GL_SCISSOR_TEST);
7342 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7343
7344 RestoreClearState();
7345
7346 glDeleteFramebuffersEXT(1, &fb);
[email protected]ed9f9cd2013-02-27 21:12:357347 Framebuffer* framebuffer =
[email protected]81375742012-06-08 00:04:007348 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7349 GLuint fb_service_id =
7350 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7351 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7352 return true;
7353 }
7354
[email protected]45d15a62012-04-18 14:33:177355 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7356
7357 uint32 size;
7358 uint32 padded_row_size;
[email protected]3458a64a2012-04-10 17:39:347359 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247360 width, height, format, type, state_.unpack_alignment, &size,
[email protected]45d15a62012-04-18 14:33:177361 NULL, &padded_row_size)) {
[email protected]0d6bfdc2011-11-02 01:32:207362 return false;
7363 }
[email protected]45d15a62012-04-18 14:33:177364
[email protected]a5d3dad2012-05-26 04:34:447365 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7366
[email protected]45d15a62012-04-18 14:33:177367 int tile_height;
7368
7369 if (size > kMaxZeroSize) {
7370 if (kMaxZeroSize < padded_row_size) {
7371 // That'd be an awfully large texture.
7372 return false;
7373 }
7374 // We should never have a large total size with a zero row size.
7375 DCHECK_GT(padded_row_size, 0U);
7376 tile_height = kMaxZeroSize / padded_row_size;
7377 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247378 width, tile_height, format, type, state_.unpack_alignment, &size,
7379 NULL, NULL)) {
[email protected]45d15a62012-04-18 14:33:177380 return false;
7381 }
[email protected]4502e6492011-12-14 19:39:157382 } else {
[email protected]45d15a62012-04-18 14:33:177383 tile_height = height;
7384 }
7385
7386 // Assumes the size has already been checked.
[email protected]40d90a22013-04-09 03:39:557387 scoped_ptr<char[]> zero(new char[size]);
[email protected]45d15a62012-04-18 14:33:177388 memset(zero.get(), 0, size);
7389 glBindTexture(bind_target, service_id);
7390
7391 GLint y = 0;
7392 while (y < height) {
7393 GLint h = y + tile_height > height ? height - y : tile_height;
7394 if (is_texture_immutable || h != height) {
7395 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7396 } else {
[email protected]8f1d2aa2013-05-10 23:45:387397 glTexImage2D(
[email protected]45d15a62012-04-18 14:33:177398 target, level, format, width, h, 0, format, type, zero.get());
7399 }
7400 y += tile_height;
[email protected]4502e6492011-12-14 19:39:157401 }
[email protected]370eaf12013-05-18 09:19:497402 TextureRef* texture = GetTextureInfoForTarget(bind_target);
[email protected]02965c22013-03-09 02:40:077403 glBindTexture(bind_target, texture ? texture->service_id() : 0);
[email protected]0d6bfdc2011-11-02 01:32:207404 return true;
7405}
7406
[email protected]ad84a3a2012-06-08 21:42:437407namespace {
7408
7409const int kS3TCBlockWidth = 4;
7410const int kS3TCBlockHeight = 4;
7411const int kS3TCDXT1BlockSize = 8;
7412const int kS3TCDXT3AndDXT5BlockSize = 16;
[email protected]2d3765b2012-10-03 00:31:077413const int kETC1BlockWidth = 4;
7414const int kETC1BlockHeight = 4;
7415const int kETC1BlockSize = 8;
[email protected]ad84a3a2012-06-08 21:42:437416
7417bool IsValidDXTSize(GLint level, GLsizei size) {
[email protected]10b56de2012-07-14 02:09:517418 return (size == 1) ||
7419 (size == 2) || !(size % kS3TCBlockWidth);
[email protected]ad84a3a2012-06-08 21:42:437420}
7421
7422} // anonymous namespace.
7423
7424bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7425 const char* function_name,
7426 GLsizei width, GLsizei height, GLenum format, size_t size) {
7427 unsigned int bytes_required = 0;
7428
7429 switch (format) {
7430 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7431 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7432 int num_blocks_across =
7433 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7434 int num_blocks_down =
7435 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7436 int num_blocks = num_blocks_across * num_blocks_down;
7437 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7438 break;
7439 }
7440 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7441 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7442 int num_blocks_across =
7443 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7444 int num_blocks_down =
7445 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7446 int num_blocks = num_blocks_across * num_blocks_down;
7447 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7448 break;
7449 }
[email protected]2d3765b2012-10-03 00:31:077450 case GL_ETC1_RGB8_OES: {
7451 int num_blocks_across =
7452 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7453 int num_blocks_down =
7454 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7455 int num_blocks = num_blocks_across * num_blocks_down;
7456 bytes_required = num_blocks * kETC1BlockSize;
7457 break;
7458 }
[email protected]ad84a3a2012-06-08 21:42:437459 default:
[email protected]ab09b612013-03-11 22:11:517460 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
[email protected]ad84a3a2012-06-08 21:42:437461 return false;
7462 }
7463
7464 if (size != bytes_required) {
[email protected]ab09b612013-03-11 22:11:517465 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437466 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7467 return false;
7468 }
7469
7470 return true;
7471}
7472
7473bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7474 const char* function_name,
7475 GLint level, GLsizei width, GLsizei height, GLenum format) {
7476 switch (format) {
7477 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7478 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7479 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7480 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7481 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
[email protected]ab09b612013-03-11 22:11:517482 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437483 GL_INVALID_OPERATION, function_name,
7484 "width or height invalid for level");
7485 return false;
7486 }
7487 return true;
7488 }
[email protected]2d3765b2012-10-03 00:31:077489 case GL_ETC1_RGB8_OES:
7490 if (width <= 0 || height <= 0) {
[email protected]ab09b612013-03-11 22:11:517491 LOCAL_SET_GL_ERROR(
[email protected]2d3765b2012-10-03 00:31:077492 GL_INVALID_OPERATION, function_name,
7493 "width or height invalid for level");
7494 return false;
7495 }
7496 return true;
[email protected]ad84a3a2012-06-08 21:42:437497 default:
7498 return false;
7499 }
7500}
7501
7502bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7503 const char* function_name,
7504 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7505 GLsizei width, GLsizei height, GLenum format,
[email protected]ed9f9cd2013-02-27 21:12:357506 Texture* texture) {
[email protected]ad84a3a2012-06-08 21:42:437507 if (xoffset < 0 || yoffset < 0) {
[email protected]ab09b612013-03-11 22:11:517508 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437509 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7510 return false;
7511 }
7512
7513 switch (format) {
7514 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7515 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7516 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7517 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7518 const int kBlockWidth = 4;
7519 const int kBlockHeight = 4;
7520 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
[email protected]ab09b612013-03-11 22:11:517521 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437522 GL_INVALID_OPERATION, function_name,
7523 "xoffset or yoffset not multiple of 4");
7524 return false;
7525 }
7526 GLsizei tex_width = 0;
7527 GLsizei tex_height = 0;
7528 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7529 width - xoffset > tex_width ||
7530 height - yoffset > tex_height) {
[email protected]ab09b612013-03-11 22:11:517531 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437532 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7533 return false;
7534 }
7535 return ValidateCompressedTexDimensions(
7536 function_name, level, width, height, format);
7537 }
[email protected]2d3765b2012-10-03 00:31:077538 case GL_ETC1_RGB8_OES: {
[email protected]ab09b612013-03-11 22:11:517539 LOCAL_SET_GL_ERROR(
[email protected]2d3765b2012-10-03 00:31:077540 GL_INVALID_OPERATION, function_name,
7541 "TexsubImage2d not supported for ECT1_RGB8_OES textures");
7542 return false;
7543 }
[email protected]ad84a3a2012-06-08 21:42:437544 default:
7545 return false;
7546 }
7547}
7548
[email protected]a93bb842010-02-16 23:03:477549error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7550 GLenum target,
7551 GLint level,
7552 GLenum internal_format,
7553 GLsizei width,
7554 GLsizei height,
7555 GLint border,
7556 GLsizei image_size,
7557 const void* data) {
[email protected]a93bb842010-02-16 23:03:477558 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:057559 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:517560 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7561 "glCompressedTexImage2D", target, "target");
[email protected]8eee29c2010-04-29 03:38:297562 return error::kNoError;
7563 }
[email protected]9438b012010-06-15 22:55:057564 if (!validators_->compressed_texture_format.IsValid(
7565 internal_format)) {
[email protected]ab09b612013-03-11 22:11:517566 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:537567 "glCompressedTexImage2D", internal_format, "internal_format");
[email protected]a93bb842010-02-16 23:03:477568 return error::kNoError;
7569 }
[email protected]80eb6b52012-01-19 00:14:417570 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:477571 border != 0) {
[email protected]ab09b612013-03-11 22:11:517572 LOCAL_SET_GL_ERROR(
7573 GL_INVALID_VALUE,
7574 "glCompressedTexImage2D", "dimensions out of range");
[email protected]a93bb842010-02-16 23:03:477575 return error::kNoError;
7576 }
[email protected]370eaf12013-05-18 09:19:497577 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7578 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517579 LOCAL_SET_GL_ERROR(
7580 GL_INVALID_VALUE,
7581 "glCompressedTexImage2D", "unknown texture target");
[email protected]a93bb842010-02-16 23:03:477582 return error::kNoError;
7583 }
[email protected]370eaf12013-05-18 09:19:497584 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:077585 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:517586 LOCAL_SET_GL_ERROR(
7587 GL_INVALID_OPERATION,
7588 "glCompressedTexImage2D", "texture is immutable");
[email protected]ad84a3a2012-06-08 21:42:437589 return error::kNoError;
7590 }
7591
7592 if (!ValidateCompressedTexDimensions(
7593 "glCompressedTexImage2D", level, width, height, internal_format) ||
7594 !ValidateCompressedTexFuncData(
7595 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
[email protected]97dc7cbe2011-12-06 17:26:177596 return error::kNoError;
7597 }
[email protected]968351b2011-12-20 08:26:517598
[email protected]7989c9e2013-01-23 06:39:267599 if (!EnsureGPUMemoryAvailable(image_size)) {
[email protected]ab09b612013-03-11 22:11:517600 LOCAL_SET_GL_ERROR(
7601 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
[email protected]7989c9e2013-01-23 06:39:267602 return error::kNoError;
7603 }
7604
[email protected]02965c22013-03-09 02:40:077605 if (texture->IsAttachedToFramebuffer()) {
[email protected]88a61bf2012-10-27 13:00:427606 clear_state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517607 }
7608
[email protected]40d90a22013-04-09 03:39:557609 scoped_ptr<int8[]> zero;
[email protected]a93bb842010-02-16 23:03:477610 if (!data) {
7611 zero.reset(new int8[image_size]);
7612 memset(zero.get(), 0, image_size);
7613 data = zero.get();
7614 }
[email protected]ab09b612013-03-11 22:11:517615 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
[email protected]a93bb842010-02-16 23:03:477616 glCompressedTexImage2D(
7617 target, level, internal_format, width, height, border, image_size, data);
[email protected]ab09b612013-03-11 22:11:517618 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
[email protected]cadde4a2010-07-31 17:10:437619 if (error == GL_NO_ERROR) {
7620 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:497621 texture_ref, target, level, internal_format,
7622 width, height, 1, border, 0, 0, true);
[email protected]cadde4a2010-07-31 17:10:437623 }
[email protected]a93bb842010-02-16 23:03:477624 return error::kNoError;
7625}
7626
[email protected]f7a64ee2010-02-01 22:24:147627error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]ed9f9cd2013-02-27 21:12:357628 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
[email protected]b9849abf2009-11-25 19:13:197629 GLenum target = static_cast<GLenum>(c.target);
7630 GLint level = static_cast<GLint>(c.level);
7631 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7632 GLsizei width = static_cast<GLsizei>(c.width);
7633 GLsizei height = static_cast<GLsizei>(c.height);
7634 GLint border = static_cast<GLint>(c.border);
7635 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7636 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7637 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7638 const void* data = NULL;
7639 if (data_shm_id != 0 || data_shm_offset != 0) {
7640 data = GetSharedMemoryAs<const void*>(
7641 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:467642 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147643 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197644 }
7645 }
[email protected]a93bb842010-02-16 23:03:477646 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197647 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:197648}
7649
[email protected]f7a64ee2010-02-01 22:24:147650error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357651 uint32 immediate_data_size, const cmds::CompressedTexImage2DImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:197652 GLenum target = static_cast<GLenum>(c.target);
7653 GLint level = static_cast<GLint>(c.level);
7654 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7655 GLsizei width = static_cast<GLsizei>(c.width);
7656 GLsizei height = static_cast<GLsizei>(c.height);
7657 GLint border = static_cast<GLint>(c.border);
7658 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:307659 const void* data = GetImmediateDataAs<const void*>(
7660 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467661 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147662 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467663 }
[email protected]a93bb842010-02-16 23:03:477664 return DoCompressedTexImage2D(
7665 target, level, internal_format, width, height, border, image_size, data);
7666}
7667
[email protected]b6140d02010-05-17 14:47:167668error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
[email protected]ed9f9cd2013-02-27 21:12:357669 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
[email protected]b6140d02010-05-17 14:47:167670 GLenum target = static_cast<GLenum>(c.target);
7671 GLint level = static_cast<GLint>(c.level);
7672 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7673 GLsizei width = static_cast<GLsizei>(c.width);
7674 GLsizei height = static_cast<GLsizei>(c.height);
7675 GLint border = static_cast<GLint>(c.border);
7676 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287677 if (!bucket) {
7678 return error::kInvalidArguments;
7679 }
7680 uint32 data_size = bucket->size();
7681 GLsizei imageSize = data_size;
7682 const void* data = bucket->GetData(0, data_size);
7683 if (!data) {
7684 return error::kInvalidArguments;
7685 }
[email protected]b6140d02010-05-17 14:47:167686 return DoCompressedTexImage2D(
7687 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:287688 imageSize, data);
[email protected]b6140d02010-05-17 14:47:167689}
7690
7691error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7692 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:357693 const cmds::CompressedTexSubImage2DBucket& c) {
[email protected]b6140d02010-05-17 14:47:167694 GLenum target = static_cast<GLenum>(c.target);
7695 GLint level = static_cast<GLint>(c.level);
7696 GLint xoffset = static_cast<GLint>(c.xoffset);
7697 GLint yoffset = static_cast<GLint>(c.yoffset);
7698 GLsizei width = static_cast<GLsizei>(c.width);
7699 GLsizei height = static_cast<GLsizei>(c.height);
7700 GLenum format = static_cast<GLenum>(c.format);
7701 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287702 if (!bucket) {
7703 return error::kInvalidArguments;
7704 }
[email protected]b6140d02010-05-17 14:47:167705 uint32 data_size = bucket->size();
7706 GLsizei imageSize = data_size;
7707 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:287708 if (!data) {
7709 return error::kInvalidArguments;
7710 }
[email protected]9438b012010-06-15 22:55:057711 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:517712 LOCAL_SET_GL_ERROR(
[email protected]f80e6e12012-08-31 00:43:537713 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
[email protected]b6140d02010-05-17 14:47:167714 return error::kNoError;
7715 }
[email protected]9438b012010-06-15 22:55:057716 if (!validators_->compressed_texture_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:517717 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7718 "glCompressedTexSubImage2D", format, "format");
[email protected]9438b012010-06-15 22:55:057719 return error::kNoError;
7720 }
[email protected]b6140d02010-05-17 14:47:167721 if (width < 0) {
[email protected]ab09b612013-03-11 22:11:517722 LOCAL_SET_GL_ERROR(
7723 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
[email protected]b6140d02010-05-17 14:47:167724 return error::kNoError;
7725 }
7726 if (height < 0) {
[email protected]ab09b612013-03-11 22:11:517727 LOCAL_SET_GL_ERROR(
7728 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
[email protected]b6140d02010-05-17 14:47:167729 return error::kNoError;
7730 }
7731 if (imageSize < 0) {
[email protected]ab09b612013-03-11 22:11:517732 LOCAL_SET_GL_ERROR(
7733 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
[email protected]b6140d02010-05-17 14:47:167734 return error::kNoError;
7735 }
[email protected]cadde4a2010-07-31 17:10:437736 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:167737 target, level, xoffset, yoffset, width, height, format, imageSize, data);
7738 return error::kNoError;
7739}
7740
[email protected]81375742012-06-08 00:04:007741bool GLES2DecoderImpl::ValidateTextureParameters(
7742 const char* function_name,
7743 GLenum target, GLenum format, GLenum type, GLint level) {
7744 if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:517745 LOCAL_SET_GL_ERROR(
7746 GL_INVALID_OPERATION, function_name,
7747 (std::string("invalid type ") +
7748 GLES2Util::GetStringEnum(type) + " for format " +
7749 GLES2Util::GetStringEnum(format)).c_str());
[email protected]81375742012-06-08 00:04:007750 return false;
7751 }
7752
7753 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7754 if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
[email protected]ab09b612013-03-11 22:11:517755 LOCAL_SET_GL_ERROR(
7756 GL_INVALID_OPERATION, function_name,
7757 (std::string("invalid type ") +
7758 GLES2Util::GetStringEnum(type) + " for format " +
7759 GLES2Util::GetStringEnum(format)).c_str());
[email protected]81375742012-06-08 00:04:007760 return false;
7761 }
7762 return true;
7763}
7764
[email protected]f598f422012-12-07 08:30:037765bool GLES2DecoderImpl::ValidateTexImage2D(
7766 const char* function_name,
7767 GLenum target,
7768 GLint level,
7769 GLenum internal_format,
7770 GLsizei width,
7771 GLsizei height,
7772 GLint border,
7773 GLenum format,
7774 GLenum type,
7775 const void* pixels,
7776 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:057777 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:517778 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
[email protected]f598f422012-12-07 08:30:037779 return false;
[email protected]8eee29c2010-04-29 03:38:297780 }
[email protected]9438b012010-06-15 22:55:057781 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]ab09b612013-03-11 22:11:517782 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7783 function_name, internal_format, "internal_format");
[email protected]f598f422012-12-07 08:30:037784 return false;
[email protected]8eee29c2010-04-29 03:38:297785 }
[email protected]9438b012010-06-15 22:55:057786 if (!validators_->texture_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:517787 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
[email protected]f598f422012-12-07 08:30:037788 return false;
[email protected]8eee29c2010-04-29 03:38:297789 }
[email protected]9438b012010-06-15 22:55:057790 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:517791 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
[email protected]f598f422012-12-07 08:30:037792 return false;
[email protected]b9849abf2009-11-25 19:13:197793 }
[email protected]7b92c412010-07-20 17:48:257794 if (format != internal_format) {
[email protected]ab09b612013-03-11 22:11:517795 LOCAL_SET_GL_ERROR(
7796 GL_INVALID_OPERATION, function_name, "format != internalFormat");
[email protected]f598f422012-12-07 08:30:037797 return false;
[email protected]7b92c412010-07-20 17:48:257798 }
[email protected]f598f422012-12-07 08:30:037799 if (!ValidateTextureParameters(function_name, target, format, type, level)) {
7800 return false;
[email protected]81375742012-06-08 00:04:007801 }
[email protected]80eb6b52012-01-19 00:14:417802 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:477803 border != 0) {
[email protected]ab09b612013-03-11 22:11:517804 LOCAL_SET_GL_ERROR(
7805 GL_INVALID_VALUE, function_name, "dimensions out of range");
[email protected]f598f422012-12-07 08:30:037806 return false;
[email protected]a93bb842010-02-16 23:03:477807 }
[email protected]81375742012-06-08 00:04:007808 if ((GLES2Util::GetChannelsForFormat(format) &
7809 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && pixels) {
[email protected]ab09b612013-03-11 22:11:517810 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:007811 GL_INVALID_OPERATION,
[email protected]f598f422012-12-07 08:30:037812 function_name, "can not supply data for depth or stencil textures");
7813 return false;
[email protected]81375742012-06-08 00:04:007814 }
[email protected]370eaf12013-05-18 09:19:497815 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7816 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517817 LOCAL_SET_GL_ERROR(
7818 GL_INVALID_OPERATION, function_name, "unknown texture for target");
[email protected]f598f422012-12-07 08:30:037819 return false;
[email protected]a93bb842010-02-16 23:03:477820 }
[email protected]370eaf12013-05-18 09:19:497821 if (texture_ref->texture()->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:517822 LOCAL_SET_GL_ERROR(
7823 GL_INVALID_OPERATION, function_name, "texture is immutable");
[email protected]f598f422012-12-07 08:30:037824 return false;
[email protected]97dc7cbe2011-12-06 17:26:177825 }
[email protected]f598f422012-12-07 08:30:037826 return true;
7827}
[email protected]97dc7cbe2011-12-06 17:26:177828
[email protected]f598f422012-12-07 08:30:037829void GLES2DecoderImpl::DoTexImage2D(
7830 GLenum target,
7831 GLint level,
7832 GLenum internal_format,
7833 GLsizei width,
7834 GLsizei height,
7835 GLint border,
7836 GLenum format,
7837 GLenum type,
7838 const void* pixels,
7839 uint32 pixels_size) {
7840 if (!ValidateTexImage2D("glTexImage2D", target, level, internal_format,
7841 width, height, border, format, type, pixels, pixels_size)) {
7842 return;
7843 }
[email protected]7989c9e2013-01-23 06:39:267844
7845 if (!EnsureGPUMemoryAvailable(pixels_size)) {
[email protected]ab09b612013-03-11 22:11:517846 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory");
[email protected]7989c9e2013-01-23 06:39:267847 return;
7848 }
7849
[email protected]370eaf12013-05-18 09:19:497850 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7851 Texture* texture = texture_ref->texture();
[email protected]0226c112011-07-22 03:25:077852 GLsizei tex_width = 0;
7853 GLsizei tex_height = 0;
7854 GLenum tex_type = 0;
7855 GLenum tex_format = 0;
7856 bool level_is_same =
[email protected]02965c22013-03-09 02:40:077857 texture->GetLevelSize(target, level, &tex_width, &tex_height) &&
7858 texture->GetLevelType(target, level, &tex_type, &tex_format) &&
[email protected]0226c112011-07-22 03:25:077859 width == tex_width && height == tex_height &&
7860 type == tex_type && format == tex_format;
7861
7862 if (level_is_same && !pixels) {
[email protected]02965c22013-03-09 02:40:077863 // Just set the level texture but mark the texture as uncleared.
[email protected]1bed6222011-12-21 11:21:397864 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:497865 texture_ref,
[email protected]1bed6222011-12-21 11:21:397866 target, level, internal_format, width, height, 1, border, format, type,
7867 false);
[email protected]ea72ed222011-08-17 18:58:437868 tex_image_2d_failed_ = false;
[email protected]f598f422012-12-07 08:30:037869 return;
[email protected]0226c112011-07-22 03:25:077870 }
7871
[email protected]02965c22013-03-09 02:40:077872 if (texture->IsAttachedToFramebuffer()) {
[email protected]88a61bf2012-10-27 13:00:427873 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:467874 }
7875
[email protected]1bed6222011-12-21 11:21:397876 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]aa283dc2013-06-14 19:46:037877 {
7878 ScopedTextureUploadTimer timer(this);
7879 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
7880 }
[email protected]370eaf12013-05-18 09:19:497881 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
[email protected]0226c112011-07-22 03:25:077882 tex_image_2d_failed_ = false;
[email protected]f598f422012-12-07 08:30:037883 return;
[email protected]7488d962010-07-16 02:41:587884 }
[email protected]876f6fee2010-08-02 23:10:327885
[email protected]ab09b612013-03-11 22:11:517886 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexImage2D");
[email protected]aa283dc2013-06-14 19:46:037887 {
7888 ScopedTextureUploadTimer timer(this);
7889 glTexImage2D(
7890 target, level, internal_format, width, height, border, format, type,
7891 pixels);
7892 }
[email protected]ab09b612013-03-11 22:11:517893 GLenum error = LOCAL_PEEK_GL_ERROR("glTexImage2D");
[email protected]cadde4a2010-07-31 17:10:437894 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:207895 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:497896 texture_ref,
[email protected]0d6bfdc2011-11-02 01:32:207897 target, level, internal_format, width, height, 1, border, format, type,
7898 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:007899 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:437900 }
[email protected]f598f422012-12-07 08:30:037901 return;
[email protected]b9849abf2009-11-25 19:13:197902}
7903
[email protected]f7a64ee2010-02-01 22:24:147904error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]ed9f9cd2013-02-27 21:12:357905 uint32 immediate_data_size, const cmds::TexImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:387906 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:007907 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:197908 GLenum target = static_cast<GLenum>(c.target);
7909 GLint level = static_cast<GLint>(c.level);
7910 GLint internal_format = static_cast<GLint>(c.internalformat);
7911 GLsizei width = static_cast<GLsizei>(c.width);
7912 GLsizei height = static_cast<GLsizei>(c.height);
7913 GLint border = static_cast<GLint>(c.border);
7914 GLenum format = static_cast<GLenum>(c.format);
7915 GLenum type = static_cast<GLenum>(c.type);
7916 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
7917 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:187918 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:347919 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247920 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
[email protected]3458a64a2012-04-10 17:39:347921 NULL)) {
[email protected]a76b0052010-03-05 00:33:187922 return error::kOutOfBounds;
7923 }
[email protected]b9849abf2009-11-25 19:13:197924 const void* pixels = NULL;
7925 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
7926 pixels = GetSharedMemoryAs<const void*>(
7927 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:467928 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147929 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197930 }
7931 }
[email protected]f598f422012-12-07 08:30:037932
7933 DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197934 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477935 pixels, pixels_size);
[email protected]f598f422012-12-07 08:30:037936 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197937}
7938
[email protected]f7a64ee2010-02-01 22:24:147939error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357940 uint32 immediate_data_size, const cmds::TexImage2DImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:197941 GLenum target = static_cast<GLenum>(c.target);
7942 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:467943 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:197944 GLsizei width = static_cast<GLsizei>(c.width);
7945 GLsizei height = static_cast<GLsizei>(c.height);
7946 GLint border = static_cast<GLint>(c.border);
7947 GLenum format = static_cast<GLenum>(c.format);
7948 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:187949 uint32 size;
[email protected]3458a64a2012-04-10 17:39:347950 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247951 width, height, format, type, state_.unpack_alignment, &size,
7952 NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:187953 return error::kOutOfBounds;
7954 }
[email protected]07f54fcc2009-12-22 02:46:307955 const void* pixels = GetImmediateDataAs<const void*>(
7956 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467957 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147958 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467959 }
[email protected]a93bb842010-02-16 23:03:477960 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:467961 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477962 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:147963 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327964}
7965
[email protected]cadde4a2010-07-31 17:10:437966void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7967 GLenum target,
7968 GLint level,
7969 GLint xoffset,
7970 GLint yoffset,
7971 GLsizei width,
7972 GLsizei height,
7973 GLenum format,
7974 GLsizei image_size,
7975 const void * data) {
[email protected]370eaf12013-05-18 09:19:497976 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7977 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517978 LOCAL_SET_GL_ERROR(
7979 GL_INVALID_OPERATION,
7980 "glCompressedTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437981 return;
7982 }
[email protected]370eaf12013-05-18 09:19:497983 Texture* texture = texture_ref->texture();
[email protected]cadde4a2010-07-31 17:10:437984 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:527985 GLenum internal_format = 0;
[email protected]02965c22013-03-09 02:40:077986 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
[email protected]ab09b612013-03-11 22:11:517987 LOCAL_SET_GL_ERROR(
[email protected]df6cf1ad2011-01-29 01:20:527988 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437989 "glCompressedTexSubImage2D", "level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527990 return;
7991 }
7992 if (internal_format != format) {
[email protected]ab09b612013-03-11 22:11:517993 LOCAL_SET_GL_ERROR(
[email protected]df6cf1ad2011-01-29 01:20:527994 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437995 "glCompressedTexSubImage2D", "format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527996 return;
7997 }
[email protected]02965c22013-03-09 02:40:077998 if (!texture->ValidForTexture(
[email protected]df6cf1ad2011-01-29 01:20:527999 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:518000 LOCAL_SET_GL_ERROR(
8001 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:438002 return;
8003 }
[email protected]ad84a3a2012-06-08 21:42:438004
8005 if (!ValidateCompressedTexFuncData(
8006 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8007 !ValidateCompressedTexSubDimensions(
8008 "glCompressedTexSubImage2D",
[email protected]02965c22013-03-09 02:40:078009 target, level, xoffset, yoffset, width, height, format, texture)) {
[email protected]ad84a3a2012-06-08 21:42:438010 return;
8011 }
8012
8013
[email protected]0d6bfdc2011-11-02 01:32:208014 // Note: There is no need to deal with texture cleared tracking here
8015 // because the validation above means you can only get here if the level
8016 // is already a matching compressed format and in that case
8017 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:438018 glCompressedTexSubImage2D(
8019 target, level, xoffset, yoffset, width, height, format, image_size, data);
8020}
8021
[email protected]6e288612010-12-21 20:45:038022static void Clip(
8023 GLint start, GLint range, GLint sourceRange,
8024 GLint* out_start, GLint* out_range) {
8025 DCHECK(out_start);
8026 DCHECK(out_range);
8027 if (start < 0) {
8028 range += start;
8029 start = 0;
8030 }
8031 GLint end = start + range;
8032 if (end > sourceRange) {
8033 range -= end - sourceRange;
8034 }
8035 *out_start = start;
8036 *out_range = range;
8037}
8038
[email protected]cadde4a2010-07-31 17:10:438039void GLES2DecoderImpl::DoCopyTexImage2D(
[email protected]a5d3dad2012-05-26 04:34:448040 GLenum target,
8041 GLint level,
8042 GLenum internal_format,
8043 GLint x,
8044 GLint y,
8045 GLsizei width,
8046 GLsizei height,
8047 GLint border) {
[email protected]09e17272012-11-30 10:30:448048 DCHECK(!ShouldDeferReads());
[email protected]370eaf12013-05-18 09:19:498049 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8050 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:518051 LOCAL_SET_GL_ERROR(
8052 GL_INVALID_OPERATION,
8053 "glCopyTexImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:438054 return;
8055 }
[email protected]370eaf12013-05-18 09:19:498056 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:078057 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:518058 LOCAL_SET_GL_ERROR(
8059 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:178060 }
[email protected]80eb6b52012-01-19 00:14:418061 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:188062 border != 0) {
[email protected]ab09b612013-03-11 22:11:518063 LOCAL_SET_GL_ERROR(
8064 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
[email protected]f5719fb2010-08-04 18:27:188065 return;
8066 }
[email protected]81375742012-06-08 00:04:008067 if (!ValidateTextureParameters(
8068 "glCopyTexImage2D", target, internal_format, GL_UNSIGNED_BYTE, level)) {
8069 return;
8070 }
[email protected]f5719fb2010-08-04 18:27:188071
[email protected]9edc6b22010-12-23 02:00:268072 // Check we have compatible formats.
8073 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8074 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8075 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8076
8077 if ((channels_needed & channels_exist) != channels_needed) {
[email protected]ab09b612013-03-11 22:11:518078 LOCAL_SET_GL_ERROR(
8079 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:268080 return;
8081 }
8082
[email protected]81375742012-06-08 00:04:008083 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:518084 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:008085 GL_INVALID_OPERATION,
[email protected]7989c9e2013-01-23 06:39:268086 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8087 return;
8088 }
8089
8090 uint32 estimated_size = 0;
8091 if (!GLES2Util::ComputeImageDataSizes(
8092 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8093 &estimated_size, NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:518094 LOCAL_SET_GL_ERROR(
8095 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:268096 return;
8097 }
8098
8099 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:518100 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
[email protected]81375742012-06-08 00:04:008101 return;
8102 }
8103
[email protected]a0b78dc2011-11-11 10:43:108104 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8105 return;
8106 }
8107
[email protected]ab09b612013-03-11 22:11:518108 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
[email protected]de26b3c2011-08-03 21:54:278109 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:038110 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:268111
[email protected]02965c22013-03-09 02:40:078112 if (texture->IsAttachedToFramebuffer()) {
[email protected]88a61bf2012-10-27 13:00:428113 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:468114 }
8115
[email protected]9edc6b22010-12-23 02:00:268116 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:038117 GLint copyX = 0;
8118 GLint copyY = 0;
8119 GLint copyWidth = 0;
8120 GLint copyHeight = 0;
8121 Clip(x, width, size.width(), &copyX, &copyWidth);
8122 Clip(y, height, size.height(), &copyY, &copyHeight);
8123
8124 if (copyX != x ||
8125 copyY != y ||
8126 copyWidth != width ||
8127 copyHeight != height) {
8128 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:208129 if (!ClearLevel(
[email protected]02965c22013-03-09 02:40:078130 texture->service_id(), texture->target(),
[email protected]4502e6492011-12-14 19:39:158131 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
[email protected]02965c22013-03-09 02:40:078132 texture->IsImmutable())) {
[email protected]ab09b612013-03-11 22:11:518133 LOCAL_SET_GL_ERROR(
8134 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
[email protected]6e288612010-12-21 20:45:038135 return;
8136 }
[email protected]6e288612010-12-21 20:45:038137 if (copyHeight > 0 && copyWidth > 0) {
8138 GLint dx = copyX - x;
8139 GLint dy = copyY - y;
8140 GLint destX = dx;
8141 GLint destY = dy;
8142 glCopyTexSubImage2D(target, level,
8143 destX, destY, copyX, copyY,
8144 copyWidth, copyHeight);
8145 }
8146 } else {
8147 glCopyTexImage2D(target, level, internal_format,
8148 copyX, copyY, copyWidth, copyHeight, border);
8149 }
[email protected]ab09b612013-03-11 22:11:518150 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
[email protected]cadde4a2010-07-31 17:10:438151 if (error == GL_NO_ERROR) {
8152 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:498153 texture_ref, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:208154 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:438155 }
8156}
8157
8158void GLES2DecoderImpl::DoCopyTexSubImage2D(
[email protected]a5d3dad2012-05-26 04:34:448159 GLenum target,
8160 GLint level,
8161 GLint xoffset,
8162 GLint yoffset,
8163 GLint x,
8164 GLint y,
8165 GLsizei width,
8166 GLsizei height) {
[email protected]09e17272012-11-30 10:30:448167 DCHECK(!ShouldDeferReads());
[email protected]370eaf12013-05-18 09:19:498168 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8169 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:518170 LOCAL_SET_GL_ERROR(
8171 GL_INVALID_OPERATION,
8172 "glCopyTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:438173 return;
8174 }
[email protected]370eaf12013-05-18 09:19:498175 Texture* texture = texture_ref->texture();
[email protected]cadde4a2010-07-31 17:10:438176 GLenum type = 0;
8177 GLenum format = 0;
[email protected]02965c22013-03-09 02:40:078178 if (!texture->GetLevelType(target, level, &type, &format) ||
8179 !texture->ValidForTexture(
[email protected]cadde4a2010-07-31 17:10:438180 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:518181 LOCAL_SET_GL_ERROR(
8182 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:438183 return;
8184 }
[email protected]85a4ac22013-05-31 01:58:478185 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:518186 LOCAL_SET_GL_ERROR(
8187 GL_INVALID_OPERATION,
8188 "glCopyTexSubImage2D", "async upload pending for texture");
[email protected]32145a92012-12-17 09:01:598189 return;
8190 }
[email protected]9edc6b22010-12-23 02:00:268191
8192 // Check we have compatible formats.
8193 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8194 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8195 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8196
[email protected]2d3765b2012-10-03 00:31:078197 if (!channels_needed ||
8198 (channels_needed & channels_exist) != channels_needed) {
[email protected]ab09b612013-03-11 22:11:518199 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:438200 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:268201 return;
8202 }
8203
[email protected]81375742012-06-08 00:04:008204 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:518205 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:008206 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438207 "glCopySubImage2D", "can not be used with depth or stencil textures");
[email protected]81375742012-06-08 00:04:008208 return;
8209 }
8210
[email protected]a0b78dc2011-11-11 10:43:108211 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8212 return;
8213 }
8214
[email protected]de26b3c2011-08-03 21:54:278215 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:038216 gfx::Size size = GetBoundReadFrameBufferSize();
8217 GLint copyX = 0;
8218 GLint copyY = 0;
8219 GLint copyWidth = 0;
8220 GLint copyHeight = 0;
8221 Clip(x, width, size.width(), &copyX, &copyWidth);
8222 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:208223
[email protected]370eaf12013-05-18 09:19:498224 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
[email protected]ab09b612013-03-11 22:11:518225 LOCAL_SET_GL_ERROR(
8226 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
[email protected]0d6bfdc2011-11-02 01:32:208227 return;
8228 }
8229
[email protected]6e288612010-12-21 20:45:038230 if (copyX != x ||
8231 copyY != y ||
8232 copyWidth != width ||
8233 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:208234 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:038235 uint32 pixels_size = 0;
[email protected]3458a64a2012-04-10 17:39:348236 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:248237 width, height, format, type, state_.unpack_alignment, &pixels_size,
8238 NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:518239 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:438240 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
[email protected]6e288612010-12-21 20:45:038241 return;
8242 }
[email protected]40d90a22013-04-09 03:39:558243 scoped_ptr<char[]> zero(new char[pixels_size]);
[email protected]6e288612010-12-21 20:45:038244 memset(zero.get(), 0, pixels_size);
8245 glTexSubImage2D(
8246 target, level, xoffset, yoffset, width, height,
8247 format, type, zero.get());
8248 }
[email protected]0d6bfdc2011-11-02 01:32:208249
[email protected]6e288612010-12-21 20:45:038250 if (copyHeight > 0 && copyWidth > 0) {
8251 GLint dx = copyX - x;
8252 GLint dy = copyY - y;
8253 GLint destX = xoffset + dx;
8254 GLint destY = yoffset + dy;
8255 glCopyTexSubImage2D(target, level,
8256 destX, destY, copyX, copyY,
8257 copyWidth, copyHeight);
8258 }
[email protected]cadde4a2010-07-31 17:10:438259}
8260
[email protected]f598f422012-12-07 08:30:038261bool GLES2DecoderImpl::ValidateTexSubImage2D(
8262 error::Error* error,
8263 const char* function_name,
8264 GLenum target,
8265 GLint level,
8266 GLint xoffset,
8267 GLint yoffset,
8268 GLsizei width,
8269 GLsizei height,
8270 GLenum format,
8271 GLenum type,
8272 const void * data) {
8273 (*error) = error::kNoError;
8274 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:518275 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
[email protected]f598f422012-12-07 08:30:038276 return false;
8277 }
8278 if (width < 0) {
[email protected]ab09b612013-03-11 22:11:518279 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
[email protected]f598f422012-12-07 08:30:038280 return false;
8281 }
8282 if (height < 0) {
[email protected]ab09b612013-03-11 22:11:518283 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
[email protected]f598f422012-12-07 08:30:038284 return false;
8285 }
8286 if (!validators_->texture_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:518287 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
[email protected]f598f422012-12-07 08:30:038288 return false;
8289 }
8290 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:518291 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
[email protected]f598f422012-12-07 08:30:038292 return false;
8293 }
[email protected]370eaf12013-05-18 09:19:498294 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8295 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:518296 LOCAL_SET_GL_ERROR(
8297 GL_INVALID_OPERATION,
8298 function_name, "unknown texture for target");
[email protected]f598f422012-12-07 08:30:038299 return false;
[email protected]cadde4a2010-07-31 17:10:438300 }
[email protected]370eaf12013-05-18 09:19:498301 Texture* texture = texture_ref->texture();
[email protected]df6cf1ad2011-01-29 01:20:528302 GLenum current_type = 0;
8303 GLenum internal_format = 0;
[email protected]02965c22013-03-09 02:40:078304 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
[email protected]ab09b612013-03-11 22:11:518305 LOCAL_SET_GL_ERROR(
[email protected]f598f422012-12-07 08:30:038306 GL_INVALID_OPERATION, function_name, "level does not exist.");
8307 return false;
[email protected]df6cf1ad2011-01-29 01:20:528308 }
8309 if (format != internal_format) {
[email protected]ab09b612013-03-11 22:11:518310 LOCAL_SET_GL_ERROR(
8311 GL_INVALID_OPERATION,
8312 function_name, "format does not match internal format.");
[email protected]f598f422012-12-07 08:30:038313 return false;
[email protected]df6cf1ad2011-01-29 01:20:528314 }
8315 if (type != current_type) {
[email protected]ab09b612013-03-11 22:11:518316 LOCAL_SET_GL_ERROR(
8317 GL_INVALID_OPERATION,
8318 function_name, "type does not match type of texture.");
[email protected]f598f422012-12-07 08:30:038319 return false;
[email protected]df6cf1ad2011-01-29 01:20:528320 }
[email protected]85a4ac22013-05-31 01:58:478321 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:518322 LOCAL_SET_GL_ERROR(
8323 GL_INVALID_OPERATION,
8324 function_name, "async upload pending for texture");
[email protected]32145a92012-12-17 09:01:598325 return false;
8326 }
[email protected]02965c22013-03-09 02:40:078327 if (!texture->ValidForTexture(
[email protected]cadde4a2010-07-31 17:10:438328 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:518329 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
[email protected]f598f422012-12-07 08:30:038330 return false;
[email protected]cadde4a2010-07-31 17:10:438331 }
[email protected]81375742012-06-08 00:04:008332 if ((GLES2Util::GetChannelsForFormat(format) &
8333 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:518334 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:008335 GL_INVALID_OPERATION,
[email protected]f598f422012-12-07 08:30:038336 function_name, "can not supply data for depth or stencil textures");
8337 return false;
[email protected]81375742012-06-08 00:04:008338 }
[email protected]f598f422012-12-07 08:30:038339 if (data == NULL) {
8340 (*error) = error::kOutOfBounds;
8341 return false;
8342 }
8343 return true;
8344}
[email protected]81375742012-06-08 00:04:008345
[email protected]f598f422012-12-07 08:30:038346error::Error GLES2DecoderImpl::DoTexSubImage2D(
8347 GLenum target,
8348 GLint level,
8349 GLint xoffset,
8350 GLint yoffset,
8351 GLsizei width,
8352 GLsizei height,
8353 GLenum format,
8354 GLenum type,
8355 const void * data) {
8356 error::Error error = error::kNoError;
8357 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8358 xoffset, yoffset, width, height, format, type, data)) {
8359 return error;
8360 }
[email protected]370eaf12013-05-18 09:19:498361 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8362 Texture* texture = texture_ref->texture();
[email protected]4502e6492011-12-14 19:39:158363 GLsizei tex_width = 0;
8364 GLsizei tex_height = 0;
[email protected]02965c22013-03-09 02:40:078365 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
[email protected]4502e6492011-12-14 19:39:158366 DCHECK(ok);
8367 if (xoffset != 0 || yoffset != 0 ||
8368 width != tex_width || height != tex_height) {
[email protected]370eaf12013-05-18 09:19:498369 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8370 target, level)) {
[email protected]ab09b612013-03-11 22:11:518371 LOCAL_SET_GL_ERROR(
8372 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
[email protected]f598f422012-12-07 08:30:038373 return error::kNoError;
[email protected]473c01ccb2011-06-07 01:33:308374 }
[email protected]63b465922012-09-06 02:04:528375 ScopedTextureUploadTimer timer(this);
[email protected]4502e6492011-12-14 19:39:158376 glTexSubImage2D(
8377 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]f598f422012-12-07 08:30:038378 return error::kNoError;
[email protected]0d6bfdc2011-11-02 01:32:208379 }
[email protected]4502e6492011-12-14 19:39:158380
[email protected]02965c22013-03-09 02:40:078381 if (teximage2d_faster_than_texsubimage2d_ && !texture->IsImmutable()) {
[email protected]63b465922012-09-06 02:04:528382 ScopedTextureUploadTimer timer(this);
[email protected]4502e6492011-12-14 19:39:158383 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
8384 // same as internal_foramt. If that changes we'll need to look them up.
[email protected]8f1d2aa2013-05-10 23:45:388385 glTexImage2D(
[email protected]4502e6492011-12-14 19:39:158386 target, level, format, width, height, 0, format, type, data);
8387 } else {
[email protected]63b465922012-09-06 02:04:528388 ScopedTextureUploadTimer timer(this);
[email protected]4502e6492011-12-14 19:39:158389 glTexSubImage2D(
8390 target, level, xoffset, yoffset, width, height, format, type, data);
8391 }
[email protected]370eaf12013-05-18 09:19:498392 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
[email protected]f598f422012-12-07 08:30:038393 return error::kNoError;
[email protected]cadde4a2010-07-31 17:10:438394}
8395
[email protected]b493ee622011-04-13 23:52:008396error::Error GLES2DecoderImpl::HandleTexSubImage2D(
[email protected]ed9f9cd2013-02-27 21:12:358397 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:388398 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:008399 GLboolean internal = static_cast<GLboolean>(c.internal);
8400 if (internal == GL_TRUE && tex_image_2d_failed_)
8401 return error::kNoError;
8402
8403 GLenum target = static_cast<GLenum>(c.target);
8404 GLint level = static_cast<GLint>(c.level);
8405 GLint xoffset = static_cast<GLint>(c.xoffset);
8406 GLint yoffset = static_cast<GLint>(c.yoffset);
8407 GLsizei width = static_cast<GLsizei>(c.width);
8408 GLsizei height = static_cast<GLsizei>(c.height);
8409 GLenum format = static_cast<GLenum>(c.format);
8410 GLenum type = static_cast<GLenum>(c.type);
8411 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:348412 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:248413 width, height, format, type, state_.unpack_alignment, &data_size,
8414 NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:008415 return error::kOutOfBounds;
8416 }
8417 const void* pixels = GetSharedMemoryAs<const void*>(
8418 c.pixels_shm_id, c.pixels_shm_offset, data_size);
[email protected]f598f422012-12-07 08:30:038419 return DoTexSubImage2D(
[email protected]b493ee622011-04-13 23:52:008420 target, level, xoffset, yoffset, width, height, format, type, pixels);
[email protected]b493ee622011-04-13 23:52:008421}
8422
8423error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
[email protected]ed9f9cd2013-02-27 21:12:358424 uint32 immediate_data_size, const cmds::TexSubImage2DImmediate& c) {
[email protected]b493ee622011-04-13 23:52:008425 GLboolean internal = static_cast<GLboolean>(c.internal);
8426 if (internal == GL_TRUE && tex_image_2d_failed_)
8427 return error::kNoError;
8428
8429 GLenum target = static_cast<GLenum>(c.target);
8430 GLint level = static_cast<GLint>(c.level);
8431 GLint xoffset = static_cast<GLint>(c.xoffset);
8432 GLint yoffset = static_cast<GLint>(c.yoffset);
8433 GLsizei width = static_cast<GLsizei>(c.width);
8434 GLsizei height = static_cast<GLsizei>(c.height);
8435 GLenum format = static_cast<GLenum>(c.format);
8436 GLenum type = static_cast<GLenum>(c.type);
8437 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:348438 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:248439 width, height, format, type, state_.unpack_alignment, &data_size,
8440 NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:008441 return error::kOutOfBounds;
8442 }
8443 const void* pixels = GetImmediateDataAs<const void*>(
8444 c, data_size, immediate_data_size);
[email protected]f598f422012-12-07 08:30:038445 return DoTexSubImage2D(
[email protected]b493ee622011-04-13 23:52:008446 target, level, xoffset, yoffset, width, height, format, type, pixels);
[email protected]b493ee622011-04-13 23:52:008447}
8448
[email protected]f7a64ee2010-02-01 22:24:148449error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]ed9f9cd2013-02-27 21:12:358450 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:368451 GLuint index = static_cast<GLuint>(c.index);
8452 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]ed9f9cd2013-02-27 21:12:358453 typedef cmds::GetVertexAttribPointerv::Result Result;
[email protected]0bfd9882010-02-05 23:02:258454 Result* result = GetSharedMemoryAs<Result*>(
8455 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:368456 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:148457 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:368458 }
[email protected]07d0cc82010-02-17 04:51:408459 // Check that the client initialized the result.
8460 if (result->size != 0) {
8461 return error::kInvalidArguments;
8462 }
[email protected]9438b012010-06-15 22:55:058463 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]ab09b612013-03-11 22:11:518464 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8465 "glGetVertexAttribPointerv", pname, "pname");
[email protected]f7a64ee2010-02-01 22:24:148466 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:368467 }
[email protected]3916c97e2010-02-25 03:20:508468 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:518469 LOCAL_SET_GL_ERROR(
8470 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
[email protected]f7a64ee2010-02-01 22:24:148471 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:368472 }
[email protected]0bfd9882010-02-05 23:02:258473 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:088474 *result->GetData() =
[email protected]ed9f9cd2013-02-27 21:12:358475 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:148476 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328477}
8478
[email protected]f7b85372010-02-03 01:11:378479bool GLES2DecoderImpl::GetUniformSetup(
[email protected]df37b9932013-03-08 05:21:428480 GLuint program_id, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:378481 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:128482 error::Error* error, GLint* real_location,
8483 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:108484 DCHECK(error);
8485 DCHECK(service_id);
8486 DCHECK(result_pointer);
8487 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:128488 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:378489 *error = error::kNoError;
8490 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:258491 SizedResult<GLint>* result;
8492 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8493 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8494 if (!result) {
[email protected]f7b85372010-02-03 01:11:378495 *error = error::kOutOfBounds;
8496 return false;
8497 }
[email protected]0bfd9882010-02-05 23:02:258498 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:378499 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:258500 result->SetNumResults(0);
[email protected]df37b9932013-03-08 05:21:428501 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8502 if (!program) {
[email protected]ae51d192010-04-27 00:48:038503 return false;
8504 }
[email protected]df37b9932013-03-08 05:21:428505 if (!program->IsValid()) {
[email protected]f7b85372010-02-03 01:11:378506 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ab09b612013-03-11 22:11:518507 LOCAL_SET_GL_ERROR(
8508 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
[email protected]f7b85372010-02-03 01:11:378509 return false;
8510 }
[email protected]df37b9932013-03-08 05:21:428511 *service_id = program->service_id();
[email protected]43c2f1f2011-03-25 18:35:368512 GLint array_index = -1;
[email protected]ed9f9cd2013-02-27 21:12:358513 const Program::UniformInfo* uniform_info =
[email protected]df37b9932013-03-08 05:21:428514 program->GetUniformInfoByFakeLocation(
[email protected]1b0a6752012-02-22 03:44:128515 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:368516 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:378517 // No such location.
[email protected]ab09b612013-03-11 22:11:518518 LOCAL_SET_GL_ERROR(
8519 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
[email protected]f7b85372010-02-03 01:11:378520 return false;
8521 }
[email protected]43c2f1f2011-03-25 18:35:368522 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:508523 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:378524 if (size == 0) {
[email protected]ab09b612013-03-11 22:11:518525 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
[email protected]f7b85372010-02-03 01:11:378526 return false;
8527 }
[email protected]0bfd9882010-02-05 23:02:258528 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8529 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8530 if (!result) {
[email protected]f7b85372010-02-03 01:11:378531 *error = error::kOutOfBounds;
8532 return false;
8533 }
[email protected]0bfd9882010-02-05 23:02:258534 result->size = size;
[email protected]939e7362010-05-13 20:49:108535 *result_type = type;
[email protected]f7b85372010-02-03 01:11:378536 return true;
8537}
8538
[email protected]f7a64ee2010-02-01 22:24:148539error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]ed9f9cd2013-02-27 21:12:358540 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:378541 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:338542 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:378543 GLuint service_id;
[email protected]939e7362010-05-13 20:49:108544 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:128545 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:378546 Error error;
[email protected]0bfd9882010-02-05 23:02:258547 void* result;
[email protected]f7b85372010-02-03 01:11:378548 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:128549 program, fake_location, c.params_shm_id, c.params_shm_offset,
8550 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:258551 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:128552 service_id, real_location,
[email protected]ed9f9cd2013-02-27 21:12:358553 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:378554 }
8555 return error;
[email protected]96449d2c2009-11-25 00:01:328556}
8557
[email protected]f7a64ee2010-02-01 22:24:148558error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]ed9f9cd2013-02-27 21:12:358559 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:378560 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:338561 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:378562 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:128563 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:378564 Error error;
[email protected]ed9f9cd2013-02-27 21:12:358565 typedef cmds::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:108566 Result* result;
8567 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:378568 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:128569 program, fake_location, c.params_shm_id, c.params_shm_offset,
8570 &error, &real_location, &service_id,
8571 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:108572 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8573 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8574 GLsizei num_values = result->GetNumResults();
[email protected]40d90a22013-04-09 03:39:558575 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:128576 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:108577 GLfloat* dst = result->GetData();
8578 for (GLsizei ii = 0; ii < num_values; ++ii) {
8579 dst[ii] = (temp[ii] != 0);
8580 }
8581 } else {
[email protected]1b0a6752012-02-22 03:44:128582 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:108583 }
[email protected]f7b85372010-02-03 01:11:378584 }
8585 return error;
[email protected]96449d2c2009-11-25 00:01:328586}
8587
[email protected]f7a64ee2010-02-01 22:24:148588error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]ed9f9cd2013-02-27 21:12:358589 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:258590 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8591 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
[email protected]ed9f9cd2013-02-27 21:12:358592 typedef cmds::GetShaderPrecisionFormat::Result Result;
[email protected]0bfd9882010-02-05 23:02:258593 Result* result = GetSharedMemoryAs<Result*>(
8594 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8595 if (!result) {
8596 return error::kOutOfBounds;
8597 }
[email protected]07d0cc82010-02-17 04:51:408598 // Check that the client initialized the result.
8599 if (result->success != 0) {
8600 return error::kInvalidArguments;
8601 }
[email protected]9438b012010-06-15 22:55:058602 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]ab09b612013-03-11 22:11:518603 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:538604 "glGetShaderPrecisionFormat", shader_type, "shader_type");
[email protected]8eee29c2010-04-29 03:38:298605 return error::kNoError;
8606 }
[email protected]9438b012010-06-15 22:55:058607 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]ab09b612013-03-11 22:11:518608 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:538609 "glGetShaderPrecisionFormat", precision_type, "precision_type");
[email protected]8eee29c2010-04-29 03:38:298610 return error::kNoError;
8611 }
8612
8613 result->success = 1; // true
[email protected]d8bc3ec2013-03-07 06:28:408614
[email protected]46c86752013-05-21 05:08:398615 GLint range[2] = { 0, 0 };
[email protected]d8bc3ec2013-03-07 06:28:408616 GLint precision = 0;
[email protected]8dc1bf92013-03-12 03:58:218617 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
[email protected]d8bc3ec2013-03-07 06:28:408618
8619 result->min_range = range[0];
8620 result->max_range = range[1];
8621 result->precision = precision;
8622
[email protected]f7a64ee2010-02-01 22:24:148623 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328624}
8625
[email protected]f7a64ee2010-02-01 22:24:148626error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]ed9f9cd2013-02-27 21:12:358627 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:258628 uint32 result_size = c.result_size;
[email protected]df37b9932013-03-08 05:21:428629 GLuint program_id = static_cast<GLuint>(c.program);
8630 Program* program = GetProgramInfoNotShader(
8631 program_id, "glGetAttachedShaders");
8632 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258633 return error::kNoError;
8634 }
[email protected]ed9f9cd2013-02-27 21:12:358635 typedef cmds::GetAttachedShaders::Result Result;
[email protected]0bfd9882010-02-05 23:02:258636 uint32 max_count = Result::ComputeMaxResults(result_size);
8637 Result* result = GetSharedMemoryAs<Result*>(
8638 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8639 if (!result) {
8640 return error::kOutOfBounds;
8641 }
[email protected]07d0cc82010-02-17 04:51:408642 // Check that the client initialized the result.
8643 if (result->size != 0) {
8644 return error::kInvalidArguments;
8645 }
[email protected]0bfd9882010-02-05 23:02:258646 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:038647 glGetAttachedShaders(
[email protected]df37b9932013-03-08 05:21:428648 program->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:258649 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:038650 if (!shader_manager()->GetClientId(result->GetData()[ii],
8651 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:258652 NOTREACHED();
8653 return error::kGenericError;
8654 }
8655 }
8656 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:148657 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328658}
8659
[email protected]f7a64ee2010-02-01 22:24:148660error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]ed9f9cd2013-02-27 21:12:358661 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
[email protected]df37b9932013-03-08 05:21:428662 GLuint program_id = c.program;
[email protected]0bfd9882010-02-05 23:02:258663 GLuint index = c.index;
8664 uint32 name_bucket_id = c.name_bucket_id;
[email protected]ed9f9cd2013-02-27 21:12:358665 typedef cmds::GetActiveUniform::Result Result;
[email protected]0bfd9882010-02-05 23:02:258666 Result* result = GetSharedMemoryAs<Result*>(
8667 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8668 if (!result) {
8669 return error::kOutOfBounds;
8670 }
[email protected]07d0cc82010-02-17 04:51:408671 // Check that the client initialized the result.
8672 if (result->success != 0) {
8673 return error::kInvalidArguments;
8674 }
[email protected]df37b9932013-03-08 05:21:428675 Program* program = GetProgramInfoNotShader(
8676 program_id, "glGetActiveUniform");
8677 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258678 return error::kNoError;
8679 }
[email protected]ed9f9cd2013-02-27 21:12:358680 const Program::UniformInfo* uniform_info =
[email protected]df37b9932013-03-08 05:21:428681 program->GetUniformInfo(index);
[email protected]0bfd9882010-02-05 23:02:258682 if (!uniform_info) {
[email protected]ab09b612013-03-11 22:11:518683 LOCAL_SET_GL_ERROR(
8684 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258685 return error::kNoError;
8686 }
8687 result->success = 1; // true.
8688 result->size = uniform_info->size;
8689 result->type = uniform_info->type;
8690 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298691 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148692 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328693}
8694
[email protected]f7a64ee2010-02-01 22:24:148695error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]ed9f9cd2013-02-27 21:12:358696 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
[email protected]df37b9932013-03-08 05:21:428697 GLuint program_id = c.program;
[email protected]0bfd9882010-02-05 23:02:258698 GLuint index = c.index;
8699 uint32 name_bucket_id = c.name_bucket_id;
[email protected]ed9f9cd2013-02-27 21:12:358700 typedef cmds::GetActiveAttrib::Result Result;
[email protected]0bfd9882010-02-05 23:02:258701 Result* result = GetSharedMemoryAs<Result*>(
8702 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8703 if (!result) {
8704 return error::kOutOfBounds;
8705 }
[email protected]07d0cc82010-02-17 04:51:408706 // Check that the client initialized the result.
8707 if (result->success != 0) {
8708 return error::kInvalidArguments;
8709 }
[email protected]df37b9932013-03-08 05:21:428710 Program* program = GetProgramInfoNotShader(
8711 program_id, "glGetActiveAttrib");
8712 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258713 return error::kNoError;
8714 }
[email protected]ed9f9cd2013-02-27 21:12:358715 const Program::VertexAttrib* attrib_info =
[email protected]df37b9932013-03-08 05:21:428716 program->GetAttribInfo(index);
[email protected]0bfd9882010-02-05 23:02:258717 if (!attrib_info) {
[email protected]ab09b612013-03-11 22:11:518718 LOCAL_SET_GL_ERROR(
8719 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258720 return error::kNoError;
8721 }
8722 result->success = 1; // true.
8723 result->size = attrib_info->size;
8724 result->type = attrib_info->type;
8725 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298726 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148727 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328728}
8729
[email protected]b273e432010-04-12 17:23:588730error::Error GLES2DecoderImpl::HandleShaderBinary(
[email protected]ed9f9cd2013-02-27 21:12:358731 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
[email protected]b273e432010-04-12 17:23:588732#if 1 // No binary shader support.
[email protected]ab09b612013-03-11 22:11:518733 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
[email protected]b273e432010-04-12 17:23:588734 return error::kNoError;
8735#else
8736 GLsizei n = static_cast<GLsizei>(c.n);
8737 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:518738 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
[email protected]b273e432010-04-12 17:23:588739 return error::kNoError;
8740 }
8741 GLsizei length = static_cast<GLsizei>(c.length);
8742 if (length < 0) {
[email protected]ab09b612013-03-11 22:11:518743 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
[email protected]b273e432010-04-12 17:23:588744 return error::kNoError;
8745 }
8746 uint32 data_size;
8747 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8748 return error::kOutOfBounds;
8749 }
8750 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8751 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8752 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8753 const void* binary = GetSharedMemoryAs<const void*>(
8754 c.binary_shm_id, c.binary_shm_offset, length);
8755 if (shaders == NULL || binary == NULL) {
8756 return error::kOutOfBounds;
8757 }
8758 scoped_array<GLuint> service_ids(new GLuint[n]);
8759 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]df37b9932013-03-08 05:21:428760 Shader* shader = GetShader(shaders[ii]);
8761 if (!shader) {
[email protected]ab09b612013-03-11 22:11:518762 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
[email protected]b273e432010-04-12 17:23:588763 return error::kNoError;
8764 }
[email protected]df37b9932013-03-08 05:21:428765 service_ids[ii] = shader->service_id();
[email protected]b273e432010-04-12 17:23:588766 }
8767 // TODO(gman): call glShaderBinary
8768 return error::kNoError;
8769#endif
8770}
8771
[email protected]6d792ee12013-05-15 00:40:568772void GLES2DecoderImpl::DoSwapBuffers() {
[email protected]64ace852011-05-19 21:49:498773 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
[email protected]a7266a92012-06-28 02:11:088774
[email protected]64ace852011-05-19 21:49:498775 int this_frame_number = frame_number_++;
[email protected]2ac620e52012-07-23 20:31:428776 // TRACE_EVENT for gpu tests:
8777 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
[email protected]c76faea2013-03-26 07:42:428778 TRACE_EVENT_SCOPE_THREAD,
[email protected]2ac620e52012-07-23 20:31:428779 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8780 "width", (is_offscreen ? offscreen_size_.width() :
8781 surface_->GetSize().width()));
[email protected]6d792ee12013-05-15 00:40:568782 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
[email protected]64ace852011-05-19 21:49:498783 "offscreen", is_offscreen,
8784 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:358785 // If offscreen then don't actually SwapBuffers to the display. Just copy
8786 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:498787 if (is_offscreen) {
[email protected]111975c62012-09-06 01:37:318788 TRACE_EVENT2("gpu", "Offscreen",
8789 "width", offscreen_size_.width(), "height", offscreen_size_.height());
[email protected]1fb8c482011-08-31 01:01:538790 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8791 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8792 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8793 // fix this.
[email protected]62e155e2012-10-23 22:43:158794 if (workarounds().needs_offscreen_buffer_workaround) {
[email protected]1fb8c482011-08-31 01:01:538795 offscreen_saved_frame_buffer_->Create();
8796 glFinish();
8797 }
8798
8799 // Allocate the offscreen saved color texture.
8800 DCHECK(offscreen_saved_color_format_);
8801 offscreen_saved_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:098802 offscreen_size_, offscreen_saved_color_format_, false);
[email protected]1fb8c482011-08-31 01:01:538803
8804 offscreen_saved_frame_buffer_->AttachRenderTexture(
8805 offscreen_saved_color_texture_.get());
[email protected]f0cfe752013-01-14 01:09:058806 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
8807 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8808 GL_FRAMEBUFFER_COMPLETE) {
8809 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8810 << "because offscreen saved FBO was incomplete.";
[email protected]6d792ee12013-05-15 00:40:568811 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8812 return;
[email protected]f0cfe752013-01-14 01:09:058813 }
[email protected]1fb8c482011-08-31 01:01:538814
[email protected]f0cfe752013-01-14 01:09:058815 // Clear the offscreen color texture.
8816 // TODO(piman): Is this still necessary?
8817 {
8818 ScopedFrameBufferBinder binder(this,
8819 offscreen_saved_frame_buffer_->id());
8820 glClearColor(0, 0, 0, 0);
8821 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8822 glDisable(GL_SCISSOR_TEST);
8823 glClear(GL_COLOR_BUFFER_BIT);
8824 RestoreClearState();
8825 }
[email protected]1fb8c482011-08-31 01:01:538826 }
8827
8828 UpdateParentTextureInfo();
8829 }
8830
[email protected]f0cfe752013-01-14 01:09:058831 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
[email protected]6d792ee12013-05-15 00:40:568832 return;
[email protected]ab09b612013-03-11 22:11:518833 ScopedGLErrorSuppressor suppressor(
[email protected]6d792ee12013-05-15 00:40:568834 "GLES2DecoderImpl::DoSwapBuffers", this);
[email protected]6217d392010-03-25 22:08:358835
[email protected]34ff8b0c2010-10-01 20:06:028836 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:138837 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:278838 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]b86b14982010-10-11 18:45:488839 } else {
[email protected]069944672012-04-25 20:52:238840 ScopedFrameBufferBinder binder(this,
8841 offscreen_target_frame_buffer_->id());
[email protected]51411e32012-01-19 20:21:138842
[email protected]069944672012-04-25 20:52:238843 if (offscreen_target_buffer_preserved_) {
8844 // Copy the target frame buffer to the saved offscreen texture.
8845 offscreen_saved_color_texture_->Copy(
8846 offscreen_saved_color_texture_->size(),
8847 offscreen_saved_color_format_);
8848 } else {
8849 // Flip the textures in the parent context via the texture manager.
8850 if (!!offscreen_saved_color_texture_info_.get())
[email protected]370eaf12013-05-18 09:19:498851 offscreen_saved_color_texture_info_->texture()->
[email protected]069944672012-04-25 20:52:238852 SetServiceId(offscreen_target_color_texture_->id());
[email protected]8a61d872012-01-20 12:43:568853
[email protected]069944672012-04-25 20:52:238854 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8855 offscreen_target_frame_buffer_->AttachRenderTexture(
8856 offscreen_target_color_texture_.get());
[email protected]b86b14982010-10-11 18:45:488857 }
[email protected]069944672012-04-25 20:52:238858
8859 // Ensure the side effects of the copy are visible to the parent
8860 // context. There is no need to do this for ANGLE because it uses a
8861 // single D3D device for all contexts.
8862 if (!IsAngle())
8863 glFlush();
[email protected]0c8c9d22010-06-25 17:36:398864 }
[email protected]6217d392010-03-25 22:08:358865 } else {
[email protected]111975c62012-09-06 01:37:318866 TRACE_EVENT2("gpu", "Onscreen",
8867 "width", surface_->GetSize().width(),
8868 "height", surface_->GetSize().height());
[email protected]f62a5ab2011-05-23 20:34:158869 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:018870 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]6d792ee12013-05-15 00:40:568871 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
[email protected]d0498742010-09-20 20:27:018872 }
[email protected]6217d392010-03-25 22:08:358873 }
[email protected]6217d392010-03-25 22:08:358874}
8875
[email protected]d4239852011-08-12 04:51:228876error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358877 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:188878 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288879 if (!bucket || bucket->size() == 0) {
8880 return error::kInvalidArguments;
8881 }
[email protected]ed9f9cd2013-02-27 21:12:358882 typedef cmds::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:188883 Result* result = GetSharedMemoryAs<Result*>(
8884 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8885 if (!result) {
8886 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:108887 }
[email protected]b1d2dcb2010-05-17 19:24:188888 // Check that the client initialized the result.
8889 if (*result != 0) {
8890 return error::kInvalidArguments;
8891 }
8892 std::string feature_str;
8893 if (!bucket->GetAsString(&feature_str)) {
8894 return error::kInvalidArguments;
8895 }
8896
8897 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:228898 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:188899 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:228900 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:408901 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8902 // TODO(gman): decide how to remove the need for this const_cast.
8903 // I could make validators_ non const but that seems bad as this is the only
8904 // place it is needed. I could make some special friend class of validators
8905 // just to allow this to set them. That seems silly. I could refactor this
8906 // code to use the extension mechanism or the initialization attributes to
8907 // turn this feature on. Given that the only real point of this is to make
8908 // the conformance tests pass and given that there is lots of real work that
8909 // needs to be done it seems like refactoring for one to one of those
8910 // methods is a very low priority.
8911 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:048912 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
8913 force_webgl_glsl_validation_ = true;
8914 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:188915 } else {
8916 return error::kNoError;
8917 }
8918
8919 *result = 1; // true.
8920 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:108921}
8922
[email protected]c2f8c8402010-12-06 18:07:248923error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8924 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:358925 const cmds::GetRequestableExtensionsCHROMIUM& c) {
[email protected]c2f8c8402010-12-06 18:07:248926 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]ed9f9cd2013-02-27 21:12:358927 scoped_refptr<FeatureInfo> info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:298928 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:248929 bucket->SetFromString(info->extensions().c_str());
8930 return error::kNoError;
8931}
8932
8933error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358934 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
[email protected]c2f8c8402010-12-06 18:07:248935 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288936 if (!bucket || bucket->size() == 0) {
8937 return error::kInvalidArguments;
8938 }
[email protected]c2f8c8402010-12-06 18:07:248939 std::string feature_str;
8940 if (!bucket->GetAsString(&feature_str)) {
8941 return error::kInvalidArguments;
8942 }
8943
[email protected]4b7eba92013-01-08 02:23:568944 bool desire_webgl_glsl_validation =
8945 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
8946 bool desire_standard_derivatives = false;
[email protected]70dc60932013-06-04 03:33:498947 bool desire_frag_depth = false;
[email protected]aff39ac82013-06-08 04:53:138948 bool desire_draw_buffers = false;
[email protected]4b7eba92013-01-08 02:23:568949 if (force_webgl_glsl_validation_) {
8950 desire_standard_derivatives =
8951 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
[email protected]70dc60932013-06-04 03:33:498952 desire_frag_depth =
8953 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
[email protected]aff39ac82013-06-08 04:53:138954 desire_draw_buffers =
8955 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
[email protected]f0d74742011-10-03 16:31:048956 }
8957
[email protected]4b7eba92013-01-08 02:23:568958 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
[email protected]70dc60932013-06-04 03:33:498959 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
[email protected]aff39ac82013-06-08 04:53:138960 desire_frag_depth != frag_depth_explicitly_enabled_ ||
8961 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
[email protected]70dc60932013-06-04 03:33:498962 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
8963 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
8964 frag_depth_explicitly_enabled_ |= desire_frag_depth;
[email protected]aff39ac82013-06-08 04:53:138965 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
[email protected]c2f8c8402010-12-06 18:07:248966 InitializeShaderTranslator();
8967 }
8968
[email protected]302ce6d2011-07-07 23:28:118969 UpdateCapabilities();
8970
[email protected]c2f8c8402010-12-06 18:07:248971 return error::kNoError;
8972}
8973
[email protected]372e0412011-06-28 16:08:568974error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358975 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
[email protected]372e0412011-06-28 16:08:568976 GLuint count = c.count;
8977 uint32 pnames_size;
8978 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
8979 return error::kOutOfBounds;
8980 }
8981 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
8982 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
8983 if (pnames == NULL) {
8984 return error::kOutOfBounds;
8985 }
8986
8987 // We have to copy them since we use them twice so the client
8988 // can't change them between the time we validate them and the time we use
8989 // them.
[email protected]40d90a22013-04-09 03:39:558990 scoped_ptr<GLenum[]> enums(new GLenum[count]);
[email protected]372e0412011-06-28 16:08:568991 memcpy(enums.get(), pnames, pnames_size);
8992
8993 // Count up the space needed for the result.
8994 uint32 num_results = 0;
8995 for (GLuint ii = 0; ii < count; ++ii) {
8996 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
8997 if (num == 0) {
[email protected]ab09b612013-03-11 22:11:518998 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8999 "glGetMulitpleCHROMIUM", enums[ii], "pname");
[email protected]372e0412011-06-28 16:08:569000 return error::kNoError;
9001 }
9002 // Num will never be more than 4.
9003 DCHECK_LE(num, 4u);
[email protected]3aad1a32012-09-07 20:54:479004 if (!SafeAddUint32(num_results, num, &num_results)) {
[email protected]372e0412011-06-28 16:08:569005 return error::kOutOfBounds;
9006 }
9007 }
9008
9009 uint32 result_size = 0;
9010 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9011 return error::kOutOfBounds;
9012 }
9013
9014 if (result_size != static_cast<uint32>(c.size)) {
[email protected]ab09b612013-03-11 22:11:519015 LOCAL_SET_GL_ERROR(
9016 GL_INVALID_VALUE,
9017 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
[email protected]372e0412011-06-28 16:08:569018 return error::kNoError;
9019 }
9020
9021 GLint* results = GetSharedMemoryAs<GLint*>(
9022 c.results_shm_id, c.results_shm_offset, result_size);
9023 if (results == NULL) {
9024 return error::kOutOfBounds;
9025 }
9026
9027 // Check the results have been cleared in case the context was lost.
9028 for (uint32 ii = 0; ii < num_results; ++ii) {
9029 if (results[ii]) {
9030 return error::kInvalidArguments;
9031 }
9032 }
9033
9034 // Get each result.
9035 GLint* start = results;
9036 for (GLuint ii = 0; ii < count; ++ii) {
9037 GLsizei num_written = 0;
[email protected]d058bca2012-11-26 10:27:269038 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
[email protected]f63b1232012-10-31 07:03:539039 !GetHelper(enums[ii], results, &num_written)) {
[email protected]b0ce0982013-05-13 18:51:489040 DoGetIntegerv(enums[ii], results);
[email protected]372e0412011-06-28 16:08:569041 }
9042 results += num_written;
9043 }
9044
9045 // Just to verify. Should this be a DCHECK?
9046 if (static_cast<uint32>(results - start) != num_results) {
9047 return error::kOutOfBounds;
9048 }
9049
9050 return error::kNoError;
9051}
9052
[email protected]2318d342011-07-11 22:27:429053error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359054 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
[email protected]df37b9932013-03-08 05:21:429055 GLuint program_id = static_cast<GLuint>(c.program);
[email protected]2318d342011-07-11 22:27:429056 uint32 bucket_id = c.bucket_id;
9057 Bucket* bucket = CreateBucket(bucket_id);
9058 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
[email protected]df37b9932013-03-08 05:21:429059 Program* program = NULL;
9060 program = GetProgram(program_id);
9061 if (!program || !program->IsValid()) {
[email protected]9a14ae612011-08-08 17:51:469062 return error::kNoError;
[email protected]2318d342011-07-11 22:27:429063 }
[email protected]df37b9932013-03-08 05:21:429064 program->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:429065 return error::kNoError;
9066}
9067
[email protected]38d139d2011-07-14 00:38:439068error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9069 switch (reset_status_) {
[email protected]ad84a3a2012-06-08 21:42:439070 case GL_NO_ERROR:
9071 // TODO(kbr): improve the precision of the error code in this case.
9072 // Consider delegating to context for error code if MakeCurrent fails.
9073 return error::kUnknown;
9074 case GL_GUILTY_CONTEXT_RESET_ARB:
9075 return error::kGuilty;
9076 case GL_INNOCENT_CONTEXT_RESET_ARB:
9077 return error::kInnocent;
9078 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9079 return error::kUnknown;
[email protected]38d139d2011-07-14 00:38:439080 }
9081
9082 NOTREACHED();
9083 return error::kUnknown;
9084}
9085
9086bool GLES2DecoderImpl::WasContextLost() {
[email protected]c4485aad62012-12-17 10:19:099087 if (reset_status_ != GL_NO_ERROR) {
9088 return true;
9089 }
[email protected]706b69f2012-07-27 04:59:309090 if (context_->WasAllocatedUsingRobustnessExtension()) {
9091 GLenum status = GL_NO_ERROR;
9092 if (has_robustness_extension_)
9093 status = glGetGraphicsResetStatusARB();
[email protected]38d139d2011-07-14 00:38:439094 if (status != GL_NO_ERROR) {
9095 // The graphics card was reset. Signal a lost context to the application.
9096 reset_status_ = status;
[email protected]93a7d98f2013-07-11 00:04:229097 reset_by_robustness_extension_ = true;
[email protected]38d139d2011-07-14 00:38:439098 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
[email protected]c4485aad62012-12-17 10:19:099099 << " context lost via ARB/EXT_robustness. Reset status = "
9100 << GLES2Util::GetStringEnum(status);
[email protected]38d139d2011-07-14 00:38:439101 return true;
9102 }
9103 }
9104 return false;
9105}
9106
[email protected]93a7d98f2013-07-11 00:04:229107bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9108 return WasContextLost() && reset_by_robustness_extension_;
9109}
9110
[email protected]c4485aad62012-12-17 10:19:099111void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9112 // Only loses the context once.
9113 if (reset_status_ != GL_NO_ERROR) {
9114 return;
9115 }
9116
9117 // Marks this context as lost.
9118 reset_status_ = reset_status;
9119 current_decoder_error_ = error::kLostContext;
[email protected]c4485aad62012-12-17 10:19:099120}
9121
9122error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359123 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
[email protected]c4485aad62012-12-17 10:19:099124 GLenum current = static_cast<GLenum>(c.current);
9125 GLenum other = static_cast<GLenum>(c.other);
9126 if (!validators_->reset_status.IsValid(current)) {
[email protected]ab09b612013-03-11 22:11:519127 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9128 "glLoseContextCHROMIUM", current, "current");
[email protected]c4485aad62012-12-17 10:19:099129 }
9130 if (!validators_->reset_status.IsValid(other)) {
[email protected]ab09b612013-03-11 22:11:519131 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
[email protected]c4485aad62012-12-17 10:19:099132 }
9133 group_->LoseContexts(other);
9134 reset_status_ = current;
9135 current_decoder_error_ = error::kLostContext;
9136 return error::kLostContext;
9137}
9138
[email protected]b096d032013-03-08 03:08:019139error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9140 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9141 return error::kUnknownCommand;
9142}
9143
[email protected]840a7e462013-02-27 01:29:519144error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359145 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
[email protected]840a7e462013-02-27 01:29:519146 if (wait_sync_point_callback_.is_null())
9147 return error::kNoError;
9148
9149 return wait_sync_point_callback_.Run(c.sync_point) ?
9150 error::kNoError : error::kDeferCommandUntilLater;
9151}
9152
[email protected]882ba1e22012-03-08 19:02:539153bool GLES2DecoderImpl::GenQueriesEXTHelper(
9154 GLsizei n, const GLuint* client_ids) {
9155 for (GLsizei ii = 0; ii < n; ++ii) {
9156 if (query_manager_->GetQuery(client_ids[ii])) {
9157 return false;
9158 }
9159 }
[email protected]c45f1972012-03-14 07:27:369160 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:539161 return true;
9162}
9163
9164void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9165 GLsizei n, const GLuint* client_ids) {
9166 for (GLsizei ii = 0; ii < n; ++ii) {
9167 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9168 if (query && !query->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:119169 if (query == state_.current_query.get()) {
[email protected]e259eb412012-10-13 05:47:249170 state_.current_query = NULL;
[email protected]882ba1e22012-03-08 19:02:539171 }
[email protected]c45f1972012-03-14 07:27:369172 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:539173 query_manager_->RemoveQuery(client_ids[ii]);
9174 }
9175 }
9176}
9177
[email protected]22e3f552012-03-13 01:54:199178bool GLES2DecoderImpl::ProcessPendingQueries() {
9179 if (query_manager_.get() == NULL) {
9180 return false;
9181 }
[email protected]c45f1972012-03-14 07:27:369182 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:199183 current_decoder_error_ = error::kOutOfBounds;
9184 }
9185 return query_manager_->HavePendingQueries();
9186}
9187
[email protected]2b1767cf2013-03-16 09:25:059188bool GLES2DecoderImpl::HasMoreIdleWork() {
[email protected]744329c2013-07-12 00:54:259189 return async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
[email protected]2b1767cf2013-03-16 09:25:059190}
9191
9192void GLES2DecoderImpl::PerformIdleWork() {
[email protected]b68b100752013-06-05 08:34:489193 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
[email protected]2b1767cf2013-03-16 09:25:059194 return;
[email protected]b68b100752013-06-05 08:34:489195 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
[email protected]2b1767cf2013-03-16 09:25:059196 ProcessFinishedAsyncTransfers();
9197}
9198
[email protected]882ba1e22012-03-08 19:02:539199error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
[email protected]ed9f9cd2013-02-27 21:12:359200 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
[email protected]882ba1e22012-03-08 19:02:539201 GLenum target = static_cast<GLenum>(c.target);
9202 GLuint client_id = static_cast<GLuint>(c.id);
9203 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9204 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9205
[email protected]c45f1972012-03-14 07:27:369206 switch (target) {
9207 case GL_COMMANDS_ISSUED_CHROMIUM:
[email protected]fb4bf5822012-10-23 21:25:559208 case GL_LATENCY_QUERY_CHROMIUM:
[email protected]0713f43d2012-12-14 22:41:309209 case GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM:
[email protected]620b0db02013-03-20 15:47:009210 case GL_GET_ERROR_QUERY_CHROMIUM:
[email protected]c45f1972012-03-14 07:27:369211 break;
9212 default:
[email protected]62e155e2012-10-23 22:43:159213 if (!features().occlusion_query_boolean) {
[email protected]ab09b612013-03-11 22:11:519214 LOCAL_SET_GL_ERROR(
[email protected]620b0db02013-03-20 15:47:009215 GL_INVALID_OPERATION, "glBeginQueryEXT",
9216 "not enabled for occlusion queries");
[email protected]c45f1972012-03-14 07:27:369217 return error::kNoError;
9218 }
9219 break;
[email protected]882ba1e22012-03-08 19:02:539220 }
9221
[email protected]7cd76fd2013-06-02 21:11:119222 if (state_.current_query.get()) {
[email protected]ab09b612013-03-11 22:11:519223 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439224 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
[email protected]882ba1e22012-03-08 19:02:539225 return error::kNoError;
9226 }
9227
9228 if (client_id == 0) {
[email protected]ab09b612013-03-11 22:11:519229 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
[email protected]882ba1e22012-03-08 19:02:539230 return error::kNoError;
9231 }
9232
9233 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9234 if (!query) {
[email protected]c45f1972012-03-14 07:27:369235 // TODO(gman): Decide if we need this check.
9236 //
[email protected]882ba1e22012-03-08 19:02:539237 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:369238 //
9239 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9240 // for all Query ids but from the POV of the command buffer service maybe
9241 // you don't.
9242 //
9243 // The client can enforce this. I don't think the service cares.
9244 //
9245 // IdAllocatorInterface* id_allocator =
9246 // group_->GetIdAllocator(id_namespaces::kQueries);
9247 // if (!id_allocator->InUse(client_id)) {
[email protected]ab09b612013-03-11 22:11:519248 // LOCAL_SET_GL_ERROR(
9249 // GL_INVALID_OPERATION,
9250 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
[email protected]c45f1972012-03-14 07:27:369251 // return error::kNoError;
9252 // }
9253 query = query_manager_->CreateQuery(
9254 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:539255 }
9256
[email protected]c45f1972012-03-14 07:27:369257 if (query->target() != target) {
[email protected]ab09b612013-03-11 22:11:519258 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439259 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
[email protected]882ba1e22012-03-08 19:02:539260 return error::kNoError;
9261 } else if (query->shm_id() != sync_shm_id ||
9262 query->shm_offset() != sync_shm_offset) {
9263 DLOG(ERROR) << "Shared memory used by query not the same as before";
9264 return error::kInvalidArguments;
9265 }
9266
[email protected]c45f1972012-03-14 07:27:369267 if (!query_manager_->BeginQuery(query)) {
9268 return error::kOutOfBounds;
9269 }
[email protected]882ba1e22012-03-08 19:02:539270
[email protected]e259eb412012-10-13 05:47:249271 state_.current_query = query;
[email protected]882ba1e22012-03-08 19:02:539272 return error::kNoError;
9273}
9274
9275error::Error GLES2DecoderImpl::HandleEndQueryEXT(
[email protected]ed9f9cd2013-02-27 21:12:359276 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
[email protected]882ba1e22012-03-08 19:02:539277 GLenum target = static_cast<GLenum>(c.target);
9278 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9279
[email protected]7cd76fd2013-06-02 21:11:119280 if (!state_.current_query.get()) {
[email protected]ab09b612013-03-11 22:11:519281 LOCAL_SET_GL_ERROR(
9282 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
[email protected]882ba1e22012-03-08 19:02:539283 return error::kNoError;
9284 }
[email protected]e259eb412012-10-13 05:47:249285 if (state_.current_query->target() != target) {
[email protected]ab09b612013-03-11 22:11:519286 LOCAL_SET_GL_ERROR(
9287 GL_INVALID_OPERATION,
9288 "glEndQueryEXT", "target does not match active query");
[email protected]882ba1e22012-03-08 19:02:539289 return error::kNoError;
9290 }
[email protected]882ba1e22012-03-08 19:02:539291
[email protected]7cd76fd2013-06-02 21:11:119292 if (!query_manager_->EndQuery(state_.current_query.get(), submit_count)) {
[email protected]c45f1972012-03-14 07:27:369293 return error::kOutOfBounds;
9294 }
9295
[email protected]fe8d73c2013-02-16 22:37:329296 query_manager_->ProcessPendingTransferQueries();
9297
[email protected]e259eb412012-10-13 05:47:249298 state_.current_query = NULL;
[email protected]882ba1e22012-03-08 19:02:539299 return error::kNoError;
9300}
9301
[email protected]944b62f32012-09-27 02:20:469302bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9303 GLsizei n, const GLuint* client_ids) {
[email protected]944b62f32012-09-27 02:20:469304 for (GLsizei ii = 0; ii < n; ++ii) {
9305 if (GetVertexAttribManager(client_ids[ii])) {
9306 return false;
9307 }
9308 }
[email protected]ab4fd7282012-10-12 16:25:579309
[email protected]62e155e2012-10-23 22:43:159310 if (!features().native_vertex_array_object) {
[email protected]ab4fd7282012-10-12 16:25:579311 // Emulated VAO
9312 for (GLsizei ii = 0; ii < n; ++ii) {
9313 CreateVertexAttribManager(client_ids[ii], 0);
9314 }
9315 } else {
[email protected]40d90a22013-04-09 03:39:559316 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ab4fd7282012-10-12 16:25:579317
9318 glGenVertexArraysOES(n, service_ids.get());
9319 for (GLsizei ii = 0; ii < n; ++ii) {
9320 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9321 }
[email protected]944b62f32012-09-27 02:20:469322 }
[email protected]ab4fd7282012-10-12 16:25:579323
[email protected]944b62f32012-09-27 02:20:469324 return true;
9325}
9326
9327void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9328 GLsizei n, const GLuint* client_ids) {
[email protected]944b62f32012-09-27 02:20:469329 for (GLsizei ii = 0; ii < n; ++ii) {
9330 VertexAttribManager* vao =
9331 GetVertexAttribManager(client_ids[ii]);
9332 if (vao && !vao->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:119333 if (state_.vertex_attrib_manager.get() == vao) {
[email protected]e259eb412012-10-13 05:47:249334 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
[email protected]944b62f32012-09-27 02:20:469335 }
9336 RemoveVertexAttribManager(client_ids[ii]);
9337 }
9338 }
9339}
9340
9341void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
[email protected]944b62f32012-09-27 02:20:469342 VertexAttribManager* vao = NULL;
9343 GLuint service_id = 0;
9344 if (client_id != 0) {
9345 vao = GetVertexAttribManager(client_id);
9346 if (!vao) {
9347 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9348 // only allows names that have been previously generated. As such, we do
9349 // not generate new names here.
[email protected]ab09b612013-03-11 22:11:519350 LOCAL_SET_GL_ERROR(
9351 GL_INVALID_OPERATION,
9352 "glBindVertexArrayOES", "bad vertex array id.");
[email protected]944b62f32012-09-27 02:20:469353 current_decoder_error_ = error::kNoError;
9354 return;
9355 } else {
9356 service_id = vao->service_id();
9357 }
[email protected]944b62f32012-09-27 02:20:469358 } else {
[email protected]7cd76fd2013-06-02 21:11:119359 vao = default_vertex_attrib_manager_.get();
[email protected]944b62f32012-09-27 02:20:469360 }
9361
[email protected]ab4fd7282012-10-12 16:25:579362 // Only set the VAO state if it's changed
[email protected]7cd76fd2013-06-02 21:11:119363 if (state_.vertex_attrib_manager.get() != vao) {
[email protected]e259eb412012-10-13 05:47:249364 state_.vertex_attrib_manager = vao;
[email protected]62e155e2012-10-23 22:43:159365 if (!features().native_vertex_array_object) {
[email protected]ab4fd7282012-10-12 16:25:579366 EmulateVertexArrayState();
9367 } else {
9368 glBindVertexArrayOES(service_id);
9369 }
9370 }
9371}
9372
9373// Used when OES_vertex_array_object isn't natively supported
9374void GLES2DecoderImpl::EmulateVertexArrayState() {
9375 // Setup the Vertex attribute state
9376 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9377 RestoreStateForAttrib(vv);
9378 }
9379
9380 // Setup the element buffer
[email protected]16ccec12013-02-28 03:40:219381 Buffer* element_array_buffer =
[email protected]e259eb412012-10-13 05:47:249382 state_.vertex_attrib_manager->element_array_buffer();
[email protected]ab4fd7282012-10-12 16:25:579383 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9384 element_array_buffer ? element_array_buffer->service_id() : 0);
[email protected]944b62f32012-09-27 02:20:469385}
9386
9387bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
[email protected]944b62f32012-09-27 02:20:469388 const VertexAttribManager* vao =
9389 GetVertexAttribManager(client_id);
9390 return vao && vao->IsValid() && !vao->IsDeleted();
9391}
9392
[email protected]b0af4f52011-09-28 22:04:429393error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
9394 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:359395 const cmds::CreateStreamTextureCHROMIUM& c) {
[email protected]62e155e2012-10-23 22:43:159396 if (!features().chromium_stream_texture) {
[email protected]ab09b612013-03-11 22:11:519397 LOCAL_SET_GL_ERROR(
9398 GL_INVALID_OPERATION,
9399 "glOpenStreamTextureCHROMIUM", "not supported.");
[email protected]b0af4f52011-09-28 22:04:429400 return error::kNoError;
9401 }
9402
9403 uint32 client_id = c.client_id;
[email protected]ed9f9cd2013-02-27 21:12:359404 typedef cmds::CreateStreamTextureCHROMIUM::Result Result;
[email protected]b0af4f52011-09-28 22:04:429405 Result* result = GetSharedMemoryAs<Result*>(
9406 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9407
[email protected]e5081262012-01-05 23:09:039408 if (!result)
9409 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:429410 *result = GL_ZERO;
[email protected]370eaf12013-05-18 09:19:499411 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
9412 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519413 LOCAL_SET_GL_ERROR(
9414 GL_INVALID_VALUE,
9415 "glCreateStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:429416 return error::kNoError;
9417 }
9418
[email protected]370eaf12013-05-18 09:19:499419 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079420 if (texture->IsStreamTexture()) {
[email protected]ab09b612013-03-11 22:11:519421 LOCAL_SET_GL_ERROR(
9422 GL_INVALID_OPERATION,
9423 "glCreateStreamTextureCHROMIUM", "is already a stream texture.");
[email protected]b0af4f52011-09-28 22:04:429424 return error::kNoError;
9425 }
9426
[email protected]02965c22013-03-09 02:40:079427 if (texture->target() && texture->target() != GL_TEXTURE_EXTERNAL_OES) {
[email protected]ab09b612013-03-11 22:11:519428 LOCAL_SET_GL_ERROR(
9429 GL_INVALID_OPERATION,
9430 "glCreateStreamTextureCHROMIUM",
9431 "is already bound to incompatible target.");
[email protected]b0af4f52011-09-28 22:04:429432 return error::kNoError;
9433 }
9434
[email protected]4f9958142013-07-02 03:58:079435 if (!stream_texture_manager())
[email protected]b0af4f52011-09-28 22:04:429436 return error::kInvalidArguments;
9437
[email protected]4f9958142013-07-02 03:58:079438 GLuint object_id = stream_texture_manager()->CreateStreamTexture(
[email protected]02965c22013-03-09 02:40:079439 texture->service_id(), client_id);
[email protected]b0af4f52011-09-28 22:04:429440
9441 if (object_id) {
[email protected]370eaf12013-05-18 09:19:499442 texture_manager()->SetStreamTexture(texture_ref, true);
[email protected]b0af4f52011-09-28 22:04:429443 } else {
[email protected]ab09b612013-03-11 22:11:519444 LOCAL_SET_GL_ERROR(
9445 GL_OUT_OF_MEMORY,
9446 "glCreateStreamTextureCHROMIUM", "failed to create platform texture.");
[email protected]b0af4f52011-09-28 22:04:429447 }
9448
9449 *result = object_id;
9450 return error::kNoError;
9451}
9452
9453error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
9454 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:359455 const cmds::DestroyStreamTextureCHROMIUM& c) {
[email protected]b0af4f52011-09-28 22:04:429456 GLuint client_id = c.texture;
[email protected]370eaf12013-05-18 09:19:499457 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
[email protected]4f9958142013-07-02 03:58:079458 if (texture_ref && texture_manager()->IsStreamTextureOwner(texture_ref)) {
9459 if (!stream_texture_manager())
[email protected]b0af4f52011-09-28 22:04:429460 return error::kInvalidArguments;
9461
[email protected]4f9958142013-07-02 03:58:079462 stream_texture_manager()->DestroyStreamTexture(texture_ref->service_id());
[email protected]370eaf12013-05-18 09:19:499463 texture_manager()->SetStreamTexture(texture_ref, false);
[email protected]b0af4f52011-09-28 22:04:429464 } else {
[email protected]ab09b612013-03-11 22:11:519465 LOCAL_SET_GL_ERROR(
9466 GL_INVALID_VALUE,
9467 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:429468 }
9469
9470 return error::kNoError;
9471}
9472
[email protected]e51bdf32011-11-23 22:21:469473#if defined(OS_MACOSX)
9474void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9475 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9476 texture_id);
9477 if (it != texture_to_io_surface_map_.end()) {
9478 // Found a previous IOSurface bound to this texture; release it.
9479 CFTypeRef surface = it->second;
9480 CFRelease(surface);
9481 texture_to_io_surface_map_.erase(it);
9482 }
9483}
9484#endif
9485
9486void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9487 GLenum target, GLsizei width, GLsizei height,
9488 GLuint io_surface_id, GLuint plane) {
9489#if defined(OS_MACOSX)
9490 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
[email protected]ab09b612013-03-11 22:11:519491 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439492 GL_INVALID_OPERATION,
9493 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
[email protected]e51bdf32011-11-23 22:21:469494 return;
9495 }
9496
9497 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9498 if (!surface_support) {
[email protected]ab09b612013-03-11 22:11:519499 LOCAL_SET_GL_ERROR(
9500 GL_INVALID_OPERATION,
9501 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
[email protected]e51bdf32011-11-23 22:21:469502 return;
9503 }
9504
9505 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9506 // This might be supported in the future, and if we could require
9507 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9508 // could delete a lot of code. For now, perform strict validation so we
9509 // know what's going on.
[email protected]ab09b612013-03-11 22:11:519510 LOCAL_SET_GL_ERROR(
[email protected]e51bdf32011-11-23 22:21:469511 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439512 "glTexImageIOSurface2DCHROMIUM",
9513 "requires TEXTURE_RECTANGLE_ARB target");
[email protected]e51bdf32011-11-23 22:21:469514 return;
9515 }
9516
[email protected]09d50362012-10-18 20:54:379517 // Default target might be conceptually valid, but disallow it to avoid
9518 // accidents.
[email protected]370eaf12013-05-18 09:19:499519 TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
9520 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519521 LOCAL_SET_GL_ERROR(
9522 GL_INVALID_OPERATION,
9523 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
[email protected]e51bdf32011-11-23 22:21:469524 return;
9525 }
[email protected]e51bdf32011-11-23 22:21:469526
9527 // Look up the new IOSurface. Note that because of asynchrony
9528 // between processes this might fail; during live resizing the
9529 // plugin process might allocate and release an IOSurface before
9530 // this process gets a chance to look it up. Hold on to any old
9531 // IOSurface in this case.
9532 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9533 if (!surface) {
[email protected]ab09b612013-03-11 22:11:519534 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439535 GL_INVALID_OPERATION,
9536 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
[email protected]e51bdf32011-11-23 22:21:469537 return;
9538 }
9539
9540 // Release any IOSurface previously bound to this texture.
[email protected]370eaf12013-05-18 09:19:499541 ReleaseIOSurfaceForTexture(texture_ref->service_id());
[email protected]e51bdf32011-11-23 22:21:469542
9543 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9544 texture_to_io_surface_map_.insert(
[email protected]370eaf12013-05-18 09:19:499545 std::make_pair(texture_ref->service_id(), surface));
[email protected]e51bdf32011-11-23 22:21:469546
9547 CGLContextObj context =
9548 static_cast<CGLContextObj>(context_->GetHandle());
9549
9550 CGLError err = surface_support->CGLTexImageIOSurface2D(
9551 context,
9552 target,
9553 GL_RGBA,
9554 width,
9555 height,
9556 GL_BGRA,
9557 GL_UNSIGNED_INT_8_8_8_8_REV,
9558 surface,
9559 plane);
9560
9561 if (err != kCGLNoError) {
[email protected]ab09b612013-03-11 22:11:519562 LOCAL_SET_GL_ERROR(
[email protected]e51bdf32011-11-23 22:21:469563 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439564 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
[email protected]e51bdf32011-11-23 22:21:469565 return;
9566 }
9567
9568 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499569 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:469570 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9571
9572#else
[email protected]ab09b612013-03-11 22:11:519573 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439574 "glTexImageIOSurface2DCHROMIUM", "not supported.");
[email protected]e51bdf32011-11-23 22:21:469575#endif
9576}
9577
[email protected]97dc7cbe2011-12-06 17:26:179578static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9579 switch (internalformat) {
9580 case GL_RGB565:
9581 return GL_RGB;
9582 case GL_RGBA4:
9583 return GL_RGBA;
9584 case GL_RGB5_A1:
9585 return GL_RGBA;
9586 case GL_RGB8_OES:
9587 return GL_RGB;
9588 case GL_RGBA8_OES:
9589 return GL_RGBA;
9590 case GL_LUMINANCE8_ALPHA8_EXT:
9591 return GL_LUMINANCE_ALPHA;
9592 case GL_LUMINANCE8_EXT:
9593 return GL_LUMINANCE;
9594 case GL_ALPHA8_EXT:
9595 return GL_ALPHA;
9596 case GL_RGBA32F_EXT:
9597 return GL_RGBA;
9598 case GL_RGB32F_EXT:
9599 return GL_RGB;
9600 case GL_ALPHA32F_EXT:
9601 return GL_ALPHA;
9602 case GL_LUMINANCE32F_EXT:
9603 return GL_LUMINANCE;
9604 case GL_LUMINANCE_ALPHA32F_EXT:
9605 return GL_LUMINANCE_ALPHA;
9606 case GL_RGBA16F_EXT:
9607 return GL_RGBA;
9608 case GL_RGB16F_EXT:
9609 return GL_RGB;
9610 case GL_ALPHA16F_EXT:
9611 return GL_ALPHA;
9612 case GL_LUMINANCE16F_EXT:
9613 return GL_LUMINANCE;
9614 case GL_LUMINANCE_ALPHA16F_EXT:
9615 return GL_LUMINANCE_ALPHA;
9616 case GL_BGRA8_EXT:
9617 return GL_BGRA_EXT;
9618 default:
9619 return GL_NONE;
9620 }
9621}
9622
[email protected]43410e92012-04-20 17:06:289623void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
[email protected]0a1e9ad2012-05-04 21:13:039624 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
[email protected]a4a6bdd12013-04-19 20:46:549625 GLenum internal_format, GLenum dest_type) {
[email protected]370eaf12013-05-18 09:19:499626 TextureRef* dest_texture_ref = GetTexture(dest_id);
9627 TextureRef* source_texture_ref = GetTexture(source_id);
[email protected]43410e92012-04-20 17:06:289628
[email protected]370eaf12013-05-18 09:19:499629 if (!source_texture_ref || !dest_texture_ref) {
[email protected]ab09b612013-03-11 22:11:519630 LOCAL_SET_GL_ERROR(
9631 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
[email protected]43410e92012-04-20 17:06:289632 return;
9633 }
9634
9635 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:519636 LOCAL_SET_GL_ERROR(
9637 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
[email protected]43410e92012-04-20 17:06:289638 return;
9639 }
9640
[email protected]370eaf12013-05-18 09:19:499641 Texture* source_texture = source_texture_ref->texture();
9642 Texture* dest_texture = dest_texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079643 if (dest_texture->target() != GL_TEXTURE_2D ||
[email protected]9bc9a2e82013-04-03 03:56:259644 (source_texture->target() != GL_TEXTURE_2D &&
9645 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
[email protected]ab09b612013-03-11 22:11:519646 LOCAL_SET_GL_ERROR(
9647 GL_INVALID_VALUE,
9648 "glCopyTextureCHROMIUM", "invalid texture target binding");
[email protected]0a1e9ad2012-05-04 21:13:039649 return;
9650 }
9651
[email protected]43410e92012-04-20 17:06:289652 int source_width, source_height, dest_width, dest_height;
[email protected]43410e92012-04-20 17:06:289653
[email protected]9bc9a2e82013-04-03 03:56:259654 if (source_texture->target() == GL_TEXTURE_2D) {
9655 if (!source_texture->GetLevelSize(GL_TEXTURE_2D, 0, &source_width,
9656 &source_height)) {
9657 LOCAL_SET_GL_ERROR(
9658 GL_INVALID_VALUE,
9659 "glCopyTextureChromium", "source texture has no level 0");
9660 return;
9661 }
9662
9663 // Check that this type of texture is allowed.
9664 if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D, level, source_width,
9665 source_height, 1)) {
9666 LOCAL_SET_GL_ERROR(
9667 GL_INVALID_VALUE,
9668 "glCopyTextureCHROMIUM", "Bad dimensions");
9669 return;
9670 }
[email protected]43410e92012-04-20 17:06:289671 }
9672
[email protected]377976552013-05-14 23:32:569673 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
[email protected]4f9958142013-07-02 03:58:079674 DCHECK(stream_texture_manager());
[email protected]377976552013-05-14 23:32:569675 StreamTexture* stream_tex =
[email protected]4f9958142013-07-02 03:58:079676 stream_texture_manager()->LookupStreamTexture(
[email protected]377976552013-05-14 23:32:569677 source_texture->service_id());
9678 if (!stream_tex) {
9679 LOCAL_SET_GL_ERROR(
9680 GL_INVALID_VALUE,
9681 "glCopyTextureChromium", "Stream texture lookup failed");
9682 return;
9683 }
9684 gfx::Size size = stream_tex->GetSize();
9685 source_width = size.width();
9686 source_height = size.height();
9687 if (source_width <= 0 || source_height <= 0) {
9688 LOCAL_SET_GL_ERROR(
9689 GL_INVALID_VALUE,
9690 "glCopyTextureChromium", "invalid streamtexture size");
9691 return;
9692 }
9693 }
9694
[email protected]cf6b8f62012-05-25 21:43:379695 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9696 // needed because it takes 10s of milliseconds to initialize.
9697 if (!copy_texture_CHROMIUM_.get()) {
[email protected]ab09b612013-03-11 22:11:519698 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
[email protected]cf6b8f62012-05-25 21:43:379699 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
[email protected]07a0cc32013-02-28 00:36:279700 copy_texture_CHROMIUM_->Initialize(this);
[email protected]cf6b8f62012-05-25 21:43:379701 RestoreCurrentFramebufferBindings();
[email protected]ab09b612013-03-11 22:11:519702 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
[email protected]cf6b8f62012-05-25 21:43:379703 return;
9704 }
9705
[email protected]a4a6bdd12013-04-19 20:46:549706 GLenum dest_type_previous;
[email protected]0a1e9ad2012-05-04 21:13:039707 GLenum dest_internal_format;
[email protected]02965c22013-03-09 02:40:079708 bool dest_level_defined = dest_texture->GetLevelSize(
9709 GL_TEXTURE_2D, level, &dest_width, &dest_height);
[email protected]43410e92012-04-20 17:06:289710
[email protected]0a1e9ad2012-05-04 21:13:039711 if (dest_level_defined) {
[email protected]a4a6bdd12013-04-19 20:46:549712 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
[email protected]02965c22013-03-09 02:40:079713 &dest_internal_format);
[email protected]0a1e9ad2012-05-04 21:13:039714 }
9715
9716 // Resize the destination texture to the dimensions of the source texture.
9717 if (!dest_level_defined || dest_width != source_width ||
9718 dest_height != source_height ||
[email protected]a4a6bdd12013-04-19 20:46:549719 dest_internal_format != internal_format ||
9720 dest_type_previous != dest_type) {
[email protected]43410e92012-04-20 17:06:289721 // Ensure that the glTexImage2D succeeds.
[email protected]ab09b612013-03-11 22:11:519722 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
[email protected]02965c22013-03-09 02:40:079723 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
[email protected]8f1d2aa2013-05-10 23:45:389724 glTexImage2D(
[email protected]43410e92012-04-20 17:06:289725 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
[email protected]0a1e9ad2012-05-04 21:13:039726 0, internal_format, dest_type, NULL);
[email protected]ab09b612013-03-11 22:11:519727 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
[email protected]0a1e9ad2012-05-04 21:13:039728 if (error != GL_NO_ERROR) {
9729 RestoreCurrentTexture2DBindings();
[email protected]43410e92012-04-20 17:06:289730 return;
[email protected]0a1e9ad2012-05-04 21:13:039731 }
[email protected]43410e92012-04-20 17:06:289732
9733 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499734 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
[email protected]0a1e9ad2012-05-04 21:13:039735 source_height, 1, 0, internal_format, dest_type, true);
[email protected]f7024712012-05-15 21:30:259736 } else {
[email protected]02965c22013-03-09 02:40:079737 texture_manager()->SetLevelCleared(
[email protected]370eaf12013-05-18 09:19:499738 dest_texture_ref, GL_TEXTURE_2D, level, true);
[email protected]43410e92012-04-20 17:06:289739 }
9740
[email protected]5394a4102013-04-18 05:41:379741 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9742 // before presenting.
9743 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9744 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9745 // instead of using default matrix crbug.com/226218.
9746 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9747 0.0f, 1.0f, 0.0f, 0.0f,
9748 0.0f, 0.0f, 1.0f, 0.0f,
9749 0.0f, 0.0f, 0.0f, 1.0f};
9750 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9751 this,
9752 source_texture->target(),
9753 dest_texture->target(),
9754 source_texture->service_id(),
9755 dest_texture->service_id(), level,
9756 source_width, source_height,
9757 unpack_flip_y_,
9758 unpack_premultiply_alpha_,
9759 unpack_unpremultiply_alpha_,
9760 default_matrix);
9761 } else {
9762 copy_texture_CHROMIUM_->DoCopyTexture(
9763 this,
9764 source_texture->target(),
9765 dest_texture->target(),
9766 source_texture->service_id(),
9767 dest_texture->service_id(), level,
9768 source_width, source_height,
9769 unpack_flip_y_,
9770 unpack_premultiply_alpha_,
9771 unpack_unpremultiply_alpha_);
9772 }
[email protected]43410e92012-04-20 17:06:289773}
9774
[email protected]97dc7cbe2011-12-06 17:26:179775static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9776 switch (internalformat) {
9777 case GL_RGB565:
9778 return GL_UNSIGNED_SHORT_5_6_5;
9779 case GL_RGBA4:
9780 return GL_UNSIGNED_SHORT_4_4_4_4;
9781 case GL_RGB5_A1:
9782 return GL_UNSIGNED_SHORT_5_5_5_1;
9783 case GL_RGB8_OES:
9784 return GL_UNSIGNED_BYTE;
9785 case GL_RGBA8_OES:
9786 return GL_UNSIGNED_BYTE;
9787 case GL_LUMINANCE8_ALPHA8_EXT:
9788 return GL_UNSIGNED_BYTE;
9789 case GL_LUMINANCE8_EXT:
9790 return GL_UNSIGNED_BYTE;
9791 case GL_ALPHA8_EXT:
9792 return GL_UNSIGNED_BYTE;
9793 case GL_RGBA32F_EXT:
9794 return GL_FLOAT;
9795 case GL_RGB32F_EXT:
9796 return GL_FLOAT;
9797 case GL_ALPHA32F_EXT:
9798 return GL_FLOAT;
9799 case GL_LUMINANCE32F_EXT:
9800 return GL_FLOAT;
9801 case GL_LUMINANCE_ALPHA32F_EXT:
9802 return GL_FLOAT;
9803 case GL_RGBA16F_EXT:
9804 return GL_HALF_FLOAT_OES;
9805 case GL_RGB16F_EXT:
9806 return GL_HALF_FLOAT_OES;
9807 case GL_ALPHA16F_EXT:
9808 return GL_HALF_FLOAT_OES;
9809 case GL_LUMINANCE16F_EXT:
9810 return GL_HALF_FLOAT_OES;
9811 case GL_LUMINANCE_ALPHA16F_EXT:
9812 return GL_HALF_FLOAT_OES;
9813 case GL_BGRA8_EXT:
9814 return GL_UNSIGNED_BYTE;
9815 default:
9816 return GL_NONE;
9817 }
9818}
9819
9820void GLES2DecoderImpl::DoTexStorage2DEXT(
[email protected]a5d3dad2012-05-26 04:34:449821 GLenum target,
9822 GLint levels,
9823 GLenum internal_format,
9824 GLsizei width,
9825 GLsizei height) {
[email protected]43ed3a72012-05-30 22:55:389826 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
[email protected]80eb6b52012-01-19 00:14:419827 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:179828 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
[email protected]ab09b612013-03-11 22:11:519829 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439830 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
[email protected]97dc7cbe2011-12-06 17:26:179831 return;
9832 }
[email protected]370eaf12013-05-18 09:19:499833 TextureRef* texture_ref = GetTextureInfoForTarget(target);
9834 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519835 LOCAL_SET_GL_ERROR(
9836 GL_INVALID_OPERATION,
9837 "glTexStorage2DEXT", "unknown texture for target");
[email protected]97dc7cbe2011-12-06 17:26:179838 return;
9839 }
[email protected]370eaf12013-05-18 09:19:499840 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079841 if (texture->IsAttachedToFramebuffer()) {
[email protected]88a61bf2012-10-27 13:00:429842 clear_state_dirty_ = true;
[email protected]97dc7cbe2011-12-06 17:26:179843 }
[email protected]02965c22013-03-09 02:40:079844 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:519845 LOCAL_SET_GL_ERROR(
9846 GL_INVALID_OPERATION,
9847 "glTexStorage2DEXT", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:179848 return;
9849 }
[email protected]7989c9e2013-01-23 06:39:269850
9851 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9852 GLenum type = ExtractTypeFromStorageFormat(internal_format);
9853
9854 {
9855 GLsizei level_width = width;
9856 GLsizei level_height = height;
9857 uint32 estimated_size = 0;
9858 for (int ii = 0; ii < levels; ++ii) {
9859 uint32 level_size = 0;
9860 if (!GLES2Util::ComputeImageDataSizes(
9861 level_width, level_height, format, type, state_.unpack_alignment,
9862 &estimated_size, NULL, NULL) ||
9863 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:519864 LOCAL_SET_GL_ERROR(
9865 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:269866 return;
9867 }
9868 level_width = std::max(1, level_width >> 1);
9869 level_height = std::max(1, level_height >> 1);
9870 }
9871 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:519872 LOCAL_SET_GL_ERROR(
9873 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
[email protected]7989c9e2013-01-23 06:39:269874 return;
9875 }
9876 }
9877
[email protected]ab09b612013-03-11 22:11:519878 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
[email protected]8f1d2aa2013-05-10 23:45:389879 glTexStorage2DEXT(target, levels, internal_format, width, height);
[email protected]ab09b612013-03-11 22:11:519880 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
[email protected]97dc7cbe2011-12-06 17:26:179881 if (error == GL_NO_ERROR) {
[email protected]4502e6492011-12-14 19:39:159882 GLsizei level_width = width;
9883 GLsizei level_height = height;
9884 for (int ii = 0; ii < levels; ++ii) {
9885 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499886 texture_ref, target, ii, format,
9887 level_width, level_height, 1, 0, format, type, false);
[email protected]4502e6492011-12-14 19:39:159888 level_width = std::max(1, level_width >> 1);
9889 level_height = std::max(1, level_height >> 1);
9890 }
[email protected]02965c22013-03-09 02:40:079891 texture->SetImmutable(true);
[email protected]97dc7cbe2011-12-06 17:26:179892 }
[email protected]97dc7cbe2011-12-06 17:26:179893}
[email protected]e51bdf32011-11-23 22:21:469894
[email protected]78b514b2012-05-01 21:50:599895error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359896 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
[email protected]78b514b2012-05-01 21:50:599897 MailboxName name;
9898 mailbox_manager()->GenerateMailboxName(&name);
9899 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
9900 Bucket* bucket = CreateBucket(bucket_id);
9901
9902 bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM);
9903 bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM);
9904
9905 return error::kNoError;
9906}
9907
9908void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
9909 const GLbyte* mailbox) {
[email protected]987b9c02013-03-23 00:58:029910 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
[email protected]1d82e822013-04-10 21:32:329911 "context", logger_.GetLogPrefix(),
[email protected]987b9c02013-03-23 00:58:029912 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9913
[email protected]370eaf12013-05-18 09:19:499914 TextureRef* texture_ref = GetTextureInfoForTarget(target);
9915 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519916 LOCAL_SET_GL_ERROR(
9917 GL_INVALID_OPERATION,
9918 "glProduceTextureCHROMIUM", "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599919 return;
9920 }
9921
[email protected]62e65f02013-05-29 22:28:109922 Texture* produced = texture_manager()->Produce(texture_ref);
9923 if (!produced) {
[email protected]ab09b612013-03-11 22:11:519924 LOCAL_SET_GL_ERROR(
9925 GL_INVALID_OPERATION,
9926 "glProduceTextureCHROMIUM", "invalid texture");
[email protected]78b514b2012-05-01 21:50:599927 return;
9928 }
9929
9930 if (!group_->mailbox_manager()->ProduceTexture(
9931 target,
9932 *reinterpret_cast<const MailboxName*>(mailbox),
[email protected]62e65f02013-05-29 22:28:109933 produced)) {
[email protected]ab09b612013-03-11 22:11:519934 LOCAL_SET_GL_ERROR(
9935 GL_INVALID_OPERATION,
9936 "glProduceTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599937 return;
9938 }
[email protected]78b514b2012-05-01 21:50:599939}
9940
9941void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
9942 const GLbyte* mailbox) {
[email protected]987b9c02013-03-23 00:58:029943 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
[email protected]1d82e822013-04-10 21:32:329944 "context", logger_.GetLogPrefix(),
[email protected]987b9c02013-03-23 00:58:029945 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9946
[email protected]62e65f02013-05-29 22:28:109947 scoped_refptr<TextureRef> texture_ref =
9948 GetTextureInfoForTargetUnlessDefault(target);
[email protected]7cd76fd2013-06-02 21:11:119949 if (!texture_ref.get()) {
9950 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9951 "glConsumeTextureCHROMIUM",
9952 "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599953 return;
9954 }
[email protected]62e65f02013-05-29 22:28:109955 GLuint client_id = texture_ref->client_id();
9956 if (!client_id) {
9957 LOCAL_SET_GL_ERROR(
9958 GL_INVALID_OPERATION,
9959 "glConsumeTextureCHROMIUM", "unknown texture for target");
9960 return;
9961 }
9962 Texture* texture =
[email protected]78b514b2012-05-01 21:50:599963 group_->mailbox_manager()->ConsumeTexture(
9964 target,
[email protected]62e65f02013-05-29 22:28:109965 *reinterpret_cast<const MailboxName*>(mailbox));
9966 if (!texture) {
[email protected]ab09b612013-03-11 22:11:519967 LOCAL_SET_GL_ERROR(
9968 GL_INVALID_OPERATION,
9969 "glConsumeTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599970 return;
9971 }
[email protected]62e65f02013-05-29 22:28:109972 if (texture->target() != target) {
[email protected]ab09b612013-03-11 22:11:519973 LOCAL_SET_GL_ERROR(
9974 GL_INVALID_OPERATION,
[email protected]62e65f02013-05-29 22:28:109975 "glConsumeTextureCHROMIUM", "invalid target");
[email protected]78b514b2012-05-01 21:50:599976 return;
9977 }
[email protected]62e65f02013-05-29 22:28:109978
9979 DeleteTexturesHelper(1, &client_id);
9980 texture_ref = texture_manager()->Consume(client_id, texture);
9981 glBindTexture(target, texture_ref->service_id());
9982
9983 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
9984 unit.bind_target = target;
9985 switch (target) {
9986 case GL_TEXTURE_2D:
9987 unit.bound_texture_2d = texture_ref;
9988 break;
9989 case GL_TEXTURE_CUBE_MAP:
9990 unit.bound_texture_cube_map = texture_ref;
9991 break;
9992 case GL_TEXTURE_EXTERNAL_OES:
9993 unit.bound_texture_external_oes = texture_ref;
9994 break;
9995 case GL_TEXTURE_RECTANGLE_ARB:
9996 unit.bound_texture_rectangle_arb = texture_ref;
9997 break;
9998 default:
9999 NOTREACHED(); // Validation should prevent us getting here.
10000 break;
10001 }
[email protected]78b514b2012-05-01 21:50:5910002}
10003
[email protected]d2a0e1a2012-08-12 02:25:0110004void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10005 GLsizei length, const GLchar* marker) {
10006 if (!marker) {
10007 marker = "";
10008 }
10009 debug_marker_manager_.SetMarker(
10010 length ? std::string(marker, length) : std::string(marker));
10011}
10012
10013void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10014 GLsizei length, const GLchar* marker) {
10015 if (!marker) {
10016 marker = "";
10017 }
10018 debug_marker_manager_.PushGroup(
10019 length ? std::string(marker, length) : std::string(marker));
10020}
10021
10022void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10023 debug_marker_manager_.PopGroup();
10024}
10025
[email protected]09d50362012-10-18 20:54:3710026void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10027 GLenum target, GLint image_id) {
10028 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10029 if (target != GL_TEXTURE_2D) {
10030 // This might be supported in the future.
[email protected]ab09b612013-03-11 22:11:5110031 LOCAL_SET_GL_ERROR(
[email protected]09d50362012-10-18 20:54:3710032 GL_INVALID_OPERATION,
10033 "glBindTexImage2DCHROMIUM", "requires TEXTURE_2D target");
10034 return;
10035 }
10036
10037 // Default target might be conceptually valid, but disallow it to avoid
10038 // accidents.
[email protected]370eaf12013-05-18 09:19:4910039 TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
10040 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:5110041 LOCAL_SET_GL_ERROR(
10042 GL_INVALID_OPERATION,
10043 "glBindTexImage2DCHROMIUM", "no texture bound");
[email protected]09d50362012-10-18 20:54:3710044 return;
10045 }
10046
10047 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10048 if (!gl_image) {
[email protected]ab09b612013-03-11 22:11:5110049 LOCAL_SET_GL_ERROR(
10050 GL_INVALID_OPERATION,
10051 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
[email protected]09d50362012-10-18 20:54:3710052 return;
10053 }
10054
[email protected]b8160812013-04-09 00:41:0410055 {
10056 ScopedGLErrorSuppressor suppressor(
10057 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", this);
10058 if (!gl_image->BindTexImage()) {
10059 LOCAL_SET_GL_ERROR(
10060 GL_INVALID_OPERATION,
10061 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10062 return;
10063 }
[email protected]09d50362012-10-18 20:54:3710064 }
10065
10066 gfx::Size size = gl_image->GetSize();
10067 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:4910068 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
[email protected]09d50362012-10-18 20:54:3710069 GL_RGBA, GL_UNSIGNED_BYTE, true);
[email protected]370eaf12013-05-18 09:19:4910070 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
[email protected]09d50362012-10-18 20:54:3710071}
10072
10073void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10074 GLenum target, GLint image_id) {
10075 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10076 if (target != GL_TEXTURE_2D) {
10077 // This might be supported in the future.
[email protected]ab09b612013-03-11 22:11:5110078 LOCAL_SET_GL_ERROR(
[email protected]09d50362012-10-18 20:54:3710079 GL_INVALID_OPERATION,
10080 "glReleaseTexImage2DCHROMIUM", "requires TEXTURE_2D target");
10081 return;
10082 }
10083
10084 // Default target might be conceptually valid, but disallow it to avoid
10085 // accidents.
[email protected]370eaf12013-05-18 09:19:4910086 TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
10087 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:5110088 LOCAL_SET_GL_ERROR(
10089 GL_INVALID_OPERATION,
10090 "glReleaseTexImage2DCHROMIUM", "no texture bound");
[email protected]09d50362012-10-18 20:54:3710091 return;
10092 }
10093
10094 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10095 if (!gl_image) {
[email protected]ab09b612013-03-11 22:11:5110096 LOCAL_SET_GL_ERROR(
10097 GL_INVALID_OPERATION,
10098 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
[email protected]09d50362012-10-18 20:54:3710099 return;
10100 }
10101
10102 // Do nothing when image is not currently bound.
[email protected]370eaf12013-05-18 09:19:4910103 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
[email protected]09d50362012-10-18 20:54:3710104 return;
10105
[email protected]b8160812013-04-09 00:41:0410106 {
10107 ScopedGLErrorSuppressor suppressor(
10108 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", this);
10109 gl_image->ReleaseTexImage();
10110 }
[email protected]09d50362012-10-18 20:54:3710111
10112 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:4910113 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
[email protected]09d50362012-10-18 20:54:3710114 GL_RGBA, GL_UNSIGNED_BYTE, false);
10115}
[email protected]d2a0e1a2012-08-12 02:25:0110116
[email protected]94307712012-11-16 23:26:1110117error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510118 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
[email protected]94307712012-11-16 23:26:1110119 Bucket* bucket = GetBucket(c.bucket_id);
10120 if (!bucket || bucket->size() == 0) {
10121 return error::kInvalidArguments;
10122 }
10123 std::string command_name;
10124 if (!bucket->GetAsString(&command_name)) {
10125 return error::kInvalidArguments;
10126 }
[email protected]fb97b662013-02-20 23:02:1410127 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10128 if (!gpu_tracer_->Begin(command_name)) {
[email protected]ab09b612013-03-11 22:11:5110129 LOCAL_SET_GL_ERROR(
10130 GL_INVALID_OPERATION,
10131 "glTraceBeginCHROMIUM", "unable to create begin trace");
[email protected]fb97b662013-02-20 23:02:1410132 return error::kNoError;
10133 }
[email protected]94307712012-11-16 23:26:1110134 return error::kNoError;
10135}
10136
10137void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
[email protected]fb97b662013-02-20 23:02:1410138 if (gpu_tracer_->CurrentName().empty()) {
[email protected]ab09b612013-03-11 22:11:5110139 LOCAL_SET_GL_ERROR(
10140 GL_INVALID_OPERATION,
10141 "glTraceEndCHROMIUM", "no trace begin found");
[email protected]94307712012-11-16 23:26:1110142 return;
10143 }
[email protected]fb97b662013-02-20 23:02:1410144 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10145 gpu_tracer_->End();
[email protected]94307712012-11-16 23:26:1110146}
10147
[email protected]2f143d482013-03-14 18:04:4910148void GLES2DecoderImpl::DoDrawBuffersEXT(
10149 GLsizei count, const GLenum* bufs) {
10150 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10151 LOCAL_SET_GL_ERROR(
10152 GL_INVALID_VALUE,
10153 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10154 return;
10155 }
10156
10157 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10158 if (framebuffer) {
10159 for (GLsizei i = 0; i < count; ++i) {
10160 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10161 bufs[i] != GL_NONE) {
10162 LOCAL_SET_GL_ERROR(
10163 GL_INVALID_OPERATION,
10164 "glDrawBuffersEXT",
10165 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10166 return;
10167 }
10168 }
10169 glDrawBuffersARB(count, bufs);
10170 framebuffer->SetDrawBuffers(count, bufs);
10171 } else { // backbuffer
10172 if (count > 1 ||
10173 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10174 LOCAL_SET_GL_ERROR(
10175 GL_INVALID_OPERATION,
10176 "glDrawBuffersEXT",
10177 "more than one buffer or bufs not GL_NONE or GL_BACK");
10178 return;
10179 }
10180 GLenum mapped_buf = bufs[0];
10181 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10182 bufs[0] == GL_BACK) {
10183 mapped_buf = GL_COLOR_ATTACHMENT0;
10184 }
10185 glDrawBuffersARB(count, &mapped_buf);
10186 group_->set_draw_buffer(bufs[0]);
10187 }
10188}
10189
[email protected]32145a92012-12-17 09:01:5910190bool GLES2DecoderImpl::ValidateAsyncTransfer(
10191 const char* function_name,
[email protected]85a4ac22013-05-31 01:58:4710192 TextureRef* texture_ref,
[email protected]32145a92012-12-17 09:01:5910193 GLenum target,
10194 GLint level,
10195 const void * data) {
10196 // We only support async uploads to 2D textures for now.
10197 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:5110198 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
[email protected]32145a92012-12-17 09:01:5910199 return false;
10200 }
10201 // We only support uploads to level zero for now.
10202 if (level != 0) {
[email protected]ab09b612013-03-11 22:11:5110203 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
[email protected]32145a92012-12-17 09:01:5910204 return false;
10205 }
10206 // A transfer buffer must be bound, even for asyncTexImage2D.
10207 if (data == NULL) {
[email protected]ab09b612013-03-11 22:11:5110208 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
[email protected]32145a92012-12-17 09:01:5910209 return false;
10210 }
10211 // We only support one async transfer in progress.
[email protected]85a4ac22013-05-31 01:58:4710212 if (!texture_ref ||
10213 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:5110214 LOCAL_SET_GL_ERROR(
10215 GL_INVALID_OPERATION,
[email protected]32145a92012-12-17 09:01:5910216 function_name, "transfer already in progress");
10217 return false;
10218 }
10219 return true;
10220}
10221
[email protected]69023942012-11-30 19:57:1610222error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510223 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
[email protected]69023942012-11-30 19:57:1610224 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
[email protected]69023942012-11-30 19:57:1610225 GLenum target = static_cast<GLenum>(c.target);
10226 GLint level = static_cast<GLint>(c.level);
10227 GLint internal_format = static_cast<GLint>(c.internalformat);
10228 GLsizei width = static_cast<GLsizei>(c.width);
10229 GLsizei height = static_cast<GLsizei>(c.height);
10230 GLint border = static_cast<GLint>(c.border);
10231 GLenum format = static_cast<GLenum>(c.format);
10232 GLenum type = static_cast<GLenum>(c.type);
10233 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10234 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10235 uint32 pixels_size;
[email protected]32145a92012-12-17 09:01:5910236
10237 // TODO(epenner): Move this and copies of this memory validation
10238 // into ValidateTexImage2D step.
[email protected]69023942012-11-30 19:57:1610239 if (!GLES2Util::ComputeImageDataSizes(
10240 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10241 NULL)) {
10242 return error::kOutOfBounds;
10243 }
10244 const void* pixels = NULL;
10245 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10246 pixels = GetSharedMemoryAs<const void*>(
10247 pixels_shm_id, pixels_shm_offset, pixels_size);
10248 if (!pixels) {
10249 return error::kOutOfBounds;
10250 }
10251 }
10252
[email protected]32145a92012-12-17 09:01:5910253 // All the normal glTexSubImage2D validation.
10254 if (!ValidateTexImage2D(
10255 "glAsyncTexImage2DCHROMIUM", target, level, internal_format,
10256 width, height, border, format, type, pixels, pixels_size)) {
10257 return error::kNoError;
10258 }
10259
10260 // Extra async validation.
[email protected]370eaf12013-05-18 09:19:4910261 TextureRef* texture_ref = GetTextureInfoForTarget(target);
10262 Texture* texture = texture_ref->texture();
[email protected]32145a92012-12-17 09:01:5910263 if (!ValidateAsyncTransfer(
[email protected]85a4ac22013-05-31 01:58:4710264 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
[email protected]32145a92012-12-17 09:01:5910265 return error::kNoError;
10266
10267 // Don't allow async redefinition of a textures.
[email protected]02965c22013-03-09 02:40:0710268 if (texture->IsDefined()) {
[email protected]ab09b612013-03-11 22:11:5110269 LOCAL_SET_GL_ERROR(
10270 GL_INVALID_OPERATION,
[email protected]32145a92012-12-17 09:01:5910271 "glAsyncTexImage2DCHROMIUM", "already defined");
10272 return error::kNoError;
10273 }
10274
[email protected]7989c9e2013-01-23 06:39:2610275 if (!EnsureGPUMemoryAvailable(pixels_size)) {
[email protected]ab09b612013-03-11 22:11:5110276 LOCAL_SET_GL_ERROR(
10277 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
[email protected]7989c9e2013-01-23 06:39:2610278 return error::kNoError;
10279 }
10280
[email protected]32145a92012-12-17 09:01:5910281 // We know the memory/size is safe, so get the real shared memory since
10282 // it might need to be duped to prevent use-after-free of the memory.
[email protected]16ccec12013-02-28 03:40:2110283 gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id);
[email protected]32145a92012-12-17 09:01:5910284 base::SharedMemory* shared_memory = buffer.shared_memory;
10285 uint32 shm_size = buffer.size;
10286 uint32 shm_data_offset = c.pixels_shm_offset;
10287 uint32 shm_data_size = pixels_size;
10288
[email protected]5b3a8e02013-03-13 05:36:4410289 // Setup the parameters.
[email protected]8f1d2aa2013-05-10 23:45:3810290 AsyncTexImage2DParams tex_params = {
10291 target, level, static_cast<GLenum>(internal_format),
10292 width, height, border, format, type};
10293 AsyncMemoryParams mem_params = {
10294 shared_memory, shm_size, shm_data_offset, shm_data_size};
[email protected]32145a92012-12-17 09:01:5910295
[email protected]5b3a8e02013-03-13 05:36:4410296 // Set up the async state if needed, and make the texture
10297 // immutable so the async state stays valid. The level info
10298 // is set up lazily when the transfer completes.
[email protected]896425e2013-06-12 17:27:1810299 AsyncPixelTransferDelegate* delegate =
10300 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10301 tex_params);
[email protected]5b3a8e02013-03-13 05:36:4410302 texture->SetImmutable(true);
[email protected]32145a92012-12-17 09:01:5910303
[email protected]896425e2013-06-12 17:27:1810304 delegate->AsyncTexImage2D(
[email protected]5b3a8e02013-03-13 05:36:4410305 tex_params,
10306 mem_params,
10307 base::Bind(&TextureManager::SetLevelInfoFromParams,
[email protected]370eaf12013-05-18 09:19:4910308 // The callback is only invoked if the transfer delegate still
10309 // exists, which implies through manager->texture_ref->state
[email protected]5b3a8e02013-03-13 05:36:4410310 // ownership that both of these pointers are valid.
10311 base::Unretained(texture_manager()),
[email protected]370eaf12013-05-18 09:19:4910312 base::Unretained(texture_ref),
[email protected]5b3a8e02013-03-13 05:36:4410313 tex_params));
[email protected]f598f422012-12-07 08:30:0310314 return error::kNoError;
[email protected]69023942012-11-30 19:57:1610315}
10316
10317error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510318 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
[email protected]69023942012-11-30 19:57:1610319 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
[email protected]69023942012-11-30 19:57:1610320 GLenum target = static_cast<GLenum>(c.target);
10321 GLint level = static_cast<GLint>(c.level);
10322 GLint xoffset = static_cast<GLint>(c.xoffset);
10323 GLint yoffset = static_cast<GLint>(c.yoffset);
10324 GLsizei width = static_cast<GLsizei>(c.width);
10325 GLsizei height = static_cast<GLsizei>(c.height);
10326 GLenum format = static_cast<GLenum>(c.format);
10327 GLenum type = static_cast<GLenum>(c.type);
[email protected]32145a92012-12-17 09:01:5910328
10329 // TODO(epenner): Move this and copies of this memory validation
10330 // into ValidateTexSubImage2D step.
[email protected]69023942012-11-30 19:57:1610331 uint32 data_size;
10332 if (!GLES2Util::ComputeImageDataSizes(
10333 width, height, format, type, state_.unpack_alignment, &data_size,
10334 NULL, NULL)) {
10335 return error::kOutOfBounds;
10336 }
10337 const void* pixels = GetSharedMemoryAs<const void*>(
10338 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]32145a92012-12-17 09:01:5910339
10340 // All the normal glTexSubImage2D validation.
10341 error::Error error = error::kNoError;
10342 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10343 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10344 return error;
[email protected]69023942012-11-30 19:57:1610345 }
10346
[email protected]32145a92012-12-17 09:01:5910347 // Extra async validation.
[email protected]370eaf12013-05-18 09:19:4910348 TextureRef* texture_ref = GetTextureInfoForTarget(target);
10349 Texture* texture = texture_ref->texture();
[email protected]32145a92012-12-17 09:01:5910350 if (!ValidateAsyncTransfer(
[email protected]85a4ac22013-05-31 01:58:4710351 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
[email protected]32145a92012-12-17 09:01:5910352 return error::kNoError;
10353
10354 // Guarantee async textures are always 'cleared' as follows:
10355 // - AsyncTexImage2D can not redefine an existing texture
10356 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10357 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10358 // - Textures become immutable after an async call.
10359 // This way we know in all cases that an async texture is always clear.
[email protected]02965c22013-03-09 02:40:0710360 if (!texture->SafeToRenderFrom()) {
[email protected]370eaf12013-05-18 09:19:4910361 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10362 target, level)) {
[email protected]ab09b612013-03-11 22:11:5110363 LOCAL_SET_GL_ERROR(
10364 GL_OUT_OF_MEMORY,
[email protected]b04e24c2013-01-08 18:35:2510365 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
[email protected]32145a92012-12-17 09:01:5910366 return error::kNoError;
10367 }
10368 }
10369
10370 // We know the memory/size is safe, so get the real shared memory since
10371 // it might need to be duped to prevent use-after-free of the memory.
[email protected]16ccec12013-02-28 03:40:2110372 gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id);
[email protected]32145a92012-12-17 09:01:5910373 base::SharedMemory* shared_memory = buffer.shared_memory;
10374 uint32 shm_size = buffer.size;
10375 uint32 shm_data_offset = c.data_shm_offset;
10376 uint32 shm_data_size = data_size;
10377
[email protected]5b3a8e02013-03-13 05:36:4410378 // Setup the parameters.
[email protected]2a7568a2013-05-09 23:12:0310379 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
[email protected]32145a92012-12-17 09:01:5910380 width, height, format, type};
[email protected]2a7568a2013-05-09 23:12:0310381 AsyncMemoryParams mem_params = {shared_memory, shm_size,
[email protected]32145a92012-12-17 09:01:5910382 shm_data_offset, shm_data_size};
[email protected]896425e2013-06-12 17:27:1810383 AsyncPixelTransferDelegate* delegate =
10384 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10385 if (!delegate) {
[email protected]5b3a8e02013-03-13 05:36:4410386 // TODO(epenner): We may want to enforce exclusive use
10387 // of async APIs in which case this should become an error,
10388 // (the texture should have been async defined).
[email protected]2a7568a2013-05-09 23:12:0310389 AsyncTexImage2DParams define_params = {target, level,
[email protected]5b3a8e02013-03-13 05:36:4410390 0, 0, 0, 0, 0, 0};
10391 texture->GetLevelSize(target, level, &define_params.width,
10392 &define_params.height);
10393 texture->GetLevelType(target, level, &define_params.type,
10394 &define_params.internal_format);
10395 // Set up the async state if needed, and make the texture
10396 // immutable so the async state stays valid.
[email protected]896425e2013-06-12 17:27:1810397 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
[email protected]85a4ac22013-05-31 01:58:4710398 texture_ref, define_params);
[email protected]5b3a8e02013-03-13 05:36:4410399 texture->SetImmutable(true);
10400 }
10401
[email protected]896425e2013-06-12 17:27:1810402 delegate->AsyncTexSubImage2D(tex_params, mem_params);
[email protected]32145a92012-12-17 09:01:5910403 return error::kNoError;
[email protected]69023942012-11-30 19:57:1610404}
10405
[email protected]a00c1f742013-03-05 17:02:1610406error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10407 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10408 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10409 GLenum target = static_cast<GLenum>(c.target);
10410
10411 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:5110412 LOCAL_SET_GL_ERROR(
10413 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
[email protected]a00c1f742013-03-05 17:02:1610414 return error::kNoError;
10415 }
[email protected]370eaf12013-05-18 09:19:4910416 TextureRef* texture_ref = GetTextureInfoForTarget(target);
10417 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:5110418 LOCAL_SET_GL_ERROR(
10419 GL_INVALID_OPERATION,
10420 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
[email protected]a00c1f742013-03-05 17:02:1610421 return error::kNoError;
10422 }
[email protected]896425e2013-06-12 17:27:1810423 AsyncPixelTransferDelegate* delegate =
10424 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10425 if (!delegate) {
[email protected]370eaf12013-05-18 09:19:4910426 LOCAL_SET_GL_ERROR(
10427 GL_INVALID_OPERATION,
10428 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10429 return error::kNoError;
10430 }
[email protected]896425e2013-06-12 17:27:1810431 delegate->WaitForTransferCompletion();
[email protected]69a8701e2013-03-07 21:31:0910432 ProcessFinishedAsyncTransfers();
[email protected]a00c1f742013-03-05 17:02:1610433 return error::kNoError;
10434}
10435
[email protected]96449d2c2009-11-25 00:01:3210436// Include the auto-generated part of this file. We split this because it means
10437// we can easily edit the non-auto generated parts right here in this file
10438// instead of having to edit some template or the code generator.
10439#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10440
10441} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:2510442} // namespace gpu