blob: 4633580ed724699cb4f31e39b9f486911b15e395 [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]9d37f062011-11-22 01:24:5217#include "base/bind.h"
[email protected]e844ae22012-01-14 03:36:2618#include "base/command_line.h"
[email protected]1078f912011-12-23 13:12:1419#include "base/debug/trace_event.h"
[email protected]3b63f8f42011-03-28 01:54:1520#include "base/memory/scoped_ptr.h"
[email protected]f4390962013-06-11 07:29:2221#include "base/strings/string_number_conversions.h"
[email protected]d37231fa2010-04-09 21:16:0222#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3223#define GLES2_GPU_SERVICE 1
[email protected]f4390962013-06-11 07:29:2224#include "gpu/command_buffer/common/debug_marker_manager.h"
[email protected]96449d2c2009-11-25 00:01:3225#include "gpu/command_buffer/common/gles2_cmd_format.h"
26#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1027#include "gpu/command_buffer/common/id_allocator.h"
[email protected]2ad674132013-06-05 07:48:5128#include "gpu/command_buffer/common/mailbox.h"
[email protected]f4390962013-06-11 07:29:2229#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
30#include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
[email protected]3916c97e2010-02-25 03:20:5031#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3232#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5033#include "gpu/command_buffer/service/context_group.h"
[email protected]e259eb412012-10-13 05:47:2434#include "gpu/command_buffer/service/context_state.h"
[email protected]d3eba342013-04-18 21:11:5035#include "gpu/command_buffer/service/error_state.h"
[email protected]915a59a12010-09-30 21:29:1136#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5837#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3238#include "gpu/command_buffer/service/gl_utils.h"
[email protected]43410e92012-04-20 17:06:2839#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
[email protected]ba3176a2009-12-16 18:19:4640#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]8f9b8dd2013-09-12 18:05:1341#include "gpu/command_buffer/service/gpu_state_tracer.h"
[email protected]e844ae22012-01-14 03:36:2642#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]fb97b662013-02-20 23:02:1443#include "gpu/command_buffer/service/gpu_tracer.h"
[email protected]09d50362012-10-18 20:54:3744#include "gpu/command_buffer/service/image_manager.h"
[email protected]78b514b2012-05-01 21:50:5945#include "gpu/command_buffer/service/mailbox_manager.h"
[email protected]ff6493f2012-07-31 19:52:2546#include "gpu/command_buffer/service/memory_tracking.h"
[email protected]a93bb842010-02-16 23:03:4747#include "gpu/command_buffer/service/program_manager.h"
[email protected]882ba1e22012-03-08 19:02:5348#include "gpu/command_buffer/service/query_manager.h"
[email protected]a25fa872010-03-25 02:57:5849#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4750#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4551#include "gpu/command_buffer/service/shader_translator.h"
[email protected]87fb6ab2012-06-13 22:28:0452#include "gpu/command_buffer/service/shader_translator_cache.h"
[email protected]b0af4f52011-09-28 22:04:4253#include "gpu/command_buffer/service/stream_texture.h"
54#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]a93bb842010-02-16 23:03:4755#include "gpu/command_buffer/service/texture_manager.h"
[email protected]944b62f32012-09-27 02:20:4656#include "gpu/command_buffer/service/vertex_array_manager.h"
[email protected]f4390962013-06-11 07:29:2257#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]d8bc3ec2013-03-07 06:28:4058#include "ui/gl/gl_bindings.h"
[email protected]5a36dc132013-07-23 23:17:5559#include "ui/gl/gl_fence.h"
[email protected]09d50362012-10-18 20:54:3760#include "ui/gl/gl_image.h"
[email protected]c9e2cbbb2012-05-12 21:17:2761#include "ui/gl/gl_implementation.h"
62#include "ui/gl/gl_surface.h"
[email protected]423e644f2013-06-19 00:48:2763
[email protected]e51bdf32011-11-23 22:21:4664#if defined(OS_MACOSX)
[email protected]423e644f2013-06-19 00:48:2765#include "ui/gl/io_surface_support_mac.h"
[email protected]e51bdf32011-11-23 22:21:4666#endif
[email protected]de17df392010-04-23 21:09:4167
[email protected]6eb775352013-08-27 05:57:1668#if defined(OS_WIN)
69#include "base/win/win_util.h"
70#endif
71
[email protected]693ca512012-11-13 18:09:1372// TODO(zmo): we can't include "City.h" due to type def conflicts.
73extern uint64 CityHash64(const char*, size_t);
74
[email protected]a7a27ace2009-12-12 00:11:2575namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3276namespace gles2 {
77
[email protected]f0d74742011-10-03 16:31:0478namespace {
[email protected]693ca512012-11-13 18:09:1379
[email protected]f0d74742011-10-03 16:31:0480static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
[email protected]70dc60932013-06-04 03:33:4981static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
[email protected]aff39ac82013-06-08 04:53:1382static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
[email protected]693ca512012-11-13 18:09:1383
[email protected]3d944a82013-02-12 19:09:0284#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
[email protected]693ca512012-11-13 18:09:1385khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
86 return static_cast<khronos_uint64_t>(
87 CityHash64(name, static_cast<size_t>(len)));
88}
[email protected]3d944a82013-02-12 19:09:0289#endif
[email protected]693ca512012-11-13 18:09:1390
[email protected]448e459e2013-06-12 17:00:4191static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
92 GLint rangeMax,
93 GLint precision) {
94 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
95}
96
[email protected]8dc1bf92013-03-12 03:58:2197static void GetShaderPrecisionFormatImpl(GLenum shader_type,
98 GLenum precision_type,
99 GLint *range, GLint *precision) {
100 switch (precision_type) {
101 case GL_LOW_INT:
102 case GL_MEDIUM_INT:
103 case GL_HIGH_INT:
104 // These values are for a 32-bit twos-complement integer format.
105 range[0] = 31;
106 range[1] = 30;
107 *precision = 0;
108 break;
109 case GL_LOW_FLOAT:
110 case GL_MEDIUM_FLOAT:
111 case GL_HIGH_FLOAT:
112 // These values are for an IEEE single-precision floating-point format.
113 range[0] = 127;
114 range[1] = 127;
115 *precision = 23;
116 break;
117 default:
118 NOTREACHED();
119 break;
120 }
121
[email protected]8af4d5e2013-03-15 23:55:33122 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
123 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
[email protected]8dc1bf92013-03-12 03:58:21124 // This function is sometimes defined even though it's really just
125 // a stub, so we need to set range and precision as if it weren't
126 // defined before calling it.
[email protected]501b57402013-03-14 22:21:44127 // On Mac OS with some GPUs, calling this generates a
128 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
129 // platforms.
[email protected]8dc1bf92013-03-12 03:58:21130 glGetShaderPrecisionFormat(shader_type, precision_type,
131 range, precision);
[email protected]448e459e2013-06-12 17:00:41132
133 // TODO(brianderson): Make the following official workarounds.
134
135 // Some drivers have bugs where they report the ranges as a negative number.
136 // Taking the absolute value here shouldn't hurt because negative numbers
137 // aren't expected anyway.
138 range[0] = abs(range[0]);
139 range[1] = abs(range[1]);
140
141 // If the driver reports a precision for highp float that isn't actually
142 // highp, don't pretend like it's supported because shader compilation will
143 // fail anyway.
144 if (precision_type == GL_HIGH_FLOAT &&
145 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
146 range[0] = 0;
147 range[1] = 0;
148 *precision = 0;
149 }
[email protected]8dc1bf92013-03-12 03:58:21150 }
151}
152
[email protected]b04e24c2013-01-08 18:35:25153} // namespace
[email protected]f0d74742011-10-03 16:31:04154
[email protected]6217d392010-03-25 22:08:35155class GLES2DecoderImpl;
156
[email protected]ab09b612013-03-11 22:11:51157// Local versions of the SET_GL_ERROR macros
158#define LOCAL_SET_GL_ERROR(error, function_name, msg) \
[email protected]d3eba342013-04-18 21:11:50159 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
[email protected]ab09b612013-03-11 22:11:51160#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
[email protected]d3eba342013-04-18 21:11:50161 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
162 function_name, value, label)
[email protected]ab09b612013-03-11 22:11:51163#define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
[email protected]d3eba342013-04-18 21:11:50164 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
165 function_name, pname)
[email protected]ab09b612013-03-11 22:11:51166#define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
[email protected]d3eba342013-04-18 21:11:50167 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
168 function_name)
[email protected]ab09b612013-03-11 22:11:51169#define LOCAL_PEEK_GL_ERROR(function_name) \
[email protected]d3eba342013-04-18 21:11:50170 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
[email protected]ab09b612013-03-11 22:11:51171#define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
[email protected]d3eba342013-04-18 21:11:50172 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
[email protected]ab09b612013-03-11 22:11:51173#define LOCAL_PERFORMANCE_WARNING(msg) \
174 PerformanceWarning(__FILE__, __LINE__, msg)
175#define LOCAL_RENDER_WARNING(msg) \
176 RenderWarning(__FILE__, __LINE__, msg)
177
[email protected]07f54fcc2009-12-22 02:46:30178// Check that certain assumptions the code makes are true. There are places in
179// the code where shared memory is passed direclty to GL. Example, glUniformiv,
180// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
181// a few others) are 32bits. If they are not 32bits the code will have to change
182// to call those GL functions with service side memory and then copy the results
183// to shared memory, converting the sizes.
184COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
185 GLint_not_same_size_as_uint32);
186COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
187 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:37188COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
189 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:30190
[email protected]43f28f832010-02-03 02:28:48191// TODO(kbr): the use of this anonymous namespace core dumps the
192// linker on Mac OS X 10.6 when the symbol ordering file is used
193// namespace {
[email protected]96449d2c2009-11-25 00:01:32194
195// Returns the address of the first byte after a struct.
196template <typename T>
197const void* AddressAfterStruct(const T& pod) {
198 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
199}
200
[email protected]07f54fcc2009-12-22 02:46:30201// Returns the address of the frst byte after the struct or NULL if size >
202// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:32203template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:30204RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
205 uint32 size,
206 uint32 immediate_data_size) {
207 return (size <= immediate_data_size) ?
208 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
209 NULL;
[email protected]96449d2c2009-11-25 00:01:32210}
211
[email protected]07f54fcc2009-12-22 02:46:30212// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18213bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32214 GLuint count,
215 size_t size,
[email protected]a76b0052010-03-05 00:33:18216 unsigned int elements_per_unit,
217 uint32* dst) {
218 uint32 value;
219 if (!SafeMultiplyUint32(count, size, &value)) {
220 return false;
221 }
222 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
223 return false;
224 }
225 *dst = value;
226 return true;
[email protected]96449d2c2009-11-25 00:01:32227}
228
229// A struct to hold info about each command.
230struct CommandInfo {
231 int arg_flags; // How to handle the arguments for this command
232 int arg_count; // How many arguments are expected for this command.
233};
234
235// A table of CommandInfo for all the commands.
236const CommandInfo g_command_info[] = {
[email protected]ed9f9cd2013-02-27 21:12:35237 #define GLES2_CMD_OP(name) { \
238 cmds::name::kArgFlags, \
239 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
[email protected]96449d2c2009-11-25 00:01:32240
241 GLES2_COMMAND_LIST(GLES2_CMD_OP)
242
243 #undef GLES2_CMD_OP
244};
245
[email protected]258a3313f2011-10-18 20:13:57246// Return true if a character belongs to the ASCII subset as defined in
247// GLSL ES 1.0 spec section 3.1.
248static bool CharacterIsValidForGLES(unsigned char c) {
249 // Printing characters are valid except " $ ` @ \ ' DEL.
250 if (c >= 32 && c <= 126 &&
251 c != '"' &&
252 c != '$' &&
253 c != '`' &&
254 c != '@' &&
255 c != '\\' &&
256 c != '\'') {
257 return true;
258 }
259 // Horizontal tab, line feed, vertical tab, form feed, carriage return
260 // are also valid.
261 if (c >= 9 && c <= 13) {
262 return true;
263 }
264
265 return false;
266}
267
268static bool StringIsValidForGLES(const char* str) {
269 for (; *str; ++str) {
270 if (!CharacterIsValidForGLES(*str)) {
271 return false;
272 }
273 }
274 return true;
275}
276
[email protected]297ca1c2011-06-20 23:08:46277// Wrapper for glEnable/glDisable that doesn't suck.
278static void EnableDisable(GLenum pname, bool enable) {
279 if (enable) {
280 glEnable(pname);
281 } else {
282 glDisable(pname);
283 }
284}
285
[email protected]6217d392010-03-25 22:08:35286// This class prevents any GL errors that occur when it is in scope from
287// being reported to the client.
288class ScopedGLErrorSuppressor {
289 public:
[email protected]ab09b612013-03-11 22:11:51290 explicit ScopedGLErrorSuppressor(
[email protected]40621eb52013-10-08 15:40:30291 const char* function_name, ErrorState* error_state);
[email protected]6217d392010-03-25 22:08:35292 ~ScopedGLErrorSuppressor();
293 private:
[email protected]ab09b612013-03-11 22:11:51294 const char* function_name_;
[email protected]40621eb52013-10-08 15:40:30295 ErrorState* error_state_;
[email protected]6217d392010-03-25 22:08:35296 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
297};
298
299// Temporarily changes a decoder's bound 2D texture and restore it when this
300// object goes out of scope. Also temporarily switches to using active texture
301// unit zero in case the client has changed that to something invalid.
302class ScopedTexture2DBinder {
303 public:
[email protected]ce296892013-10-24 22:04:36304 ScopedTexture2DBinder(ContextState* state, GLuint id);
[email protected]6217d392010-03-25 22:08:35305 ~ScopedTexture2DBinder();
306
307 private:
[email protected]ce296892013-10-24 22:04:36308 ContextState* state_;
[email protected]6217d392010-03-25 22:08:35309 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
310};
311
312// Temporarily changes a decoder's bound render buffer and restore it when this
313// object goes out of scope.
314class ScopedRenderBufferBinder {
315 public:
[email protected]18e785a2013-10-09 03:29:41316 ScopedRenderBufferBinder(ContextState* state, GLuint id);
[email protected]6217d392010-03-25 22:08:35317 ~ScopedRenderBufferBinder();
318
319 private:
[email protected]18e785a2013-10-09 03:29:41320 ContextState* state_;
[email protected]6217d392010-03-25 22:08:35321 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
322};
323
324// Temporarily changes a decoder's bound frame buffer and restore it when this
325// object goes out of scope.
326class ScopedFrameBufferBinder {
327 public:
328 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
329 ~ScopedFrameBufferBinder();
330
331 private:
332 GLES2DecoderImpl* decoder_;
333 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
334};
335
[email protected]34ff8b0c2010-10-01 20:06:02336// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52337// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27338// if it is bound or enforce_internal_framebuffer is true. If internal is
339// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02340class ScopedResolvedFrameBufferBinder {
341 public:
[email protected]e7e38032011-07-26 17:25:25342 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27343 bool enforce_internal_framebuffer,
344 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02345 ~ScopedResolvedFrameBufferBinder();
346
347 private:
348 GLES2DecoderImpl* decoder_;
349 bool resolve_and_bind_;
350 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
351};
352
[email protected]6217d392010-03-25 22:08:35353// Encapsulates an OpenGL texture.
[email protected]ed9f9cd2013-02-27 21:12:35354class BackTexture {
[email protected]6217d392010-03-25 22:08:35355 public:
[email protected]ce296892013-10-24 22:04:36356 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
[email protected]ed9f9cd2013-02-27 21:12:35357 ~BackTexture();
[email protected]6217d392010-03-25 22:08:35358
359 // Create a new render texture.
360 void Create();
361
362 // Set the initial size and format of a render texture or resize it.
[email protected]678a73f2012-12-19 19:22:09363 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
[email protected]6217d392010-03-25 22:08:35364
365 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58366 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35367
368 // Destroy the render texture. This must be explicitly called before
369 // destroying this object.
370 void Destroy();
371
[email protected]97872062010-11-03 19:07:05372 // Invalidate the texture. This can be used when a context is lost and it is
373 // not possible to make it current in order to free the resource.
374 void Invalidate();
375
[email protected]6217d392010-03-25 22:08:35376 GLuint id() const {
377 return id_;
378 }
379
[email protected]d37231fa2010-04-09 21:16:02380 gfx::Size size() const {
381 return size_;
382 }
383
[email protected]1078f912011-12-23 13:12:14384 size_t estimated_size() const {
[email protected]ff6493f2012-07-31 19:52:25385 return memory_tracker_.GetMemRepresented();
[email protected]1078f912011-12-23 13:12:14386 }
387
[email protected]6217d392010-03-25 22:08:35388 private:
[email protected]ff6493f2012-07-31 19:52:25389 MemoryTypeTracker memory_tracker_;
[email protected]ce296892013-10-24 22:04:36390 ContextState* state_;
[email protected]68e81a4a62012-12-13 01:16:48391 size_t bytes_allocated_;
[email protected]6217d392010-03-25 22:08:35392 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02393 gfx::Size size_;
[email protected]ed9f9cd2013-02-27 21:12:35394 DISALLOW_COPY_AND_ASSIGN(BackTexture);
[email protected]6217d392010-03-25 22:08:35395};
396
397// Encapsulates an OpenGL render buffer of any format.
[email protected]ed9f9cd2013-02-27 21:12:35398class BackRenderbuffer {
[email protected]6217d392010-03-25 22:08:35399 public:
[email protected]d5a28e452013-10-10 01:01:40400 explicit BackRenderbuffer(
401 RenderbufferManager* renderbuffer_manager,
402 MemoryTracker* memory_tracker,
403 ContextState* state);
[email protected]ed9f9cd2013-02-27 21:12:35404 ~BackRenderbuffer();
[email protected]6217d392010-03-25 22:08:35405
406 // Create a new render buffer.
407 void Create();
408
409 // Set the initial size and format of a render buffer or resize it.
[email protected]f42f05b2013-11-15 21:46:18410 bool AllocateStorage(const FeatureInfo* feature_info,
411 const gfx::Size& size,
412 GLenum format,
413 GLsizei samples);
[email protected]6217d392010-03-25 22:08:35414
415 // Destroy the render buffer. This must be explicitly called before destroying
416 // this object.
417 void Destroy();
418
[email protected]97872062010-11-03 19:07:05419 // Invalidate the render buffer. This can be used when a context is lost and
420 // it is not possible to make it current in order to free the resource.
421 void Invalidate();
422
[email protected]6217d392010-03-25 22:08:35423 GLuint id() const {
424 return id_;
425 }
426
[email protected]1078f912011-12-23 13:12:14427 size_t estimated_size() const {
[email protected]ff6493f2012-07-31 19:52:25428 return memory_tracker_.GetMemRepresented();
[email protected]1078f912011-12-23 13:12:14429 }
430
[email protected]6217d392010-03-25 22:08:35431 private:
[email protected]d5a28e452013-10-10 01:01:40432 RenderbufferManager* renderbuffer_manager_;
[email protected]ff6493f2012-07-31 19:52:25433 MemoryTypeTracker memory_tracker_;
[email protected]d5a28e452013-10-10 01:01:40434 ContextState* state_;
[email protected]68e81a4a62012-12-13 01:16:48435 size_t bytes_allocated_;
[email protected]6217d392010-03-25 22:08:35436 GLuint id_;
[email protected]ed9f9cd2013-02-27 21:12:35437 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
[email protected]6217d392010-03-25 22:08:35438};
439
440// Encapsulates an OpenGL frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35441class BackFramebuffer {
[email protected]6217d392010-03-25 22:08:35442 public:
[email protected]ed9f9cd2013-02-27 21:12:35443 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
444 ~BackFramebuffer();
[email protected]6217d392010-03-25 22:08:35445
446 // Create a new frame buffer.
447 void Create();
448
449 // Attach a color render buffer to a frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35450 void AttachRenderTexture(BackTexture* texture);
[email protected]6217d392010-03-25 22:08:35451
[email protected]b9363b22010-06-09 22:06:15452 // Attach a render buffer to a frame buffer. Note that this unbinds any
453 // currently bound frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35454 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35455
[email protected]6217d392010-03-25 22:08:35456 // Destroy the frame buffer. This must be explicitly called before destroying
457 // this object.
458 void Destroy();
459
[email protected]97872062010-11-03 19:07:05460 // Invalidate the frame buffer. This can be used when a context is lost and it
461 // is not possible to make it current in order to free the resource.
462 void Invalidate();
463
[email protected]6217d392010-03-25 22:08:35464 // See glCheckFramebufferStatusEXT.
465 GLenum CheckStatus();
466
467 GLuint id() const {
468 return id_;
469 }
470
471 private:
472 GLES2DecoderImpl* decoder_;
473 GLuint id_;
[email protected]ed9f9cd2013-02-27 21:12:35474 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
[email protected]6217d392010-03-25 22:08:35475};
[email protected]34ff8b0c2010-10-01 20:06:02476
[email protected]5a36dc132013-07-23 23:17:55477struct FenceCallback {
478 explicit FenceCallback()
479 : fence(gfx::GLFence::Create()) {
480 DCHECK(fence);
481 }
482 void AddCallback(base::Closure cb) {
483 callbacks.push_back(cb);
484 }
485 std::vector<base::Closure> callbacks;
486 scoped_ptr<gfx::GLFence> fence;
487};
488
489
[email protected]43f28f832010-02-03 02:28:48490// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32491
[email protected]ddb1e5a2010-12-13 20:10:45492bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
493 uint32* service_texture_id) {
494 return false;
495}
496
[email protected]a3ded6d2010-10-19 06:44:39497GLES2Decoder::GLES2Decoder()
[email protected]55e136f2013-04-03 18:50:06498 : initialized_(false),
499 debug_(false),
[email protected]1d82e822013-04-10 21:32:32500 log_commands_(false) {
[email protected]96449d2c2009-11-25 00:01:32501}
502
[email protected]3916c97e2010-02-25 03:20:50503GLES2Decoder::~GLES2Decoder() {
504}
505
[email protected]f39f4b3f2010-05-12 17:04:08506// This class implements GLES2Decoder so we don't have to expose all the GLES2
507// cmd stuff to outside this class.
[email protected]91c94eb2013-10-22 10:32:54508class GLES2DecoderImpl : public GLES2Decoder,
509 public FramebufferManager::TextureDetachObserver {
[email protected]f39f4b3f2010-05-12 17:04:08510 public:
[email protected]476ccb72012-12-06 15:52:52511 // Used by PrepForSetUniformByLocation to validate types.
512 struct BaseUniformInfo {
513 const GLenum* const valid_types;
514 size_t num_valid_types;
515 };
516
[email protected]aa7666122011-09-02 19:45:52517 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]b8e97b62012-09-30 15:09:00518 virtual ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08519
[email protected]96449d2c2009-11-25 00:01:32520 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14521 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50522 unsigned int arg_count,
[email protected]b8e97b62012-09-30 15:09:00523 const void* args) OVERRIDE;
[email protected]96449d2c2009-11-25 00:01:32524
525 // Overridden from AsyncAPIInterface.
[email protected]b8e97b62012-09-30 15:09:00526 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
[email protected]96449d2c2009-11-25 00:01:32527
528 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38529 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
530 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:23531 bool offscreen,
[email protected]6217d392010-03-25 22:08:35532 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29533 const DisallowedFeatures& disallowed_features,
[email protected]b8e97b62012-09-30 15:09:00534 const std::vector<int32>& attribs) OVERRIDE;
535 virtual void Destroy(bool have_context) OVERRIDE;
[email protected]63c9b052012-05-17 18:27:38536 virtual void SetSurface(
537 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
[email protected]2ad674132013-06-05 07:48:51538 virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
[email protected]b8e97b62012-09-30 15:09:00539 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
[email protected]9a5afa432011-07-22 18:16:39540 void UpdateParentTextureInfo();
[email protected]b8e97b62012-09-30 15:09:00541 virtual bool MakeCurrent() OVERRIDE;
542 virtual void ReleaseCurrent() OVERRIDE;
543 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
544 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
545 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
[email protected]1868a342012-11-07 15:56:02546 virtual void RestoreState() const OVERRIDE;
[email protected]29a4d902013-02-26 20:18:06547
548 virtual void RestoreActiveTexture() const OVERRIDE {
549 state_.RestoreActiveTexture();
550 }
[email protected]217004512013-05-10 21:25:55551 virtual void RestoreAllTextureUnitBindings() const OVERRIDE {
552 state_.RestoreAllTextureUnitBindings();
553 }
[email protected]29a4d902013-02-26 20:18:06554 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
555 state_.RestoreAttribute(index);
556 }
557 virtual void RestoreBufferBindings() const OVERRIDE {
558 state_.RestoreBufferBindings();
559 }
560 virtual void RestoreGlobalState() const OVERRIDE {
561 state_.RestoreGlobalState();
562 }
563 virtual void RestoreProgramBindings() const OVERRIDE {
564 state_.RestoreProgramBindings();
565 }
566 virtual void RestoreRenderbufferBindings() const OVERRIDE {
567 state_.RestoreRenderbufferBindings();
568 }
569 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
570 state_.RestoreTextureUnitBindings(unit);
571 }
572 virtual void RestoreFramebufferBindings() const OVERRIDE;
573 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
574
[email protected]b8e97b62012-09-30 15:09:00575 virtual QueryManager* GetQueryManager() OVERRIDE {
576 return query_manager_.get();
577 }
578 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
[email protected]944b62f32012-09-27 02:20:46579 return vertex_array_manager_.get();
580 }
[email protected]b8e97b62012-09-30 15:09:00581 virtual bool ProcessPendingQueries() OVERRIDE;
[email protected]2b1767cf2013-03-16 09:25:05582 virtual bool HasMoreIdleWork() OVERRIDE;
583 virtual void PerformIdleWork() OVERRIDE;
[email protected]43f28f832010-02-03 02:28:48584
[email protected]5a36dc132013-07-23 23:17:55585 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
586
[email protected]9d37f062011-11-22 01:24:52587 virtual void SetResizeCallback(
[email protected]729c0b42013-05-26 02:05:07588 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
[email protected]22f320a2011-08-30 01:17:00589
[email protected]1d82e822013-04-10 21:32:32590 virtual Logger* GetLogger() OVERRIDE;
[email protected]d3eba342013-04-18 21:11:50591 virtual ErrorState* GetErrorState() OVERRIDE;
[email protected]1d82e822013-04-10 21:32:32592
[email protected]e3932abb2013-03-13 00:01:37593 virtual void SetShaderCacheCallback(
594 const ShaderCacheCallback& callback) OVERRIDE;
[email protected]840a7e462013-02-27 01:29:51595 virtual void SetWaitSyncPointCallback(
596 const WaitSyncPointCallback& callback) OVERRIDE;
[email protected]22f320a2011-08-30 01:17:00597
[email protected]85a4ac22013-05-31 01:58:47598 virtual AsyncPixelTransferManager*
599 GetAsyncPixelTransferManager() OVERRIDE;
600 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
[email protected]498b5c072013-06-04 19:30:07601 virtual void SetAsyncPixelTransferManagerForTest(
602 AsyncPixelTransferManager* manager) OVERRIDE;
[email protected]69a8701e2013-03-07 21:31:09603 void ProcessFinishedAsyncTransfers();
[email protected]32145a92012-12-17 09:01:59604
[email protected]1318e922010-09-17 22:03:16605 virtual bool GetServiceTextureId(uint32 client_texture_id,
[email protected]b8e97b62012-09-30 15:09:00606 uint32* service_texture_id) OVERRIDE;
[email protected]43f28f832010-02-03 02:28:48607
[email protected]63b465922012-09-06 02:04:52608 virtual uint32 GetTextureUploadCount() OVERRIDE;
609 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
610 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
[email protected]dc25dda2012-09-27 21:36:30611 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
[email protected]63b465922012-09-06 02:04:52612
[email protected]8e3e0662010-08-23 18:46:30613 // Restores the current state to the user's settings.
614 void RestoreCurrentFramebufferBindings();
[email protected]8e3e0662010-08-23 18:46:30615
[email protected]297ca1c2011-06-20 23:08:46616 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
617 void ApplyDirtyState();
618
619 // These check the state of the currently bound framebuffer or the
620 // backbuffer if no framebuffer is bound.
[email protected]f3b191b2013-06-19 03:43:54621 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
622 // check with all attached and enabled color attachments.
623 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
[email protected]297ca1c2011-06-20 23:08:46624 bool BoundFramebufferHasDepthAttachment();
625 bool BoundFramebufferHasStencilAttachment();
626
[email protected]b8e97b62012-09-30 15:09:00627 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
[email protected]38d139d2011-07-14 00:38:43628
[email protected]91c94eb2013-10-22 10:32:54629 // Overridden from FramebufferManager::TextureDetachObserver:
630 virtual void OnTextureRefDetachedFromFramebuffer(
631 TextureRef* texture) OVERRIDE;
632
[email protected]f42f05b2013-11-15 21:46:18633 // Helpers to facilitate calling into compatible extensions.
634 static void RenderbufferStorageMultisampleHelper(
635 const FeatureInfo* feature_info,
636 GLenum target,
637 GLsizei samples,
638 GLenum internal_format,
639 GLsizei width,
640 GLsizei height);
641
642 void BlitFramebufferHelper(GLint srcX0,
643 GLint srcY0,
644 GLint srcX1,
645 GLint srcY1,
646 GLint dstX0,
647 GLint dstY0,
648 GLint dstX1,
649 GLint dstY1,
650 GLbitfield mask,
651 GLenum filter);
[email protected]345ba902013-11-14 21:39:00652
[email protected]96449d2c2009-11-25 00:01:32653 private:
[email protected]70d34263c2013-01-09 00:27:45654 friend class ScopedFrameBufferBinder;
[email protected]34ff8b0c2010-10-01 20:06:02655 friend class ScopedResolvedFrameBufferBinder;
[email protected]ed9f9cd2013-02-27 21:12:35656 friend class BackFramebuffer;
[email protected]6217d392010-03-25 22:08:35657
[email protected]c2f8c8402010-12-06 18:07:24658 // Initialize or re-initialize the shader translator.
659 bool InitializeShaderTranslator();
660
[email protected]302ce6d2011-07-07 23:28:11661 void UpdateCapabilities();
662
[email protected]ae51d192010-04-27 00:48:03663 // Helpers for the glGen and glDelete functions.
664 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
665 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
666 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
667 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
668 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
669 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
670 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
671 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]882ba1e22012-03-08 19:02:53672 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
673 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
[email protected]944b62f32012-09-27 02:20:46674 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
675 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47676
[email protected]70d34263c2013-01-09 00:27:45677 // Workarounds
678 void OnFboChanged() const;
[email protected]28718a92013-04-04 12:12:51679 void OnUseFramebuffer() const;
[email protected]70d34263c2013-01-09 00:27:45680
[email protected]3916c97e2010-02-25 03:20:50681 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50682 BufferManager* buffer_manager() {
683 return group_->buffer_manager();
684 }
685
[email protected]a25fa872010-03-25 02:57:58686 RenderbufferManager* renderbuffer_manager() {
687 return group_->renderbuffer_manager();
688 }
689
690 FramebufferManager* framebuffer_manager() {
691 return group_->framebuffer_manager();
692 }
693
[email protected]3916c97e2010-02-25 03:20:50694 ProgramManager* program_manager() {
695 return group_->program_manager();
696 }
697
698 ShaderManager* shader_manager() {
699 return group_->shader_manager();
700 }
701
[email protected]29a4d902013-02-26 20:18:06702 const TextureManager* texture_manager() const {
703 return group_->texture_manager();
704 }
705
[email protected]3916c97e2010-02-25 03:20:50706 TextureManager* texture_manager() {
707 return group_->texture_manager();
708 }
709
[email protected]78b514b2012-05-01 21:50:59710 MailboxManager* mailbox_manager() {
711 return group_->mailbox_manager();
712 }
713
[email protected]09d50362012-10-18 20:54:37714 ImageManager* image_manager() {
715 return group_->image_manager();
716 }
717
[email protected]944b62f32012-09-27 02:20:46718 VertexArrayManager* vertex_array_manager() {
719 return vertex_array_manager_.get();
720 }
721
[email protected]7989c9e2013-01-23 06:39:26722 MemoryTracker* memory_tracker() {
723 return group_->memory_tracker();
724 }
725
[email protected]4f9958142013-07-02 03:58:07726 StreamTextureManager* stream_texture_manager() const {
727 return group_->stream_texture_manager();
728 }
729
[email protected]7989c9e2013-01-23 06:39:26730 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
731 MemoryTracker* tracker = memory_tracker();
732 if (tracker) {
733 return tracker->EnsureGPUMemoryAvailable(estimated_size);
734 }
735 return true;
736 }
737
[email protected]34ff8b0c2010-10-01 20:06:02738 bool IsOffscreenBufferMultisampled() const {
739 return offscreen_target_samples_ > 1;
740 }
741
[email protected]ed9f9cd2013-02-27 21:12:35742 // Creates a Texture for the given texture.
[email protected]370eaf12013-05-18 09:19:49743 TextureRef* CreateTexture(
[email protected]ae51d192010-04-27 00:48:03744 GLuint client_id, GLuint service_id) {
[email protected]ed9f9cd2013-02-27 21:12:35745 return texture_manager()->CreateTexture(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47746 }
747
748 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]370eaf12013-05-18 09:19:49749 TextureRef* GetTexture(GLuint client_id) const {
[email protected]02965c22013-03-09 02:40:07750 return texture_manager()->GetTexture(client_id);
[email protected]a93bb842010-02-16 23:03:47751 }
752
753 // Deletes the texture info for the given texture.
[email protected]ed9f9cd2013-02-27 21:12:35754 void RemoveTexture(GLuint client_id) {
755 texture_manager()->RemoveTexture(client_id);
[email protected]3916c97e2010-02-25 03:20:50756 }
[email protected]a93bb842010-02-16 23:03:47757
[email protected]d37231fa2010-04-09 21:16:02758 // Get the size (in pixels) of the currently bound frame buffer (either FBO
759 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30760 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02761
[email protected]9edc6b22010-12-23 02:00:26762 // Get the format of the currently bound frame buffer (either FBO or regular
763 // back buffer)
764 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46765 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26766
[email protected]a93bb842010-02-16 23:03:47767 // Wrapper for CompressedTexImage2D commands.
768 error::Error DoCompressedTexImage2D(
[email protected]09d50362012-10-18 20:54:37769 GLenum target,
770 GLint level,
771 GLenum internal_format,
772 GLsizei width,
773 GLsizei height,
774 GLint border,
775 GLsizei image_size,
776 const void* data);
[email protected]a93bb842010-02-16 23:03:47777
[email protected]cadde4a2010-07-31 17:10:43778 // Wrapper for CompressedTexSubImage2D.
779 void DoCompressedTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37780 GLenum target,
781 GLint level,
782 GLint xoffset,
783 GLint yoffset,
784 GLsizei width,
785 GLsizei height,
786 GLenum format,
787 GLsizei imageSize,
788 const void * data);
[email protected]cadde4a2010-07-31 17:10:43789
790 // Wrapper for CopyTexImage2D.
791 void DoCopyTexImage2D(
[email protected]09d50362012-10-18 20:54:37792 GLenum target,
793 GLint level,
794 GLenum internal_format,
795 GLint x,
796 GLint y,
797 GLsizei width,
798 GLsizei height,
799 GLint border);
[email protected]cadde4a2010-07-31 17:10:43800
[email protected]6d792ee12013-05-15 00:40:56801 // Wrapper for SwapBuffers.
802 void DoSwapBuffers();
803
[email protected]cadde4a2010-07-31 17:10:43804 // Wrapper for CopyTexSubImage2D.
805 void DoCopyTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37806 GLenum target,
807 GLint level,
808 GLint xoffset,
809 GLint yoffset,
810 GLint x,
811 GLint y,
812 GLsizei width,
813 GLsizei height);
[email protected]cadde4a2010-07-31 17:10:43814
[email protected]f598f422012-12-07 08:30:03815 // Validation for TexSubImage2D.
816 bool ValidateTexSubImage2D(
817 error::Error* error,
818 const char* function_name,
819 GLenum target,
820 GLint level,
821 GLint xoffset,
822 GLint yoffset,
823 GLsizei width,
824 GLsizei height,
825 GLenum format,
826 GLenum type,
827 const void * data);
828
[email protected]cadde4a2010-07-31 17:10:43829 // Wrapper for TexSubImage2D.
[email protected]f598f422012-12-07 08:30:03830 error::Error DoTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37831 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);
[email protected]cadde4a2010-07-31 17:10:43840
[email protected]32145a92012-12-17 09:01:59841 // Extra validation for async tex(Sub)Image2D.
842 bool ValidateAsyncTransfer(
843 const char* function_name,
[email protected]85a4ac22013-05-31 01:58:47844 TextureRef* texture_ref,
[email protected]32145a92012-12-17 09:01:59845 GLenum target,
846 GLint level,
847 const void * data);
848
[email protected]e51bdf32011-11-23 22:21:46849 // Wrapper for TexImageIOSurface2DCHROMIUM.
850 void DoTexImageIOSurface2DCHROMIUM(
[email protected]09d50362012-10-18 20:54:37851 GLenum target,
852 GLsizei width,
853 GLsizei height,
854 GLuint io_surface_id,
855 GLuint plane);
[email protected]e51bdf32011-11-23 22:21:46856
[email protected]43410e92012-04-20 17:06:28857 void DoCopyTextureCHROMIUM(
[email protected]09d50362012-10-18 20:54:37858 GLenum target,
859 GLuint source_id,
860 GLuint target_id,
861 GLint level,
[email protected]a4a6bdd12013-04-19 20:46:54862 GLenum internal_format,
863 GLenum dest_type);
[email protected]43410e92012-04-20 17:06:28864
[email protected]97dc7cbe2011-12-06 17:26:17865 // Wrapper for TexStorage2DEXT.
866 void DoTexStorage2DEXT(
[email protected]09d50362012-10-18 20:54:37867 GLenum target,
868 GLint levels,
869 GLenum internal_format,
870 GLsizei width,
871 GLsizei height);
[email protected]97dc7cbe2011-12-06 17:26:17872
[email protected]78b514b2012-05-01 21:50:59873 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
874 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
875
[email protected]09d50362012-10-18 20:54:37876 void DoBindTexImage2DCHROMIUM(
877 GLenum target,
878 GLint image_id);
879 void DoReleaseTexImage2DCHROMIUM(
880 GLenum target,
881 GLint image_id);
882
[email protected]94307712012-11-16 23:26:11883 void DoTraceEndCHROMIUM(void);
884
[email protected]2f143d482013-03-14 18:04:49885 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
886
[email protected]ed9f9cd2013-02-27 21:12:35887 // Creates a Program for the given program.
888 Program* CreateProgram(
[email protected]d685a682011-04-29 16:19:57889 GLuint client_id, GLuint service_id) {
[email protected]ed9f9cd2013-02-27 21:12:35890 return program_manager()->CreateProgram(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47891 }
892
[email protected]07f54fcc2009-12-22 02:46:30893 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ed9f9cd2013-02-27 21:12:35894 Program* GetProgram(GLuint client_id) {
895 return program_manager()->GetProgram(client_id);
[email protected]1d32bc82010-01-13 22:06:46896 }
[email protected]07f54fcc2009-12-22 02:46:30897
[email protected]cae20172012-12-07 00:06:19898#if defined(NDEBUG)
899 void LogClientServiceMapping(
900 const char* /* function_name */,
901 GLuint /* client_id */,
902 GLuint /* service_id */) {
903 }
904 template<typename T>
905 void LogClientServiceForInfo(
906 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
907 }
908#else
909 void LogClientServiceMapping(
910 const char* function_name, GLuint client_id, GLuint service_id) {
[email protected]2a22fe72012-12-07 04:21:26911 if (service_logging_) {
[email protected]1d82e822013-04-10 21:32:32912 DLOG(INFO) << "[" << logger_.GetLogPrefix() << "] " << function_name
[email protected]2a22fe72012-12-07 04:21:26913 << ": client_id = " << client_id
914 << ", service_id = " << service_id;
915 }
[email protected]cae20172012-12-07 00:06:19916 }
917 template<typename T>
918 void LogClientServiceForInfo(
919 T* info, GLuint client_id, const char* function_name) {
[email protected]2a22fe72012-12-07 04:21:26920 if (info) {
[email protected]cae20172012-12-07 00:06:19921 LogClientServiceMapping(function_name, client_id, info->service_id());
922 }
923 }
924#endif
925
[email protected]6b8cf1a2010-05-06 16:13:58926 // Gets the program info for the given program. If it's not a program
927 // generates a GL error. Returns NULL if not program.
[email protected]ed9f9cd2013-02-27 21:12:35928 Program* GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:58929 GLuint client_id, const char* function_name) {
[email protected]df37b9932013-03-08 05:21:42930 Program* program = GetProgram(client_id);
931 if (!program) {
[email protected]ed9f9cd2013-02-27 21:12:35932 if (GetShader(client_id)) {
[email protected]ab09b612013-03-11 22:11:51933 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43934 GL_INVALID_OPERATION, function_name, "shader passed for program");
[email protected]6b8cf1a2010-05-06 16:13:58935 } else {
[email protected]ab09b612013-03-11 22:11:51936 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
[email protected]6b8cf1a2010-05-06 16:13:58937 }
938 }
[email protected]df37b9932013-03-08 05:21:42939 LogClientServiceForInfo(program, client_id, function_name);
940 return program;
[email protected]6b8cf1a2010-05-06 16:13:58941 }
942
943
[email protected]ed9f9cd2013-02-27 21:12:35944 // Creates a Shader for the given shader.
945 Shader* CreateShader(
[email protected]d685a682011-04-29 16:19:57946 GLuint client_id,
947 GLuint service_id,
948 GLenum shader_type) {
[email protected]ed9f9cd2013-02-27 21:12:35949 return shader_manager()->CreateShader(
[email protected]d685a682011-04-29 16:19:57950 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31951 }
952
953 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ed9f9cd2013-02-27 21:12:35954 Shader* GetShader(GLuint client_id) {
955 return shader_manager()->GetShader(client_id);
[email protected]45bf5152010-02-12 00:11:31956 }
957
[email protected]6b8cf1a2010-05-06 16:13:58958 // Gets the shader info for the given shader. If it's not a shader generates a
959 // GL error. Returns NULL if not shader.
[email protected]ed9f9cd2013-02-27 21:12:35960 Shader* GetShaderInfoNotProgram(
[email protected]6b8cf1a2010-05-06 16:13:58961 GLuint client_id, const char* function_name) {
[email protected]df37b9932013-03-08 05:21:42962 Shader* shader = GetShader(client_id);
963 if (!shader) {
[email protected]ed9f9cd2013-02-27 21:12:35964 if (GetProgram(client_id)) {
[email protected]ab09b612013-03-11 22:11:51965 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43966 GL_INVALID_OPERATION, function_name, "program passed for shader");
[email protected]6b8cf1a2010-05-06 16:13:58967 } else {
[email protected]ab09b612013-03-11 22:11:51968 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43969 GL_INVALID_VALUE, function_name, "unknown shader");
[email protected]6b8cf1a2010-05-06 16:13:58970 }
971 }
[email protected]df37b9932013-03-08 05:21:42972 LogClientServiceForInfo(shader, client_id, function_name);
973 return shader;
[email protected]6b8cf1a2010-05-06 16:13:58974 }
975
[email protected]a93bb842010-02-16 23:03:47976 // Creates a buffer info for the given buffer.
[email protected]ed9f9cd2013-02-27 21:12:35977 void CreateBuffer(GLuint client_id, GLuint service_id) {
978 return buffer_manager()->CreateBuffer(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47979 }
980
[email protected]07f54fcc2009-12-22 02:46:30981 // Gets the buffer info for the given buffer.
[email protected]16ccec12013-02-28 03:40:21982 Buffer* GetBuffer(GLuint client_id) {
[email protected]b10492f2013-03-08 05:24:07983 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
984 return buffer;
[email protected]1d32bc82010-01-13 22:06:46985 }
[email protected]07f54fcc2009-12-22 02:46:30986
[email protected]a93bb842010-02-16 23:03:47987 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
988 // on glDeleteBuffers so we can make sure the user does not try to render
989 // with deleted buffers.
[email protected]ed9f9cd2013-02-27 21:12:35990 void RemoveBuffer(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47991
[email protected]a25fa872010-03-25 02:57:58992 // Creates a framebuffer info for the given framebuffer.
[email protected]ed9f9cd2013-02-27 21:12:35993 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
994 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58995 }
996
997 // Gets the framebuffer info for the given framebuffer.
[email protected]4d8f0dd2013-03-09 14:37:06998 Framebuffer* GetFramebuffer(GLuint client_id) {
999 return framebuffer_manager()->GetFramebuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581000 }
1001
1002 // Removes the framebuffer info for the given framebuffer.
[email protected]ed9f9cd2013-02-27 21:12:351003 void RemoveFramebuffer(GLuint client_id) {
1004 framebuffer_manager()->RemoveFramebuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581005 }
1006
1007 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ed9f9cd2013-02-27 21:12:351008 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1009 return renderbuffer_manager()->CreateRenderbuffer(
[email protected]ae51d192010-04-27 00:48:031010 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:581011 }
1012
1013 // Gets the renderbuffer info for the given renderbuffer.
[email protected]ee2a79c32013-03-10 03:50:271014 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1015 return renderbuffer_manager()->GetRenderbuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581016 }
1017
1018 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ed9f9cd2013-02-27 21:12:351019 void RemoveRenderbuffer(GLuint client_id) {
1020 renderbuffer_manager()->RemoveRenderbuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581021 }
1022
[email protected]944b62f32012-09-27 02:20:461023 // Gets the vertex attrib manager for the given vertex array.
1024 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1025 VertexAttribManager* info =
1026 vertex_array_manager()->GetVertexAttribManager(client_id);
1027 return info;
1028 }
1029
1030 // Removes the vertex attrib manager for the given vertex array.
1031 void RemoveVertexAttribManager(GLuint client_id) {
1032 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1033 }
1034
1035 // Creates a vertex attrib manager for the given vertex array.
1036 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1037 return vertex_array_manager()->CreateVertexAttribManager(
1038 client_id, service_id, group_->max_vertex_attribs());
1039 }
1040
[email protected]258a3313f2011-10-18 20:13:571041 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
[email protected]2be6abf32012-06-26 00:28:331042 void DoBindUniformLocationCHROMIUM(
1043 GLuint client_id, GLint location, const char* name);
[email protected]258a3313f2011-10-18 20:13:571044
[email protected]558847a2010-03-24 07:02:541045 error::Error GetAttribLocationHelper(
1046 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1047 const std::string& name_str);
1048
1049 error::Error GetUniformLocationHelper(
1050 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1051 const std::string& name_str);
1052
[email protected]3916c97e2010-02-25 03:20:501053 // Helper for glShaderSource.
1054 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:031055 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:301056
[email protected]0d6bfdc2011-11-02 01:32:201057 // Clear any textures used by the current program.
1058 bool ClearUnclearedTextures();
1059
1060 // Clear any uncleared level in texture.
1061 // Returns false if there was a generated GL error.
[email protected]02965c22013-03-09 02:40:071062 bool ClearTexture(Texture* texture);
[email protected]0d6bfdc2011-11-02 01:32:201063
1064 // Clears any uncleared attachments attached to the given frame buffer.
1065 // Returns false if there was a generated GL error.
[email protected]4d8f0dd2013-03-09 14:37:061066 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
[email protected]3a2e7c7b2010-08-06 01:12:281067
[email protected]0d6bfdc2011-11-02 01:32:201068 // overridden from GLES2Decoder
[email protected]b8e97b62012-09-30 15:09:001069 virtual bool ClearLevel(unsigned service_id,
1070 unsigned bind_target,
1071 unsigned target,
1072 int level,
1073 unsigned format,
1074 unsigned type,
1075 int width,
1076 int height,
1077 bool is_texture_immutable) OVERRIDE;
[email protected]0d6bfdc2011-11-02 01:32:201078
[email protected]c007aa02010-09-02 22:22:401079 // Restore all GL state that affects clearing.
1080 void RestoreClearState();
1081
[email protected]3a2e7c7b2010-08-06 01:12:281082 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:461083 // Returns: true if glEnable/glDisable should actually be called.
1084 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:281085
[email protected]0d6bfdc2011-11-02 01:32:201086 // Check that the currently bound framebuffers are valid.
1087 // Generates GL error if not.
1088 bool CheckBoundFramebuffersValid(const char* func_name);
1089
1090 // Check if a framebuffer meets our requirements.
1091 bool CheckFramebufferValid(
[email protected]ed9f9cd2013-02-27 21:12:351092 Framebuffer* framebuffer,
[email protected]0d6bfdc2011-11-02 01:32:201093 GLenum target,
1094 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:271095
[email protected]939e7362010-05-13 20:49:101096 // Checks if the current program exists and is valid. If not generates the
1097 // appropriate GL error. Returns true if the current program is in a usable
1098 // state.
1099 bool CheckCurrentProgram(const char* function_name);
1100
1101 // Checks if the current program exists and is valid and that location is not
1102 // -1. If the current program is not valid generates the appropriate GL
1103 // error. Returns true if the current program is in a usable state and
1104 // location is not -1.
1105 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1106
1107 // Gets the type of a uniform for a location in the current program. Sets GL
1108 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:361109 // program is valid and the location exists. Adjusts count so it
1110 // does not overflow the uniform.
1111 bool PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:121112 GLint fake_location, const char* function_name,
[email protected]476ccb72012-12-06 15:52:521113 const BaseUniformInfo& base_info,
[email protected]1b0a6752012-02-22 03:44:121114 GLint* real_location, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:101115
[email protected]b177ae22011-11-01 03:29:111116 // Gets the service id for any simulated backbuffer fbo.
[email protected]1868a342012-11-07 15:56:021117 GLuint GetBackbufferServiceId() const;
[email protected]b177ae22011-11-01 03:29:111118
[email protected]b273e432010-04-12 17:23:581119 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1120 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1121
[email protected]ac77603c72013-03-08 13:52:061122 // Helper for glGetVertexAttrib
1123 void GetVertexAttribHelper(
1124 const VertexAttrib* attrib, GLenum pname, GLint* param);
1125
[email protected]96449d2c2009-11-25 00:01:321126 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:031127 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321128
1129 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:031130 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321131
[email protected]3916c97e2010-02-25 03:20:501132 // Wrapper for glActiveTexture
1133 void DoActiveTexture(GLenum texture_unit);
1134
[email protected]ae51d192010-04-27 00:48:031135 // Wrapper for glAttachShader
1136 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1137
[email protected]96449d2c2009-11-25 00:01:321138 // Wrapper for glBindBuffer since we need to track the current targets.
1139 void DoBindBuffer(GLenum target, GLuint buffer);
1140
[email protected]86093972010-03-11 00:13:561141 // Wrapper for glBindFramebuffer since we need to track the current targets.
1142 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1143
1144 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1145 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1146
[email protected]a93bb842010-02-16 23:03:471147 // Wrapper for glBindTexture since we need to track the current targets.
1148 void DoBindTexture(GLenum target, GLuint texture);
1149
[email protected]944b62f32012-09-27 02:20:461150 // Wrapper for glBindVertexArrayOES
1151 void DoBindVertexArrayOES(GLuint array);
[email protected]ab4fd7282012-10-12 16:25:571152 void EmulateVertexArrayState();
[email protected]944b62f32012-09-27 02:20:461153
[email protected]49cabed2013-11-13 18:15:181154 // Wrapper for glBlitFramebufferCHROMIUM.
1155 void DoBlitFramebufferCHROMIUM(
[email protected]8e3e0662010-08-23 18:46:301156 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1157 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1158 GLbitfield mask, GLenum filter);
1159
[email protected]36cef8ce2010-03-16 07:34:451160 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111161 void DoBufferSubData(
1162 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1163
[email protected]36cef8ce2010-03-16 07:34:451164 // Wrapper for glCheckFramebufferStatus
1165 GLenum DoCheckFramebufferStatus(GLenum target);
1166
[email protected]3a03a8f2011-03-19 00:51:271167 // Wrapper for glClear
[email protected]a7266a92012-06-28 02:11:081168 error::Error DoClear(GLbitfield mask);
[email protected]3a03a8f2011-03-19 00:51:271169
[email protected]88a61bf2012-10-27 13:00:421170 // Wrappers for various state.
[email protected]88a61bf2012-10-27 13:00:421171 void DoDepthRangef(GLclampf znear, GLclampf zfar);
[email protected]b04e24c2013-01-08 18:35:251172 void DoSampleCoverage(GLclampf value, GLboolean invert);
[email protected]3a2e7c7b2010-08-06 01:12:281173
[email protected]45bf5152010-02-12 00:11:311174 // Wrapper for glCompileShader.
1175 void DoCompileShader(GLuint shader);
1176
[email protected]269200b12010-11-18 22:53:061177 // Helper for DeleteSharedIdsCHROMIUM commands.
1178 void DoDeleteSharedIdsCHROMIUM(
1179 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101180
[email protected]ae51d192010-04-27 00:48:031181 // Wrapper for glDetachShader
1182 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1183
[email protected]3a2e7c7b2010-08-06 01:12:281184 // Wrapper for glDisable
1185 void DoDisable(GLenum cap);
1186
[email protected]07f54fcc2009-12-22 02:46:301187 // Wrapper for glDisableVertexAttribArray.
1188 void DoDisableVertexAttribArray(GLuint index);
1189
[email protected]60f22d32012-12-12 00:31:581190 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1191 // attachments.
1192 void DoDiscardFramebufferEXT(GLenum target,
1193 GLsizei numAttachments,
1194 const GLenum* attachments);
1195
[email protected]3a2e7c7b2010-08-06 01:12:281196 // Wrapper for glEnable
1197 void DoEnable(GLenum cap);
1198
[email protected]07f54fcc2009-12-22 02:46:301199 // Wrapper for glEnableVertexAttribArray.
1200 void DoEnableVertexAttribArray(GLuint index);
1201
[email protected]882ba1e22012-03-08 19:02:531202 // Wrapper for glFinish.
1203 void DoFinish();
1204
1205 // Wrapper for glFlush.
1206 void DoFlush();
1207
[email protected]36cef8ce2010-03-16 07:34:451208 // Wrapper for glFramebufferRenderbufffer.
1209 void DoFramebufferRenderbuffer(
1210 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1211 GLuint renderbuffer);
1212
1213 // Wrapper for glFramebufferTexture2D.
1214 void DoFramebufferTexture2D(
1215 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1216 GLint level);
1217
[email protected]7d3c36e2013-07-12 14:13:161218 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1219 void DoFramebufferTexture2DMultisample(
1220 GLenum target, GLenum attachment, GLenum textarget,
1221 GLuint texture, GLint level, GLsizei samples);
1222
1223 // Common implementation for both DoFramebufferTexture2D wrappers.
1224 void DoFramebufferTexture2DCommon(const char* name,
1225 GLenum target, GLenum attachment, GLenum textarget,
1226 GLuint texture, GLint level, GLsizei samples);
1227
[email protected]a93bb842010-02-16 23:03:471228 // Wrapper for glGenerateMipmap
1229 void DoGenerateMipmap(GLenum target);
1230
[email protected]269200b12010-11-18 22:53:061231 // Helper for GenSharedIdsCHROMIUM commands.
1232 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101233 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1234
[email protected]7d3c36e2013-07-12 14:13:161235 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1236 // to account for different pname values defined in different extension
1237 // variants.
1238 GLenum AdjustGetPname(GLenum pname);
1239
[email protected]b273e432010-04-12 17:23:581240 // Wrapper for DoGetBooleanv.
1241 void DoGetBooleanv(GLenum pname, GLboolean* params);
1242
1243 // Wrapper for DoGetFloatv.
1244 void DoGetFloatv(GLenum pname, GLfloat* params);
1245
[email protected]36cef8ce2010-03-16 07:34:451246 // Wrapper for glGetFramebufferAttachmentParameteriv.
1247 void DoGetFramebufferAttachmentParameteriv(
1248 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1249
[email protected]a0c3e972010-04-21 00:49:131250 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581251 void DoGetIntegerv(GLenum pname, GLint* params);
1252
[email protected]29a9eb52010-04-13 09:04:231253 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061254 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231255 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1256
[email protected]17cfbe0e2013-03-07 01:26:081257 // Wrapper for glGetBufferParameteriv.
1258 void DoGetBufferParameteriv(
1259 GLenum target, GLenum pname, GLint* params);
1260
[email protected]a0c3e972010-04-21 00:49:131261 // Wrapper for glGetProgramiv.
1262 void DoGetProgramiv(
1263 GLuint program_id, GLenum pname, GLint* params);
1264
[email protected]36cef8ce2010-03-16 07:34:451265 // Wrapper for glRenderbufferParameteriv.
1266 void DoGetRenderbufferParameteriv(
1267 GLenum target, GLenum pname, GLint* params);
1268
[email protected]ddd968b82010-03-02 00:44:291269 // Wrapper for glGetShaderiv
1270 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1271
[email protected]b1122982010-05-17 23:04:241272 // Wrappers for glGetVertexAttrib.
1273 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1274 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1275
[email protected]1958e0e2010-04-22 05:17:151276 // Wrappers for glIsXXX functions.
[email protected]3dc69c42012-05-12 02:29:241277 bool DoIsEnabled(GLenum cap);
[email protected]1958e0e2010-04-22 05:17:151278 bool DoIsBuffer(GLuint client_id);
1279 bool DoIsFramebuffer(GLuint client_id);
1280 bool DoIsProgram(GLuint client_id);
1281 bool DoIsRenderbuffer(GLuint client_id);
1282 bool DoIsShader(GLuint client_id);
1283 bool DoIsTexture(GLuint client_id);
[email protected]944b62f32012-09-27 02:20:461284 bool DoIsVertexArrayOES(GLuint client_id);
[email protected]1958e0e2010-04-22 05:17:151285
[email protected]07f54fcc2009-12-22 02:46:301286 // Wrapper for glLinkProgram
1287 void DoLinkProgram(GLuint program);
1288
[email protected]269200b12010-11-18 22:53:061289 // Helper for RegisterSharedIdsCHROMIUM.
1290 void DoRegisterSharedIdsCHROMIUM(
1291 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101292
[email protected]36cef8ce2010-03-16 07:34:451293 // Wrapper for glRenderbufferStorage.
1294 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031295 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451296
[email protected]49cabed2013-11-13 18:15:181297 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1298 void DoRenderbufferStorageMultisampleCHROMIUM(
[email protected]8e3e0662010-08-23 18:46:301299 GLenum target, GLsizei samples, GLenum internalformat,
1300 GLsizei width, GLsizei height);
1301
[email protected]49cabed2013-11-13 18:15:181302 // Handler for glRenderbufferStorageMultisampleEXT
1303 // (multisampled_render_to_texture).
1304 void DoRenderbufferStorageMultisampleEXT(
1305 GLenum target, GLsizei samples, GLenum internalformat,
1306 GLsizei width, GLsizei height);
1307
1308 // Common validation for multisample extensions.
1309 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1310 GLenum internalformat,
1311 GLsizei width,
1312 GLsizei height);
1313
[email protected]4a4c18b2013-09-13 22:50:101314 // Verifies that the currently bound multisample renderbuffer is valid
1315 // Very slow! Only done on platforms with driver bugs that return invalid
1316 // buffers under memory pressure
1317 bool VerifyMultisampleRenderbufferIntegrity(
1318 GLuint renderbuffer, GLenum format);
1319
[email protected]b273e432010-04-12 17:23:581320 // Wrapper for glReleaseShaderCompiler.
1321 void DoReleaseShaderCompiler() { }
1322
[email protected]3916c97e2010-02-25 03:20:501323 // Wrappers for glTexParameter functions.
1324 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1325 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1326 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1327 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1328
1329 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1330 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121331 void DoUniform1i(GLint fake_location, GLint v0);
1332 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1333 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1334 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1335 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101336
1337 // Wrappers for glUniformfv because some drivers don't correctly accept
1338 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121339 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1340 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1341 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1342 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501343
[email protected]43c2f1f2011-03-25 18:35:361344 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121345 GLint fake_location, GLsizei count, GLboolean transpose,
1346 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361347 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121348 GLint fake_location, GLsizei count, GLboolean transpose,
1349 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361350 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121351 GLint fake_location, GLsizei count, GLboolean transpose,
1352 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361353
[email protected]af6380962012-11-29 23:24:131354 bool SetVertexAttribValue(
1355 const char* function_name, GLuint index, const GLfloat* value);
1356
[email protected]b1122982010-05-17 23:04:241357 // Wrappers for glVertexAttrib??
1358 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1359 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1360 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1361 void DoVertexAttrib4f(
1362 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1363 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1364 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1365 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1366 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1367
[email protected]43410e92012-04-20 17:06:281368 // Wrapper for glViewport
1369 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1370
[email protected]07f54fcc2009-12-22 02:46:301371 // Wrapper for glUseProgram
1372 void DoUseProgram(GLuint program);
1373
[email protected]ae51d192010-04-27 00:48:031374 // Wrapper for glValidateProgram.
1375 void DoValidateProgram(GLuint program_client_id);
1376
[email protected]d2a0e1a2012-08-12 02:25:011377 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1378 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1379 void DoPopGroupMarkerEXT(void);
1380
[email protected]4e8a5b122010-05-08 22:00:101381 // Gets the number of values that will be returned by glGetXXX. Returns
1382 // false if pname is unknown.
1383 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1384
[email protected]07f54fcc2009-12-22 02:46:301385 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]ad84a3a2012-06-08 21:42:431386 bool IsDrawValid(
1387 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301388
[email protected]c13e1da62011-09-09 21:48:301389 // Returns true if successful, simulated will be true if attrib0 was
1390 // simulated.
[email protected]c6aef902012-02-14 03:31:421391 bool SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:431392 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
[email protected]43410e92012-04-20 17:06:281393 void RestoreStateForAttrib(GLuint attrib);
[email protected]b1122982010-05-17 23:04:241394
[email protected]e56131d22013-07-28 16:14:111395 // If texture is a stream texture, this will update the stream to the newest
[email protected]e8dc5662013-10-17 23:28:291396 // buffer and bind the texture implicitly.
1397 void UpdateStreamTextureIfNeeded(Texture* texture, GLuint texture_unit_index);
[email protected]e56131d22013-07-28 16:14:111398
[email protected]91c94eb2013-10-22 10:32:541399 // If an image is bound to texture, this will call Will/DidUseTexImage
1400 // if needed.
1401 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1402 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1403
1404 // Returns false if textures were replaced.
[email protected]e56131d22013-07-28 16:14:111405 bool PrepareTexturesForRender();
[email protected]91c94eb2013-10-22 10:32:541406 void RestoreStateForTextures();
[email protected]3916c97e2010-02-25 03:20:501407
[email protected]8fbedc02010-11-18 18:43:401408 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421409 bool SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:431410 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421411 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401412 void RestoreStateForSimulatedFixedAttribs();
1413
[email protected]c6aef902012-02-14 03:31:421414 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1415 // cases (primcount is 0 for non-instanced).
1416 error::Error DoDrawArrays(
[email protected]ad84a3a2012-06-08 21:42:431417 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421418 bool instanced, GLenum mode, GLint first, GLsizei count,
1419 GLsizei primcount);
1420 error::Error DoDrawElements(
[email protected]ad84a3a2012-06-08 21:42:431421 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421422 bool instanced, GLenum mode, GLsizei count, GLenum type,
1423 int32 offset, GLsizei primcount);
1424
[email protected]61eeb33f2011-07-26 15:30:311425 GLenum GetBindTargetForSamplerType(GLenum type) {
1426 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461427 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1428 switch (type) {
1429 case GL_SAMPLER_2D:
1430 return GL_TEXTURE_2D;
1431 case GL_SAMPLER_CUBE:
1432 return GL_TEXTURE_CUBE_MAP;
1433 case GL_SAMPLER_EXTERNAL_OES:
1434 return GL_TEXTURE_EXTERNAL_OES;
1435 case GL_SAMPLER_2D_RECT_ARB:
1436 return GL_TEXTURE_RECTANGLE_ARB;
1437 }
1438
1439 NOTREACHED();
1440 return 0;
[email protected]61eeb33f2011-07-26 15:30:311441 }
1442
[email protected]8e3e0662010-08-23 18:46:301443 // Gets the framebuffer info for a particular target.
[email protected]4d8f0dd2013-03-09 14:37:061444 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1445 Framebuffer* framebuffer = NULL;
[email protected]8e3e0662010-08-23 18:46:301446 switch (target) {
1447 case GL_FRAMEBUFFER:
[email protected]ebfb73c2012-08-15 02:37:451448 case GL_DRAW_FRAMEBUFFER_EXT:
[email protected]9d3b2e12013-10-02 01:04:341449 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
[email protected]8e3e0662010-08-23 18:46:301450 break;
[email protected]ebfb73c2012-08-15 02:37:451451 case GL_READ_FRAMEBUFFER_EXT:
[email protected]9d3b2e12013-10-02 01:04:341452 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
[email protected]8e3e0662010-08-23 18:46:301453 break;
1454 default:
1455 NOTREACHED();
1456 break;
1457 }
[email protected]4d8f0dd2013-03-09 14:37:061458 return framebuffer;
[email protected]8e3e0662010-08-23 18:46:301459 }
1460
[email protected]ed9f9cd2013-02-27 21:12:351461 Renderbuffer* GetRenderbufferInfoForTarget(
[email protected]0d6bfdc2011-11-02 01:32:201462 GLenum target) {
[email protected]ee2a79c32013-03-10 03:50:271463 Renderbuffer* renderbuffer = NULL;
[email protected]0d6bfdc2011-11-02 01:32:201464 switch (target) {
1465 case GL_RENDERBUFFER:
[email protected]7cd76fd2013-06-02 21:11:111466 renderbuffer = state_.bound_renderbuffer.get();
[email protected]0d6bfdc2011-11-02 01:32:201467 break;
1468 default:
1469 NOTREACHED();
1470 break;
1471 }
[email protected]ee2a79c32013-03-10 03:50:271472 return renderbuffer;
[email protected]0d6bfdc2011-11-02 01:32:201473 }
1474
[email protected]f7b85372010-02-03 01:11:371475 // Validates the program and location for a glGetUniform call and returns
1476 // a SizeResult setup to receive the result. Returns true if glGetUniform
1477 // should be called.
1478 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121479 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371480 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121481 error::Error* error, GLint* real_location, GLuint* service_id,
1482 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371483
[email protected]1078f912011-12-23 13:12:141484 // Computes the estimated memory used for the backbuffer and passes it to
1485 // the tracing system.
[email protected]260ddc4e2012-06-28 00:01:531486 size_t GetBackbufferMemoryTotal();
[email protected]1078f912011-12-23 13:12:141487
[email protected]a10b4a02012-11-26 23:09:501488 virtual bool WasContextLost() OVERRIDE;
[email protected]93a7d98f2013-07-11 00:04:221489 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
[email protected]c4485aad62012-12-17 10:19:091490 virtual void LoseContext(uint32 reset_status) OVERRIDE;
[email protected]38d139d2011-07-14 00:38:431491
[email protected]e51bdf32011-11-23 22:21:461492#if defined(OS_MACOSX)
1493 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1494#endif
1495
[email protected]81375742012-06-08 00:04:001496 // Validates the combination of texture parameters. For example validates that
1497 // for a given format the specific type, level and targets are valid.
1498 // Synthesizes the correct GL error if invalid. Returns true if valid.
1499 bool ValidateTextureParameters(
1500 const char* function_name,
1501 GLenum target, GLenum format, GLenum type, GLint level);
1502
[email protected]ad84a3a2012-06-08 21:42:431503 bool ValidateCompressedTexDimensions(
1504 const char* function_name,
1505 GLint level, GLsizei width, GLsizei height, GLenum format);
1506 bool ValidateCompressedTexFuncData(
1507 const char* function_name,
1508 GLsizei width, GLsizei height, GLenum format, size_t size);
1509 bool ValidateCompressedTexSubDimensions(
1510 const char* function_name,
1511 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1512 GLsizei width, GLsizei height, GLenum format,
[email protected]ed9f9cd2013-02-27 21:12:351513 Texture* texture);
[email protected]ad84a3a2012-06-08 21:42:431514
[email protected]ab09b612013-03-11 22:11:511515 void RenderWarning(const char* filename, int line, const std::string& msg);
1516 void PerformanceWarning(
1517 const char* filename, int line, const std::string& msg);
[email protected]0f8afe82012-05-14 23:43:011518
[email protected]62e155e2012-10-23 22:43:151519 const FeatureInfo::FeatureFlags& features() const {
1520 return feature_info_->feature_flags();
1521 }
1522
1523 const FeatureInfo::Workarounds& workarounds() const {
1524 return feature_info_->workarounds();
1525 }
1526
[email protected]a7266a92012-06-28 02:11:081527 bool ShouldDeferDraws() {
1528 return !offscreen_target_frame_buffer_.get() &&
[email protected]9d3b2e12013-10-02 01:04:341529 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
[email protected]a7266a92012-06-28 02:11:081530 surface_->DeferDraws();
1531 }
1532
[email protected]09e17272012-11-30 10:30:441533 bool ShouldDeferReads() {
1534 return !offscreen_target_frame_buffer_.get() &&
[email protected]9d3b2e12013-10-02 01:04:341535 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
[email protected]09e17272012-11-30 10:30:441536 surface_->DeferDraws();
1537 }
1538
[email protected]5a36dc132013-07-23 23:17:551539 void ProcessPendingReadPixels();
1540 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1541
[email protected]96449d2c2009-11-25 00:01:321542 // Generate a member function prototype for each command in an automated and
1543 // typesafe way.
1544 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141545 Error Handle ## name( \
[email protected]ed9f9cd2013-02-27 21:12:351546 uint32 immediate_data_size, \
1547 const cmds::name& args); \
[email protected]96449d2c2009-11-25 00:01:321548
1549 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1550
1551 #undef GLES2_CMD_OP
1552
[email protected]2f2d7042010-04-14 21:45:581553 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381554 scoped_refptr<gfx::GLSurface> surface_;
1555 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021556
[email protected]a3ded6d2010-10-19 06:44:391557 // The ContextGroup for this decoder uses to track resources.
[email protected]ed9f9cd2013-02-27 21:12:351558 scoped_refptr<ContextGroup> group_;
[email protected]a3ded6d2010-10-19 06:44:391559
[email protected]1d82e822013-04-10 21:32:321560 DebugMarkerManager debug_marker_manager_;
1561 Logger logger_;
1562
[email protected]e259eb412012-10-13 05:47:241563 // All the state for this context.
1564 ContextState state_;
1565
[email protected]34ff8b0c2010-10-01 20:06:021566 // Current width and height of the offscreen frame buffer.
1567 gfx::Size offscreen_size_;
1568
[email protected]96449d2c2009-11-25 00:01:321569 // Util to help with GL.
1570 GLES2Util util_;
1571
[email protected]43410e92012-04-20 17:06:281572 // unpack flip y as last set by glPixelStorei
1573 bool unpack_flip_y_;
1574
[email protected]6c75c712012-06-19 15:43:171575 // unpack (un)premultiply alpha as last set by glPixelStorei
[email protected]43410e92012-04-20 17:06:281576 bool unpack_premultiply_alpha_;
[email protected]6c75c712012-06-19 15:43:171577 bool unpack_unpremultiply_alpha_;
[email protected]43410e92012-04-20 17:06:281578
[email protected]944b62f32012-09-27 02:20:461579 // Default vertex attribs manager, used when no VAOs are bound.
[email protected]ed9f9cd2013-02-27 21:12:351580 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301581
[email protected]b1122982010-05-17 23:04:241582 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1583 GLuint attrib_0_buffer_id_;
1584
1585 // The value currently in attrib_0.
[email protected]af6380962012-11-29 23:24:131586 Vec4 attrib_0_value_;
[email protected]b1122982010-05-17 23:04:241587
[email protected]fc753442011-02-04 19:49:491588 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1589 bool attrib_0_buffer_matches_value_;
1590
[email protected]b1122982010-05-17 23:04:241591 // The size of attrib 0.
1592 GLsizei attrib_0_size_;
1593
[email protected]8fbedc02010-11-18 18:43:401594 // The buffer used to simulate GL_FIXED attribs.
1595 GLuint fixed_attrib_buffer_id_;
1596
1597 // The size of fiixed attrib buffer.
1598 GLsizei fixed_attrib_buffer_size_;
1599
[email protected]b9363b22010-06-09 22:06:151600 // The offscreen frame buffer that the client renders to. With EGL, the
1601 // depth and stencil buffers are separate. With regular GL there is a single
1602 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1603 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]ed9f9cd2013-02-27 21:12:351604 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1605 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1606 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1607 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1608 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021609 GLenum offscreen_target_color_format_;
1610 GLenum offscreen_target_depth_format_;
1611 GLenum offscreen_target_stencil_format_;
1612 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561613 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351614
[email protected]de26b3c2011-08-03 21:54:271615 // The copy that is saved when SwapBuffers is called.
[email protected]ed9f9cd2013-02-27 21:12:351616 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1617 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
[email protected]370eaf12013-05-18 09:19:491618 scoped_refptr<TextureRef>
[email protected]ed9f9cd2013-02-27 21:12:351619 offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271620
1621 // The copy that is used as the destination for multi-sample resolves.
[email protected]ed9f9cd2013-02-27 21:12:351622 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1623 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051624 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351625
[email protected]882ba1e22012-03-08 19:02:531626 scoped_ptr<QueryManager> query_manager_;
[email protected]882ba1e22012-03-08 19:02:531627
[email protected]944b62f32012-09-27 02:20:461628 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1629
[email protected]729c0b42013-05-26 02:05:071630 base::Callback<void(gfx::Size, float)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001631
[email protected]840a7e462013-02-27 01:29:511632 WaitSyncPointCallback wait_sync_point_callback_;
[email protected]43f28f832010-02-03 02:28:481633
[email protected]e3932abb2013-03-13 00:01:371634 ShaderCacheCallback shader_cache_callback_;
1635
[email protected]85a4ac22013-05-31 01:58:471636 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
[email protected]b0af4f52011-09-28 22:04:421637
[email protected]32fe9aa2011-01-21 23:47:131638 // The format of the back buffer_
1639 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461640 bool back_buffer_has_depth_;
1641 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131642
[email protected]60f22d32012-12-12 00:31:581643 // Backbuffer attachments that are currently undefined.
1644 uint32 backbuffer_needs_clear_bits_;
1645
[email protected]a3a93e7b2010-08-28 00:48:561646 // The current decoder error.
1647 error::Error current_decoder_error_;
1648
[email protected]b1d2dcb2010-05-17 19:24:181649 bool use_shader_translator_;
[email protected]87fb6ab2012-06-13 22:28:041650 scoped_refptr<ShaderTranslator> vertex_translator_;
1651 scoped_refptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181652
[email protected]e82fb792011-09-22 00:33:291653 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411654
[email protected]915a59a12010-09-30 21:29:111655 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051656 const Validators* validators_;
[email protected]ed9f9cd2013-02-27 21:12:351657 scoped_refptr<FeatureInfo> feature_info_;
[email protected]9438b012010-06-15 22:55:051658
[email protected]65225772011-05-12 21:10:241659 int frame_number_;
1660
[email protected]706b69f2012-07-27 04:59:301661 bool has_robustness_extension_;
[email protected]38d139d2011-07-14 00:38:431662 GLenum reset_status_;
[email protected]93a7d98f2013-07-11 00:04:221663 bool reset_by_robustness_extension_;
[email protected]38d139d2011-07-14 00:38:431664
[email protected]f0d74742011-10-03 16:31:041665 // These flags are used to override the state of the shared feature_info_
1666 // member. Because the same FeatureInfo instance may be shared among many
1667 // contexts, the assumptions on the availablity of extensions in WebGL
1668 // contexts may be broken. These flags override the shared state to preserve
1669 // WebGL semantics.
1670 bool force_webgl_glsl_validation_;
1671 bool derivatives_explicitly_enabled_;
[email protected]70dc60932013-06-04 03:33:491672 bool frag_depth_explicitly_enabled_;
[email protected]aff39ac82013-06-08 04:53:131673 bool draw_buffers_explicitly_enabled_;
[email protected]f0d74742011-10-03 16:31:041674
[email protected]062c38b2012-01-18 03:25:101675 bool compile_shader_always_succeeds_;
1676
[email protected]cae20172012-12-07 00:06:191677 // Log extra info.
1678 bool service_logging_;
1679
[email protected]e51bdf32011-11-23 22:21:461680#if defined(OS_MACOSX)
1681 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1682 TextureToIOSurfaceMap texture_to_io_surface_map_;
1683#endif
1684
[email protected]43410e92012-04-20 17:06:281685 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1686
[email protected]1868a342012-11-07 15:56:021687 // Cached values of the currently assigned viewport dimensions.
1688 GLsizei viewport_max_width_;
1689 GLsizei viewport_max_height_;
1690
[email protected]63b465922012-09-06 02:04:521691 // Command buffer stats.
[email protected]63b465922012-09-06 02:04:521692 base::TimeDelta total_processing_commands_time_;
1693
[email protected]c986af502013-08-14 01:04:441694 // States related to each manager.
1695 DecoderTextureState texture_state_;
1696 DecoderFramebufferState framebuffer_state_;
1697
[email protected]fb97b662013-02-20 23:02:141698 scoped_ptr<GPUTracer> gpu_tracer_;
[email protected]8f9b8dd2013-09-12 18:05:131699 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
[email protected]94307712012-11-16 23:26:111700
[email protected]5a36dc132013-07-23 23:17:551701 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1702
[email protected]4a4c18b2013-09-13 22:50:101703 // Used to validate multisample renderbuffers if needed
1704 GLuint validation_texture_;
1705 GLuint validation_fbo_multisample_;
1706 GLuint validation_fbo_;
1707
[email protected]96449d2c2009-11-25 00:01:321708 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1709};
1710
[email protected]ab09b612013-03-11 22:11:511711ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
[email protected]40621eb52013-10-08 15:40:301712 const char* function_name, ErrorState* error_state)
[email protected]ab09b612013-03-11 22:11:511713 : function_name_(function_name),
[email protected]40621eb52013-10-08 15:40:301714 error_state_(error_state) {
1715 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
[email protected]6217d392010-03-25 22:08:351716}
1717
1718ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
[email protected]40621eb52013-10-08 15:40:301719 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
[email protected]6217d392010-03-25 22:08:351720}
1721
[email protected]ce296892013-10-24 22:04:361722static void RestoreCurrentTexture2DBindings(ContextState* state) {
1723 TextureUnit& info = state->texture_units[0];
1724 GLuint last_id;
1725 if (info.bound_texture_2d.get()) {
1726 last_id = info.bound_texture_2d->service_id();
1727 } else {
1728 last_id = 0;
1729 }
1730
1731 glBindTexture(GL_TEXTURE_2D, last_id);
1732 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1733}
1734
1735ScopedTexture2DBinder::ScopedTexture2DBinder(ContextState* state,
[email protected]6217d392010-03-25 22:08:351736 GLuint id)
[email protected]ce296892013-10-24 22:04:361737 : state_(state) {
[email protected]ab09b612013-03-11 22:11:511738 ScopedGLErrorSuppressor suppressor(
[email protected]ce296892013-10-24 22:04:361739 "ScopedTexture2DBinder::ctor", state_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351740
1741 // TODO(apatrick): Check if there are any other states that need to be reset
1742 // before binding a new texture.
1743 glActiveTexture(GL_TEXTURE0);
1744 glBindTexture(GL_TEXTURE_2D, id);
1745}
1746
1747ScopedTexture2DBinder::~ScopedTexture2DBinder() {
[email protected]ab09b612013-03-11 22:11:511748 ScopedGLErrorSuppressor suppressor(
[email protected]ce296892013-10-24 22:04:361749 "ScopedTexture2DBinder::dtor", state_->GetErrorState());
1750 RestoreCurrentTexture2DBindings(state_);
[email protected]6217d392010-03-25 22:08:351751}
1752
[email protected]18e785a2013-10-09 03:29:411753ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
[email protected]6217d392010-03-25 22:08:351754 GLuint id)
[email protected]18e785a2013-10-09 03:29:411755 : state_(state) {
[email protected]ab09b612013-03-11 22:11:511756 ScopedGLErrorSuppressor suppressor(
[email protected]18e785a2013-10-09 03:29:411757 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351758 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1759}
1760
1761ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
[email protected]ab09b612013-03-11 22:11:511762 ScopedGLErrorSuppressor suppressor(
[email protected]18e785a2013-10-09 03:29:411763 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1764 state_->RestoreRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351765}
1766
1767ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1768 GLuint id)
1769 : decoder_(decoder) {
[email protected]ab09b612013-03-11 22:11:511770 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:301771 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351772 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
[email protected]70d34263c2013-01-09 00:27:451773 decoder->OnFboChanged();
[email protected]6217d392010-03-25 22:08:351774}
1775
1776ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
[email protected]ab09b612013-03-11 22:11:511777 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:301778 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
[email protected]8e3e0662010-08-23 18:46:301779 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351780}
1781
[email protected]34ff8b0c2010-10-01 20:06:021782ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271783 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521784 : decoder_(decoder) {
[email protected]9d3b2e12013-10-02 01:04:341785 resolve_and_bind_ = (
1786 decoder_->offscreen_target_frame_buffer_.get() &&
1787 decoder_->IsOffscreenBufferMultisampled() &&
1788 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1789 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021790 if (!resolve_and_bind_)
1791 return;
1792
[email protected]ab09b612013-03-11 22:11:511793 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:301794 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
[email protected]34ff8b0c2010-10-01 20:06:021795 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1796 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271797 GLuint targetid;
1798 if (internal) {
1799 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1800 decoder_->offscreen_resolved_frame_buffer_.reset(
[email protected]ed9f9cd2013-02-27 21:12:351801 new BackFramebuffer(decoder_));
[email protected]de26b3c2011-08-03 21:54:271802 decoder_->offscreen_resolved_frame_buffer_->Create();
[email protected]ed9f9cd2013-02-27 21:12:351803 decoder_->offscreen_resolved_color_texture_.reset(
[email protected]ce296892013-10-24 22:04:361804 new BackTexture(decoder->memory_tracker(), &decoder->state_));
[email protected]de26b3c2011-08-03 21:54:271805 decoder_->offscreen_resolved_color_texture_->Create();
1806
1807 DCHECK(decoder_->offscreen_saved_color_format_);
1808 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:091809 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1810 false);
[email protected]de26b3c2011-08-03 21:54:271811 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1812 decoder_->offscreen_resolved_color_texture_.get());
1813 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1814 GL_FRAMEBUFFER_COMPLETE) {
1815 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1816 << "because offscreen resolved FBO was incomplete.";
1817 return;
1818 }
1819 }
1820 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1821 } else {
1822 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1823 }
1824 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021825 const int width = decoder_->offscreen_size_.width();
1826 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181827 glDisable(GL_SCISSOR_TEST);
[email protected]f42f05b2013-11-15 21:46:181828 decoder->BlitFramebufferHelper(0,
1829 0,
1830 width,
1831 height,
1832 0,
1833 0,
1834 width,
1835 height,
1836 GL_COLOR_BUFFER_BIT,
1837 GL_NEAREST);
[email protected]de26b3c2011-08-03 21:54:271838 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021839}
1840
1841ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1842 if (!resolve_and_bind_)
1843 return;
1844
[email protected]ab09b612013-03-11 22:11:511845 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:301846 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
[email protected]34ff8b0c2010-10-01 20:06:021847 decoder_->RestoreCurrentFramebufferBindings();
[email protected]f731b9462012-10-30 00:35:221848 if (decoder_->state_.enable_flags.scissor_test) {
[email protected]8c3e68782010-10-27 16:41:181849 glEnable(GL_SCISSOR_TEST);
1850 }
[email protected]34ff8b0c2010-10-01 20:06:021851}
1852
[email protected]ce296892013-10-24 22:04:361853BackTexture::BackTexture(
1854 MemoryTracker* memory_tracker,
1855 ContextState* state)
1856 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1857 state_(state),
[email protected]68e81a4a62012-12-13 01:16:481858 bytes_allocated_(0),
[email protected]ff6493f2012-07-31 19:52:251859 id_(0) {
[email protected]6217d392010-03-25 22:08:351860}
1861
[email protected]ed9f9cd2013-02-27 21:12:351862BackTexture::~BackTexture() {
[email protected]6217d392010-03-25 22:08:351863 // This does not destroy the render texture because that would require that
1864 // the associated GL context was current. Just check that it was explicitly
1865 // destroyed.
1866 DCHECK_EQ(id_, 0u);
1867}
1868
[email protected]ed9f9cd2013-02-27 21:12:351869void BackTexture::Create() {
[email protected]40621eb52013-10-08 15:40:301870 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
[email protected]ce296892013-10-24 22:04:361871 state_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351872 Destroy();
1873 glGenTextures(1, &id_);
[email protected]ce296892013-10-24 22:04:361874 ScopedTexture2DBinder binder(state_, id_);
[email protected]3a4d0c52011-06-29 23:11:581875 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1876 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1877 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1878 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161879
1880 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1881 // never called on an offscreen context, no data will ever be uploaded to the
1882 // saved offscreen color texture (it is deferred until to when SwapBuffers
1883 // is called). My idea is that some nvidia drivers might have a bug where
1884 // deleting a texture that has never been populated might cause a
1885 // crash.
1886 glTexImage2D(
1887 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]68e81a4a62012-12-13 01:16:481888
1889 bytes_allocated_ = 16u * 16u * 4u;
1890 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]6217d392010-03-25 22:08:351891}
1892
[email protected]ed9f9cd2013-02-27 21:12:351893bool BackTexture::AllocateStorage(
1894 const gfx::Size& size, GLenum format, bool zero) {
[email protected]6217d392010-03-25 22:08:351895 DCHECK_NE(id_, 0u);
[email protected]40621eb52013-10-08 15:40:301896 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
[email protected]ce296892013-10-24 22:04:361897 state_->GetErrorState());
1898 ScopedTexture2DBinder binder(state_, id_);
[email protected]678a73f2012-12-19 19:22:091899 uint32 image_size = 0;
1900 GLES2Util::ComputeImageDataSizes(
1901 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1902 NULL, NULL);
1903
[email protected]7989c9e2013-01-23 06:39:261904 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1905 return false;
1906 }
1907
[email protected]40d90a22013-04-09 03:39:551908 scoped_ptr<char[]> zero_data;
[email protected]678a73f2012-12-19 19:22:091909 if (zero) {
1910 zero_data.reset(new char[image_size]);
1911 memset(zero_data.get(), 0, image_size);
1912 }
[email protected]6217d392010-03-25 22:08:351913
[email protected]8f1d2aa2013-05-10 23:45:381914 glTexImage2D(GL_TEXTURE_2D,
1915 0, // mip level
1916 format,
1917 size.width(),
1918 size.height(),
1919 0, // border
1920 format,
1921 GL_UNSIGNED_BYTE,
1922 zero_data.get());
[email protected]6217d392010-03-25 22:08:351923
[email protected]d37231fa2010-04-09 21:16:021924 size_ = size;
1925
[email protected]1078f912011-12-23 13:12:141926 bool success = glGetError() == GL_NO_ERROR;
1927 if (success) {
[email protected]68e81a4a62012-12-13 01:16:481928 memory_tracker_.TrackMemFree(bytes_allocated_);
1929 bytes_allocated_ = image_size;
1930 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]1078f912011-12-23 13:12:141931 }
1932 return success;
[email protected]6217d392010-03-25 22:08:351933}
1934
[email protected]ed9f9cd2013-02-27 21:12:351935void BackTexture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351936 DCHECK_NE(id_, 0u);
[email protected]40621eb52013-10-08 15:40:301937 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
[email protected]ce296892013-10-24 22:04:361938 state_->GetErrorState());
1939 ScopedTexture2DBinder binder(state_, id_);
[email protected]6217d392010-03-25 22:08:351940 glCopyTexImage2D(GL_TEXTURE_2D,
1941 0, // level
[email protected]3a4d0c52011-06-29 23:11:581942 format,
[email protected]6217d392010-03-25 22:08:351943 0, 0,
1944 size.width(),
1945 size.height(),
1946 0); // border
1947}
1948
[email protected]ed9f9cd2013-02-27 21:12:351949void BackTexture::Destroy() {
[email protected]6217d392010-03-25 22:08:351950 if (id_ != 0) {
[email protected]40621eb52013-10-08 15:40:301951 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
[email protected]ce296892013-10-24 22:04:361952 state_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351953 glDeleteTextures(1, &id_);
1954 id_ = 0;
1955 }
[email protected]68e81a4a62012-12-13 01:16:481956 memory_tracker_.TrackMemFree(bytes_allocated_);
1957 bytes_allocated_ = 0;
[email protected]6217d392010-03-25 22:08:351958}
1959
[email protected]ed9f9cd2013-02-27 21:12:351960void BackTexture::Invalidate() {
[email protected]97872062010-11-03 19:07:051961 id_ = 0;
1962}
1963
[email protected]d5a28e452013-10-10 01:01:401964BackRenderbuffer::BackRenderbuffer(
1965 RenderbufferManager* renderbuffer_manager,
1966 MemoryTracker* memory_tracker,
1967 ContextState* state)
1968 : renderbuffer_manager_(renderbuffer_manager),
1969 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1970 state_(state),
[email protected]68e81a4a62012-12-13 01:16:481971 bytes_allocated_(0),
[email protected]ff6493f2012-07-31 19:52:251972 id_(0) {
[email protected]6217d392010-03-25 22:08:351973}
1974
[email protected]ed9f9cd2013-02-27 21:12:351975BackRenderbuffer::~BackRenderbuffer() {
[email protected]6217d392010-03-25 22:08:351976 // This does not destroy the render buffer because that would require that
1977 // the associated GL context was current. Just check that it was explicitly
1978 // destroyed.
1979 DCHECK_EQ(id_, 0u);
1980}
1981
[email protected]ed9f9cd2013-02-27 21:12:351982void BackRenderbuffer::Create() {
[email protected]40621eb52013-10-08 15:40:301983 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
[email protected]d5a28e452013-10-10 01:01:401984 state_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351985 Destroy();
1986 glGenRenderbuffersEXT(1, &id_);
1987}
1988
[email protected]f42f05b2013-11-15 21:46:181989bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
1990 const gfx::Size& size,
1991 GLenum format,
[email protected]ed9f9cd2013-02-27 21:12:351992 GLsizei samples) {
[email protected]ab09b612013-03-11 22:11:511993 ScopedGLErrorSuppressor suppressor(
[email protected]d5a28e452013-10-10 01:01:401994 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
1995 ScopedRenderBufferBinder binder(state_, id_);
[email protected]7989c9e2013-01-23 06:39:261996
1997 uint32 estimated_size = 0;
[email protected]d5a28e452013-10-10 01:01:401998 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
[email protected]8e102e102013-09-20 22:50:231999 size.width(), size.height(), samples, format, &estimated_size)) {
[email protected]7989c9e2013-01-23 06:39:262000 return false;
2001 }
2002
2003 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2004 return false;
2005 }
2006
[email protected]34ff8b0c2010-10-01 20:06:022007 if (samples <= 1) {
2008 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2009 format,
2010 size.width(),
2011 size.height());
2012 } else {
[email protected]f42f05b2013-11-15 21:46:182013 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2014 GL_RENDERBUFFER,
2015 samples,
2016 format,
2017 size.width(),
2018 size.height());
[email protected]34ff8b0c2010-10-01 20:06:022019 }
[email protected]1078f912011-12-23 13:12:142020 bool success = glGetError() == GL_NO_ERROR;
2021 if (success) {
[email protected]d5a28e452013-10-10 01:01:402022 // Mark the previously allocated bytes as free.
[email protected]68e81a4a62012-12-13 01:16:482023 memory_tracker_.TrackMemFree(bytes_allocated_);
[email protected]7989c9e2013-01-23 06:39:262024 bytes_allocated_ = estimated_size;
[email protected]d5a28e452013-10-10 01:01:402025 // Track the newly allocated bytes.
[email protected]68e81a4a62012-12-13 01:16:482026 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]1078f912011-12-23 13:12:142027 }
2028 return success;
[email protected]6217d392010-03-25 22:08:352029}
2030
[email protected]ed9f9cd2013-02-27 21:12:352031void BackRenderbuffer::Destroy() {
[email protected]6217d392010-03-25 22:08:352032 if (id_ != 0) {
[email protected]40621eb52013-10-08 15:40:302033 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
[email protected]d5a28e452013-10-10 01:01:402034 state_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352035 glDeleteRenderbuffersEXT(1, &id_);
2036 id_ = 0;
2037 }
[email protected]68e81a4a62012-12-13 01:16:482038 memory_tracker_.TrackMemFree(bytes_allocated_);
2039 bytes_allocated_ = 0;
[email protected]6217d392010-03-25 22:08:352040}
2041
[email protected]ed9f9cd2013-02-27 21:12:352042void BackRenderbuffer::Invalidate() {
[email protected]97872062010-11-03 19:07:052043 id_ = 0;
2044}
2045
[email protected]ed9f9cd2013-02-27 21:12:352046BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
[email protected]6217d392010-03-25 22:08:352047 : decoder_(decoder),
2048 id_(0) {
2049}
2050
[email protected]ed9f9cd2013-02-27 21:12:352051BackFramebuffer::~BackFramebuffer() {
[email protected]6217d392010-03-25 22:08:352052 // This does not destroy the frame buffer because that would require that
2053 // the associated GL context was current. Just check that it was explicitly
2054 // destroyed.
2055 DCHECK_EQ(id_, 0u);
2056}
2057
[email protected]ed9f9cd2013-02-27 21:12:352058void BackFramebuffer::Create() {
[email protected]40621eb52013-10-08 15:40:302059 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2060 decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352061 Destroy();
2062 glGenFramebuffersEXT(1, &id_);
2063}
2064
[email protected]ed9f9cd2013-02-27 21:12:352065void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
[email protected]6217d392010-03-25 22:08:352066 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:512067 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:302068 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352069 ScopedFrameBufferBinder binder(decoder_, id_);
2070 GLuint attach_id = texture ? texture->id() : 0;
2071 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2072 GL_COLOR_ATTACHMENT0,
2073 GL_TEXTURE_2D,
2074 attach_id,
2075 0);
2076}
2077
[email protected]ed9f9cd2013-02-27 21:12:352078void BackFramebuffer::AttachRenderBuffer(GLenum target,
2079 BackRenderbuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:352080 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:512081 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:302082 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352083 ScopedFrameBufferBinder binder(decoder_, id_);
2084 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2085 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:152086 target,
[email protected]6217d392010-03-25 22:08:352087 GL_RENDERBUFFER,
2088 attach_id);
2089}
2090
[email protected]ed9f9cd2013-02-27 21:12:352091void BackFramebuffer::Destroy() {
[email protected]6217d392010-03-25 22:08:352092 if (id_ != 0) {
[email protected]40621eb52013-10-08 15:40:302093 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2094 decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352095 glDeleteFramebuffersEXT(1, &id_);
2096 id_ = 0;
2097 }
2098}
2099
[email protected]ed9f9cd2013-02-27 21:12:352100void BackFramebuffer::Invalidate() {
[email protected]97872062010-11-03 19:07:052101 id_ = 0;
2102}
2103
[email protected]ed9f9cd2013-02-27 21:12:352104GLenum BackFramebuffer::CheckStatus() {
[email protected]6217d392010-03-25 22:08:352105 DCHECK_NE(id_, 0u);
[email protected]40621eb52013-10-08 15:40:302106 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2107 decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352108 ScopedFrameBufferBinder binder(decoder_, id_);
2109 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2110}
2111
[email protected]aa7666122011-09-02 19:45:522112GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2113 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:322114}
2115
[email protected]aa7666122011-09-02 19:45:522116GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:392117 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:572118 group_(group),
[email protected]1d82e822013-04-10 21:32:322119 logger_(&debug_marker_manager_),
[email protected]d3eba342013-04-18 21:11:502120 state_(group_->feature_info(), &logger_),
[email protected]43410e92012-04-20 17:06:282121 unpack_flip_y_(false),
2122 unpack_premultiply_alpha_(false),
[email protected]6c75c712012-06-19 15:43:172123 unpack_unpremultiply_alpha_(false),
[email protected]b1122982010-05-17 23:04:242124 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:492125 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:242126 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:402127 fixed_attrib_buffer_id_(0),
2128 fixed_attrib_buffer_size_(0),
[email protected]34ff8b0c2010-10-01 20:06:022129 offscreen_target_color_format_(0),
2130 offscreen_target_depth_format_(0),
2131 offscreen_target_stencil_format_(0),
2132 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:562133 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:052134 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:132135 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:462136 back_buffer_has_depth_(false),
2137 back_buffer_has_stencil_(false),
[email protected]60f22d32012-12-12 00:31:582138 backbuffer_needs_clear_bits_(0),
[email protected]a3a93e7b2010-08-28 00:48:562139 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:052140 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:112141 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:002142 feature_info_(group_->feature_info()),
[email protected]38d139d2011-07-14 00:38:432143 frame_number_(0),
[email protected]706b69f2012-07-27 04:59:302144 has_robustness_extension_(false),
[email protected]75c023c2011-08-22 23:54:512145 reset_status_(GL_NO_ERROR),
[email protected]93a7d98f2013-07-11 00:04:222146 reset_by_robustness_extension_(false),
[email protected]f0d74742011-10-03 16:31:042147 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:102148 derivatives_explicitly_enabled_(false),
[email protected]70dc60932013-06-04 03:33:492149 frag_depth_explicitly_enabled_(false),
[email protected]aff39ac82013-06-08 04:53:132150 draw_buffers_explicitly_enabled_(false),
[email protected]43410e92012-04-20 17:06:282151 compile_shader_always_succeeds_(false),
[email protected]cae20172012-12-07 00:06:192152 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2153 switches::kEnableGPUServiceLoggingGPU)),
[email protected]1868a342012-11-07 15:56:022154 viewport_max_width_(0),
[email protected]4a4c18b2013-09-13 22:50:102155 viewport_max_height_(0),
[email protected]345ba902013-11-14 21:39:002156 texture_state_(group_->feature_info()
2157 ->workarounds()
2158 .texsubimage2d_faster_than_teximage2d),
[email protected]4a4c18b2013-09-13 22:50:102159 validation_texture_(0),
2160 validation_fbo_multisample_(0),
2161 validation_fbo_(0) {
[email protected]3b1ecc262011-08-03 22:49:572162 DCHECK(group);
2163
[email protected]b1122982010-05-17 23:04:242164 attrib_0_value_.v[0] = 0.0f;
2165 attrib_0_value_.v[1] = 0.0f;
2166 attrib_0_value_.v[2] = 0.0f;
2167 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:152168
[email protected]c2f8c8402010-12-06 18:07:242169 // The shader translator is used for WebGL even when running on EGL
2170 // because additional restrictions are needed (like only enabling
2171 // GL_OES_standard_derivatives on demand). It is used for the unit
[email protected]4b7eba92013-01-08 02:23:562172 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2173 // the empty string to CompileShader and this is not a valid shader.
2174 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
[email protected]39ba4f02012-03-26 01:16:002175 CommandLine::ForCurrentProcess()->HasSwitch(
2176 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:152177 use_shader_translator_ = false;
2178 }
[email protected]96449d2c2009-11-25 00:01:322179}
2180
[email protected]80eb6b52012-01-19 00:14:412181GLES2DecoderImpl::~GLES2DecoderImpl() {
2182}
2183
[email protected]c410da802011-03-14 19:17:412184bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:382185 const scoped_refptr<gfx::GLSurface>& surface,
2186 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:232187 bool offscreen,
[email protected]c410da802011-03-14 19:17:412188 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:292189 const DisallowedFeatures& disallowed_features,
[email protected]3c644d82011-06-20 19:58:242190 const std::vector<int32>& attribs) {
[email protected]3551cb202012-05-24 10:55:322191 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
[email protected]63c9b052012-05-17 18:27:382192 DCHECK(context->IsCurrent(surface.get()));
[email protected]66791e382010-07-14 20:48:302193 DCHECK(!context_.get());
2194
[email protected]55e136f2013-04-03 18:50:062195 set_initialized();
[email protected]fb97b662013-02-20 23:02:142196 gpu_tracer_ = GPUTracer::Create();
[email protected]8f9b8dd2013-09-12 18:05:132197 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
[email protected]fb97b662013-02-20 23:02:142198
[email protected]e844ae22012-01-14 03:36:262199 if (CommandLine::ForCurrentProcess()->HasSwitch(
2200 switches::kEnableGPUDebugging)) {
2201 set_debug(true);
2202 }
2203
[email protected]39ba4f02012-03-26 01:16:002204 if (CommandLine::ForCurrentProcess()->HasSwitch(
2205 switches::kEnableGPUCommandLogging)) {
2206 set_log_commands(true);
2207 }
2208
[email protected]062c38b2012-01-18 03:25:102209 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2210 switches::kCompileShaderAlwaysSucceeds);
2211
[email protected]f62a5ab2011-05-23 20:34:152212
[email protected]63c9b052012-05-17 18:27:382213 // Take ownership of the context and surface. The surface can be replaced with
2214 // SetSurface.
[email protected]fbe20372011-06-01 01:46:382215 context_ = context;
[email protected]63c9b052012-05-17 18:27:382216 surface_ = surface;
[email protected]eb54a562010-01-20 21:55:182217
[email protected]956aec52013-09-05 15:41:192218 if (!group_->Initialize(this, disallowed_features)) {
[email protected]09ddb91f2011-04-14 23:16:222219 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392220 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422221 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]63c9b052012-05-17 18:27:382222 Destroy(true);
[email protected]ae1741092010-11-17 19:16:032223 return false;
[email protected]a3ded6d2010-10-19 06:44:392224 }
[email protected]b64c24952012-04-19 03:20:272225 CHECK_GL_ERROR();
[email protected]43410e92012-04-20 17:06:282226
[email protected]e82fb792011-09-22 00:33:292227 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502228
[email protected]af6380962012-11-29 23:24:132229 state_.attrib_values.resize(group_->max_vertex_attribs());
[email protected]944b62f32012-09-27 02:20:462230 default_vertex_attrib_manager_ = new VertexAttribManager();
2231 default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
2232
[email protected]ab4fd7282012-10-12 16:25:572233 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2234 DoBindVertexArrayOES(0);
[email protected]876f6fee2010-08-02 23:10:322235
[email protected]7cd76fd2013-06-02 21:11:112236 query_manager_.reset(new QueryManager(this, feature_info_.get()));
[email protected]944b62f32012-09-27 02:20:462237 vertex_array_manager_.reset(new VertexArrayManager());
[email protected]882ba1e22012-03-08 19:02:532238
[email protected]302ce6d2011-07-07 23:28:112239 util_.set_num_compressed_texture_formats(
2240 validators_->compressed_texture_format.GetValues().size());
2241
[email protected]1071e572011-02-09 20:00:122242 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2243 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2244 // OpenGL ES 2.0 does not have this issue.
2245 glEnableVertexAttribArray(0);
2246 }
[email protected]b1122982010-05-17 23:04:242247 glGenBuffersARB(1, &attrib_0_buffer_id_);
2248 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2249 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2250 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402251 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082252
[email protected]1868a342012-11-07 15:56:022253 state_.texture_units.resize(group_->max_texture_units());
2254 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492255 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312256 // We want the last bind to be 2D.
[email protected]370eaf12013-05-18 09:19:492257 TextureRef* ref;
[email protected]62e155e2012-10-23 22:43:152258 if (features().oes_egl_image_external) {
[email protected]370eaf12013-05-18 09:19:492259 ref = texture_manager()->GetDefaultTextureInfo(
[email protected]02965c22013-03-09 02:40:072260 GL_TEXTURE_EXTERNAL_OES);
[email protected]370eaf12013-05-18 09:19:492261 state_.texture_units[tt].bound_texture_external_oes = ref;
2262 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
[email protected]61eeb33f2011-07-26 15:30:312263 }
[email protected]62e155e2012-10-23 22:43:152264 if (features().arb_texture_rectangle) {
[email protected]370eaf12013-05-18 09:19:492265 ref = texture_manager()->GetDefaultTextureInfo(
[email protected]02965c22013-03-09 02:40:072266 GL_TEXTURE_RECTANGLE_ARB);
[email protected]370eaf12013-05-18 09:19:492267 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2268 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
[email protected]e51bdf32011-11-23 22:21:462269 }
[email protected]370eaf12013-05-18 09:19:492270 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2271 state_.texture_units[tt].bound_texture_cube_map = ref;
2272 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2273 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2274 state_.texture_units[tt].bound_texture_2d = ref;
2275 glBindTexture(GL_TEXTURE_2D, ref->service_id());
[email protected]1958e0e2010-04-22 05:17:152276 }
[email protected]00f893d2010-08-24 18:55:492277 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502278 CHECK_GL_ERROR();
2279
[email protected]763eaf72013-08-16 00:58:562280 ContextCreationAttribHelper attrib_parser;
[email protected]297ca1c2011-06-20 23:08:462281 if (!attrib_parser.Parse(attribs))
2282 return false;
[email protected]41c56362011-06-14 16:47:432283
[email protected]069944672012-04-25 20:52:232284 if (offscreen) {
[email protected]34ff8b0c2010-10-01 20:06:022285 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]b0609652012-12-14 07:24:542286 features().chromium_framebuffer_multisample) {
[email protected]34ff8b0c2010-10-01 20:06:022287 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432288 // max_sample_count must be initialized to a sane value. If
2289 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2290 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022291 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2292 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2293 max_sample_count);
2294 } else {
2295 offscreen_target_samples_ = 1;
2296 }
[email protected]8a61d872012-01-20 12:43:562297 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022298
2299 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2300 const bool rgb8_supported =
2301 context_->HasExtension("GL_OES_rgb8_rgba8");
2302 // The only available default render buffer formats in GLES2 have very
2303 // little precision. Don't enable multisampling unless 8-bit render
2304 // buffer formats are available--instead fall back to 8-bit textures.
2305 if (rgb8_supported && offscreen_target_samples_ > 1) {
2306 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2307 GL_RGBA8 : GL_RGB8;
2308 } else {
2309 offscreen_target_samples_ = 1;
2310 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2311 GL_RGBA : GL_RGB;
2312 }
2313
2314 // ANGLE only supports packed depth/stencil formats, so use it if it is
2315 // available.
2316 const bool depth24_stencil8_supported =
[email protected]f42f05b2013-11-15 21:46:182317 feature_info_->feature_flags().packed_depth24_stencil8;
[email protected]d366c482010-10-20 00:11:272318 VLOG(1) << "GL_OES_packed_depth_stencil "
2319 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002320 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2321 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022322 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2323 offscreen_target_stencil_format_ = 0;
2324 } else {
2325 // It may be the case that this depth/stencil combination is not
2326 // supported, but this will be checked later by CheckFramebufferStatus.
2327 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2328 GL_DEPTH_COMPONENT16 : 0;
2329 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2330 GL_STENCIL_INDEX8 : 0;
2331 }
2332 } else {
2333 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2334 GL_RGBA : GL_RGB;
2335
2336 // If depth is requested at all, use the packed depth stencil format if
2337 // it's available, as some desktop GL drivers don't support any non-packed
2338 // formats for depth attachments.
2339 const bool depth24_stencil8_supported =
[email protected]f42f05b2013-11-15 21:46:182340 feature_info_->feature_flags().packed_depth24_stencil8;
[email protected]d366c482010-10-20 00:11:272341 VLOG(1) << "GL_EXT_packed_depth_stencil "
2342 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022343
[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 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2350 GL_DEPTH_COMPONENT : 0;
2351 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2352 GL_STENCIL_INDEX : 0;
2353 }
2354 }
2355
[email protected]97872062010-11-03 19:07:052356 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2357 GL_RGBA : GL_RGB;
2358
[email protected]6217d392010-03-25 22:08:352359 // Create the target frame buffer. This is the one that the client renders
2360 // directly to.
[email protected]ed9f9cd2013-02-27 21:12:352361 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
[email protected]6217d392010-03-25 22:08:352362 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022363 // Due to GLES2 format limitations, either the color texture (for
2364 // non-multisampling) or the color render buffer (for multisampling) will be
2365 // attached to the offscreen frame buffer. The render buffer has more
2366 // limited formats available to it, but the texture can't do multisampling.
2367 if (IsOffscreenBufferMultisampled()) {
[email protected]d5a28e452013-10-10 01:01:402368 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2369 renderbuffer_manager(), memory_tracker(), &state_));
[email protected]34ff8b0c2010-10-01 20:06:022370 offscreen_target_color_render_buffer_->Create();
2371 } else {
[email protected]ce296892013-10-24 22:04:362372 offscreen_target_color_texture_.reset(new BackTexture(
2373 memory_tracker(), &state_));
[email protected]34ff8b0c2010-10-01 20:06:022374 offscreen_target_color_texture_->Create();
2375 }
[email protected]d5a28e452013-10-10 01:01:402376 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2377 renderbuffer_manager(), memory_tracker(), &state_));
[email protected]b9363b22010-06-09 22:06:152378 offscreen_target_depth_render_buffer_->Create();
[email protected]d5a28e452013-10-10 01:01:402379 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2380 renderbuffer_manager(), memory_tracker(), &state_));
[email protected]b9363b22010-06-09 22:06:152381 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352382
2383 // Create the saved offscreen texture. The target frame buffer is copied
2384 // here when SwapBuffers is called.
[email protected]ed9f9cd2013-02-27 21:12:352385 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
[email protected]34ff8b0c2010-10-01 20:06:022386 offscreen_saved_frame_buffer_->Create();
2387 //
[email protected]ce296892013-10-24 22:04:362388 offscreen_saved_color_texture_.reset(new BackTexture(
2389 memory_tracker(), &state_));
[email protected]6217d392010-03-25 22:08:352390 offscreen_saved_color_texture_->Create();
2391
[email protected]6217d392010-03-25 22:08:352392 // Allocate the render buffers at their initial size and check the status
2393 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592394 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012395 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]63c9b052012-05-17 18:27:382396 Destroy(true);
[email protected]6217d392010-03-25 22:08:352397 return false;
2398 }
2399
[email protected]678a73f2012-12-19 19:22:092400 // Allocate the offscreen saved color texture.
2401 DCHECK(offscreen_saved_color_format_);
2402 offscreen_saved_color_texture_->AllocateStorage(
2403 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2404
2405 offscreen_saved_frame_buffer_->AttachRenderTexture(
2406 offscreen_saved_color_texture_.get());
2407 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2408 GL_FRAMEBUFFER_COMPLETE) {
2409 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2410 Destroy(true);
2411 return false;
2412 }
2413
[email protected]6217d392010-03-25 22:08:352414 // Bind to the new default frame buffer (the offscreen target frame buffer).
2415 // This should now be associated with ID zero.
2416 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]62e65f02013-05-29 22:28:102417 } else {
2418 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2419 // These are NOT if the back buffer has these proprorties. They are
2420 // if we want the command buffer to enforce them regardless of what
2421 // the real backbuffer is assuming the real back buffer gives us more than
2422 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2423 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2424 // can't do anything about that.
2425
2426 GLint v = 0;
2427 glGetIntegerv(GL_ALPHA_BITS, &v);
2428 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2429 // user requested RGB then RGB. If the user did not specify a preference
2430 // than use whatever we were given. Same for DEPTH and STENCIL.
2431 back_buffer_color_format_ =
2432 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2433 glGetIntegerv(GL_DEPTH_BITS, &v);
2434 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2435 glGetIntegerv(GL_STENCIL_BITS, &v);
2436 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
[email protected]6217d392010-03-25 22:08:352437 }
2438
[email protected]76a0ee102010-04-07 21:03:042439 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2440 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2441 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372442 // mailing list archives. It also implicitly enables the desktop GL
2443 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2444 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152445 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2446 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372447 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152448 }
[email protected]de17df392010-04-23 21:09:412449
[email protected]706b69f2012-07-27 04:59:302450 has_robustness_extension_ =
2451 context->HasExtension("GL_ARB_robustness") ||
2452 context->HasExtension("GL_EXT_robustness");
[email protected]38d139d2011-07-14 00:38:432453
[email protected]c2f8c8402010-12-06 18:07:242454 if (!InitializeShaderTranslator()) {
2455 return false;
[email protected]de17df392010-04-23 21:09:412456 }
[email protected]76a0ee102010-04-07 21:03:042457
[email protected]e259eb412012-10-13 05:47:242458 state_.viewport_width = size.width();
2459 state_.viewport_height = size.height();
[email protected]43410e92012-04-20 17:06:282460
[email protected]5904806b2012-05-08 18:10:222461 GLint viewport_params[4] = { 0 };
[email protected]43410e92012-04-20 17:06:282462 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
[email protected]1868a342012-11-07 15:56:022463 viewport_max_width_ = viewport_params[0];
2464 viewport_max_height_ = viewport_params[1];
[email protected]43410e92012-04-20 17:06:282465
[email protected]88a61bf2012-10-27 13:00:422466 state_.scissor_width = state_.viewport_width;
2467 state_.scissor_height = state_.viewport_height;
2468
[email protected]11f3e702012-06-19 19:00:012469 // Set all the default state because some GL drivers get it wrong.
[email protected]f731b9462012-10-30 00:35:222470 state_.InitCapabilities();
2471 state_.InitState();
[email protected]e259eb412012-10-13 05:47:242472 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]11f3e702012-06-19 19:00:012473
2474 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2475 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2476 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2477 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2478
[email protected]88cfd132013-07-11 00:59:002479 bool call_gl_clear = true;
2480#if defined(OS_ANDROID)
2481 // Temporary workaround for Android WebView because this clear ignores the
2482 // clip and corrupts that external UI of the App. Not calling glClear is ok
2483 // because the system already clears the buffer before each draw. Proper
2484 // fix might be setting the scissor clip properly before initialize. See
2485 // crbug.com/259023 for details.
2486 call_gl_clear = surface_->GetHandle();
2487#endif
2488 if (call_gl_clear) {
2489 // Clear the backbuffer.
2490 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2491 }
[email protected]561cc0a62013-05-07 18:34:452492
[email protected]62e155e2012-10-23 22:43:152493 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
[email protected]dd289a5d62012-06-30 22:05:462494 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2495 }
[email protected]dd289a5d62012-06-30 22:05:462496
[email protected]9b753992013-04-27 02:04:412497 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2498 context_->SetUnbindFboOnMakeCurrent();
[email protected]85cb4682013-04-20 00:54:242499 }
[email protected]85cb4682013-04-20 00:54:242500
[email protected]40245ccf2013-11-13 04:00:492501 if (feature_info_->workarounds().release_image_after_use) {
2502 image_manager()->SetReleaseAfterUse();
2503 }
2504
[email protected]97419c02013-04-10 02:52:382505 // Only compositor contexts are known to use only the subset of GL
2506 // that can be safely migrated between the iGPU and the dGPU. Mark
2507 // those contexts as safe to forcibly transition between the GPUs.
2508 // http://crbug.com/180876, http://crbug.com/227228
2509 if (!offscreen)
2510 context_->SetSafeToForceGpuSwitch();
2511
[email protected]85a4ac22013-05-31 01:58:472512 async_pixel_transfer_manager_.reset(
[email protected]498b5c072013-06-04 19:30:072513 AsyncPixelTransferManager::Create(context.get()));
2514 async_pixel_transfer_manager_->Initialize(texture_manager());
[email protected]32145a92012-12-17 09:01:592515
[email protected]91c94eb2013-10-22 10:32:542516 framebuffer_manager()->AddObserver(this);
2517
[email protected]246a70452010-03-05 21:53:502518 return true;
[email protected]96449d2c2009-11-25 00:01:322519}
2520
[email protected]302ce6d2011-07-07 23:28:112521void GLES2DecoderImpl::UpdateCapabilities() {
2522 util_.set_num_compressed_texture_formats(
2523 validators_->compressed_texture_format.GetValues().size());
2524 util_.set_num_shader_binary_formats(
2525 validators_->shader_binary_format.GetValues().size());
2526}
2527
[email protected]c2f8c8402010-12-06 18:07:242528bool GLES2DecoderImpl::InitializeShaderTranslator() {
[email protected]a5d3dad2012-05-26 04:34:442529 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2530
[email protected]c2f8c8402010-12-06 18:07:242531 if (!use_shader_translator_) {
2532 return true;
2533 }
2534 ShBuiltInResources resources;
2535 ShInitBuiltInResources(&resources);
2536 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2537 resources.MaxVertexUniformVectors =
2538 group_->max_vertex_uniform_vectors();
2539 resources.MaxVaryingVectors = group_->max_varying_vectors();
2540 resources.MaxVertexTextureImageUnits =
2541 group_->max_vertex_texture_image_units();
2542 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2543 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2544 resources.MaxFragmentUniformVectors =
2545 group_->max_fragment_uniform_vectors();
[email protected]2f143d482013-03-14 18:04:492546 resources.MaxDrawBuffers = group_->max_draw_buffers();
[email protected]a0b78142013-05-23 00:47:242547 resources.MaxExpressionComplexity = 256;
2548 resources.MaxCallStackDepth = 256;
[email protected]f0d74742011-10-03 16:31:042549
[email protected]9e98f61b2013-03-05 02:21:142550#if (ANGLE_SH_VERSION >= 110)
[email protected]46c86752013-05-21 05:08:392551 GLint range[2] = { 0, 0 };
[email protected]8dc1bf92013-03-12 03:58:212552 GLint precision = 0;
2553 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2554 range, &precision);
[email protected]448e459e2013-06-12 17:00:412555 resources.FragmentPrecisionHigh =
2556 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
[email protected]9e98f61b2013-03-05 02:21:142557#endif
2558
[email protected]f0d74742011-10-03 16:31:042559 if (force_webgl_glsl_validation_) {
2560 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
[email protected]70dc60932013-06-04 03:33:492561 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
[email protected]aff39ac82013-06-08 04:53:132562 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
[email protected]cd8f1892013-09-05 00:14:442563 if (!draw_buffers_explicitly_enabled_)
2564 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042565 } else {
2566 resources.OES_standard_derivatives =
[email protected]62e155e2012-10-23 22:43:152567 features().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462568 resources.ARB_texture_rectangle =
[email protected]62e155e2012-10-23 22:43:152569 features().arb_texture_rectangle ? 1 : 0;
[email protected]70e7bb12012-09-29 14:01:062570 resources.OES_EGL_image_external =
[email protected]62e155e2012-10-23 22:43:152571 features().oes_egl_image_external ? 1 : 0;
[email protected]2f143d482013-03-14 18:04:492572 resources.EXT_draw_buffers =
2573 features().ext_draw_buffers ? 1 : 0;
[email protected]70dc60932013-06-04 03:33:492574 resources.EXT_frag_depth =
2575 features().ext_frag_depth ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042576 }
2577
[email protected]26b61442013-03-17 16:12:012578 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2579 : SH_GLES2_SPEC;
[email protected]6aedcdc2013-01-24 01:25:052580 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
[email protected]3d944a82013-02-12 19:09:022581#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
[email protected]6aedcdc2013-01-24 01:25:052582 resources.HashFunction = &CityHashForAngle;
[email protected]3d944a82013-02-12 19:09:022583#else
2584 resources.HashFunction = &CityHash64;
2585#endif
[email protected]6aedcdc2013-01-24 01:25:052586 else
2587 resources.HashFunction = NULL;
[email protected]a2a0fe762011-09-20 00:59:122588 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2589 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2590 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
[email protected]a6739bc2013-09-07 04:45:212591 int driver_bug_workarounds = 0;
2592 if (workarounds().needs_glsl_built_in_function_emulation)
2593 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
[email protected]81187c62013-09-09 23:54:542594 if (workarounds().init_gl_position_in_vertex_shader)
2595 driver_bug_workarounds |= SH_INIT_GL_POSITION;
[email protected]f0c87602013-10-17 19:34:112596 if (workarounds().unfold_short_circuit_as_ternary_operation)
2597 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
[email protected]87fb6ab2012-06-13 22:28:042598
2599 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2600 vertex_translator_ = cache->GetTranslator(
2601 SH_VERTEX_SHADER, shader_spec, &resources,
[email protected]a6739bc2013-09-07 04:45:212602 implementation_type,
2603 static_cast<ShCompileOptions>(driver_bug_workarounds));
[email protected]87fb6ab2012-06-13 22:28:042604 if (!vertex_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242605 LOG(ERROR) << "Could not initialize vertex shader translator.";
[email protected]63c9b052012-05-17 18:27:382606 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242607 return false;
2608 }
[email protected]87fb6ab2012-06-13 22:28:042609
2610 fragment_translator_ = cache->GetTranslator(
2611 SH_FRAGMENT_SHADER, shader_spec, &resources,
[email protected]a6739bc2013-09-07 04:45:212612 implementation_type,
2613 static_cast<ShCompileOptions>(driver_bug_workarounds));
[email protected]87fb6ab2012-06-13 22:28:042614 if (!fragment_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242615 LOG(ERROR) << "Could not initialize fragment shader translator.";
[email protected]63c9b052012-05-17 18:27:382616 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242617 return false;
2618 }
2619 return true;
2620}
2621
[email protected]ae51d192010-04-27 00:48:032622bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472623 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352624 if (GetBuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032625 return false;
2626 }
2627 }
[email protected]40d90a22013-04-09 03:39:552628 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032629 glGenBuffersARB(n, service_ids.get());
2630 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352631 CreateBuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032632 }
2633 return true;
2634}
2635
2636bool GLES2DecoderImpl::GenFramebuffersHelper(
2637 GLsizei n, const GLuint* client_ids) {
2638 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352639 if (GetFramebuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032640 return false;
2641 }
2642 }
[email protected]40d90a22013-04-09 03:39:552643 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032644 glGenFramebuffersEXT(n, service_ids.get());
2645 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352646 CreateFramebuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032647 }
2648 return true;
2649}
2650
2651bool GLES2DecoderImpl::GenRenderbuffersHelper(
2652 GLsizei n, const GLuint* client_ids) {
2653 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352654 if (GetRenderbuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032655 return false;
2656 }
2657 }
[email protected]40d90a22013-04-09 03:39:552658 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032659 glGenRenderbuffersEXT(n, service_ids.get());
2660 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352661 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032662 }
2663 return true;
2664}
2665
2666bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2667 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352668 if (GetTexture(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032669 return false;
2670 }
2671 }
[email protected]40d90a22013-04-09 03:39:552672 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032673 glGenTextures(n, service_ids.get());
2674 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352675 CreateTexture(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032676 }
2677 return true;
2678}
2679
2680void GLES2DecoderImpl::DeleteBuffersHelper(
2681 GLsizei n, const GLuint* client_ids) {
2682 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]16ccec12013-02-28 03:40:212683 Buffer* buffer = GetBuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102684 if (buffer && !buffer->IsDeleted()) {
[email protected]e259eb412012-10-13 05:47:242685 state_.vertex_attrib_manager->Unbind(buffer);
[email protected]7cd76fd2013-06-02 21:11:112686 if (state_.bound_array_buffer.get() == buffer) {
[email protected]e259eb412012-10-13 05:47:242687 state_.bound_array_buffer = NULL;
[email protected]a0b78dc2011-11-11 10:43:102688 }
[email protected]ed9f9cd2013-02-27 21:12:352689 RemoveBuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032690 }
[email protected]a93bb842010-02-16 23:03:472691 }
[email protected]07f54fcc2009-12-22 02:46:302692}
2693
[email protected]ae51d192010-04-27 00:48:032694void GLES2DecoderImpl::DeleteFramebuffersHelper(
2695 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452696 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152697 features().chromium_framebuffer_multisample;
[email protected]b177ae22011-11-01 03:29:112698
[email protected]a25fa872010-03-25 02:57:582699 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352700 Framebuffer* framebuffer =
2701 GetFramebuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102702 if (framebuffer && !framebuffer->IsDeleted()) {
[email protected]9d3b2e12013-10-02 01:04:342703 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2704 framebuffer_state_.bound_draw_framebuffer = NULL;
[email protected]c986af502013-08-14 01:04:442705 framebuffer_state_.clear_state_dirty = true;
[email protected]ebfb73c2012-08-15 02:37:452706 GLenum target = supports_separate_framebuffer_binds ?
2707 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]b177ae22011-11-01 03:29:112708 glBindFramebufferEXT(target, GetBackbufferServiceId());
2709 }
[email protected]9d3b2e12013-10-02 01:04:342710 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2711 framebuffer_state_.bound_read_framebuffer = NULL;
[email protected]ebfb73c2012-08-15 02:37:452712 GLenum target = supports_separate_framebuffer_binds ?
2713 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]b177ae22011-11-01 03:29:112714 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462715 }
[email protected]70d34263c2013-01-09 00:27:452716 OnFboChanged();
[email protected]ed9f9cd2013-02-27 21:12:352717 RemoveFramebuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032718 }
[email protected]a25fa872010-03-25 02:57:582719 }
[email protected]07f54fcc2009-12-22 02:46:302720}
2721
[email protected]ae51d192010-04-27 00:48:032722void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2723 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452724 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152725 features().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582726 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352727 Renderbuffer* renderbuffer =
2728 GetRenderbuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102729 if (renderbuffer && !renderbuffer->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:112730 if (state_.bound_renderbuffer.get() == renderbuffer) {
[email protected]e259eb412012-10-13 05:47:242731 state_.bound_renderbuffer = NULL;
[email protected]a0b78dc2011-11-11 10:43:102732 }
2733 // Unbind from current framebuffers.
[email protected]ebfb73c2012-08-15 02:37:452734 if (supports_separate_framebuffer_binds) {
[email protected]9d3b2e12013-10-02 01:04:342735 if (framebuffer_state_.bound_read_framebuffer.get()) {
2736 framebuffer_state_.bound_read_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112737 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102738 }
[email protected]9d3b2e12013-10-02 01:04:342739 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2740 framebuffer_state_.bound_draw_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112741 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102742 }
2743 } else {
[email protected]9d3b2e12013-10-02 01:04:342744 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2745 framebuffer_state_.bound_draw_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112746 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102747 }
2748 }
[email protected]c986af502013-08-14 01:04:442749 framebuffer_state_.clear_state_dirty = true;
[email protected]ed9f9cd2013-02-27 21:12:352750 RemoveRenderbuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032751 }
[email protected]a25fa872010-03-25 02:57:582752 }
[email protected]07f54fcc2009-12-22 02:46:302753}
2754
[email protected]ae51d192010-04-27 00:48:032755void GLES2DecoderImpl::DeleteTexturesHelper(
2756 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452757 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152758 features().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472759 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]370eaf12013-05-18 09:19:492760 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2761 if (texture_ref) {
2762 Texture* texture = texture_ref->texture();
[email protected]a0b78dc2011-11-11 10:43:102763 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:442764 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:462765 }
[email protected]370eaf12013-05-18 09:19:492766 // Unbind texture_ref from texture_ref units.
[email protected]1868a342012-11-07 15:56:022767 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
[email protected]370eaf12013-05-18 09:19:492768 state_.texture_units[jj].Unbind(texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102769 }
2770 // Unbind from current framebuffers.
[email protected]ebfb73c2012-08-15 02:37:452771 if (supports_separate_framebuffer_binds) {
[email protected]9d3b2e12013-10-02 01:04:342772 if (framebuffer_state_.bound_read_framebuffer.get()) {
2773 framebuffer_state_.bound_read_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112774 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102775 }
[email protected]9d3b2e12013-10-02 01:04:342776 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2777 framebuffer_state_.bound_draw_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112778 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102779 }
2780 } else {
[email protected]9d3b2e12013-10-02 01:04:342781 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2782 framebuffer_state_.bound_draw_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112783 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102784 }
2785 }
[email protected]e51bdf32011-11-23 22:21:462786#if defined(OS_MACOSX)
[email protected]4f9958142013-07-02 03:58:072787 GLuint service_id = texture->service_id();
[email protected]e51bdf32011-11-23 22:21:462788 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2789 ReleaseIOSurfaceForTexture(service_id);
2790 }
2791#endif
[email protected]ed9f9cd2013-02-27 21:12:352792 RemoveTexture(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032793 }
[email protected]a93bb842010-02-16 23:03:472794 }
[email protected]07f54fcc2009-12-22 02:46:302795}
2796
[email protected]43f28f832010-02-03 02:28:482797// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322798
[email protected]eb54a562010-01-20 21:55:182799bool GLES2DecoderImpl::MakeCurrent() {
[email protected]63c9b052012-05-17 18:27:382800 if (!context_.get() || !context_->MakeCurrent(surface_.get()))
2801 return false;
2802
2803 if (WasContextLost()) {
[email protected]38d139d2011-07-14 00:38:432804 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
[email protected]e9f0ca82013-04-01 23:52:292805
2806 // Some D3D drivers cannot recover from device lost in the GPU process
2807 // sandbox. Allow a new GPU process to launch.
2808 if (workarounds().exit_on_context_lost) {
2809 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2810 << " a D3D device in the Chrome GPU process sandbox.";
[email protected]6eb775352013-08-27 05:57:162811#if defined(OS_WIN)
2812 base::win::SetShouldCrashOnProcessDetach(false);
2813#endif
[email protected]e9f0ca82013-04-01 23:52:292814 exit(0);
2815 }
2816
[email protected]63c9b052012-05-17 18:27:382817 return false;
[email protected]38d139d2011-07-14 00:38:432818 }
2819
[email protected]69a8701e2013-03-07 21:31:092820 ProcessFinishedAsyncTransfers();
[email protected]69a8701e2013-03-07 21:31:092821
[email protected]9b753992013-04-27 02:04:412822 // Rebind the FBO if it was unbound by the context.
2823 if (workarounds().unbind_fbo_on_context_switch)
2824 RestoreFramebufferBindings();
2825
[email protected]c986af502013-08-14 01:04:442826 framebuffer_state_.clear_state_dirty = true;
[email protected]370eaf12013-05-18 09:19:492827
[email protected]69a8701e2013-03-07 21:31:092828 return true;
2829}
2830
2831void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
[email protected]5a36dc132013-07-23 23:17:552832 ProcessPendingReadPixels();
[email protected]fe8d73c2013-02-16 22:37:322833 if (engine() && query_manager_.get())
2834 query_manager_->ProcessPendingTransferQueries();
2835
[email protected]5b3a8e02013-03-13 05:36:442836 // TODO(epenner): Is there a better place to do this?
2837 // This needs to occur before we execute any batch of commands
2838 // from the client, as the client may have recieved an async
2839 // completion while issuing those commands.
2840 // "DidFlushStart" would be ideal if we had such a callback.
[email protected]b68b100752013-06-05 08:34:482841 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
[email protected]eb54a562010-01-20 21:55:182842}
2843
[email protected]a96a6022011-11-04 00:58:122844void GLES2DecoderImpl::ReleaseCurrent() {
2845 if (context_.get())
2846 context_->ReleaseCurrent(surface_.get());
2847}
2848
[email protected]8e3e0662010-08-23 18:46:302849static void RebindCurrentFramebuffer(
2850 GLenum target,
[email protected]4d8f0dd2013-03-09 14:37:062851 Framebuffer* framebuffer,
[email protected]a3783712012-01-20 22:18:242852 GLuint back_buffer_service_id) {
[email protected]4d8f0dd2013-03-09 14:37:062853 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462854
[email protected]a3783712012-01-20 22:18:242855 if (framebuffer_id == 0) {
2856 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302857 }
[email protected]297ca1c2011-06-20 23:08:462858
[email protected]8e3e0662010-08-23 18:46:302859 glBindFramebufferEXT(target, framebuffer_id);
2860}
2861
2862void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]c986af502013-08-14 01:04:442863 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:462864
[email protected]62e155e2012-10-23 22:43:152865 if (!features().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302866 RebindCurrentFramebuffer(
2867 GL_FRAMEBUFFER,
[email protected]9d3b2e12013-10-02 01:04:342868 framebuffer_state_.bound_draw_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242869 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302870 } else {
2871 RebindCurrentFramebuffer(
2872 GL_READ_FRAMEBUFFER_EXT,
[email protected]9d3b2e12013-10-02 01:04:342873 framebuffer_state_.bound_read_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242874 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302875 RebindCurrentFramebuffer(
2876 GL_DRAW_FRAMEBUFFER_EXT,
[email protected]9d3b2e12013-10-02 01:04:342877 framebuffer_state_.bound_draw_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242878 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302879 }
[email protected]70d34263c2013-01-09 00:27:452880 OnFboChanged();
[email protected]8e3e0662010-08-23 18:46:302881}
2882
[email protected]0d6bfdc2011-11-02 01:32:202883bool GLES2DecoderImpl::CheckFramebufferValid(
[email protected]ed9f9cd2013-02-27 21:12:352884 Framebuffer* framebuffer,
[email protected]0d6bfdc2011-11-02 01:32:202885 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102886 if (!framebuffer) {
[email protected]60f22d32012-12-12 00:31:582887 if (backbuffer_needs_clear_bits_) {
2888 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2889 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2890 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2891 glClearStencil(0);
2892 glStencilMask(-1);
2893 glClearDepth(1.0f);
2894 glDepthMask(true);
2895 glDisable(GL_SCISSOR_TEST);
2896 glClear(backbuffer_needs_clear_bits_);
2897 backbuffer_needs_clear_bits_ = 0;
2898 RestoreClearState();
2899 }
[email protected]0d6bfdc2011-11-02 01:32:202900 return true;
2901 }
2902
[email protected]968351b2011-12-20 08:26:512903 if (framebuffer_manager()->IsComplete(framebuffer)) {
2904 return true;
2905 }
2906
[email protected]0d6bfdc2011-11-02 01:32:202907 GLenum completeness = framebuffer->IsPossiblyComplete();
2908 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512909 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432910 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
[email protected]3a03a8f2011-03-19 00:51:272911 return false;
2912 }
[email protected]0d6bfdc2011-11-02 01:32:202913
2914 // Are all the attachments cleared?
2915 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2916 texture_manager()->HaveUnclearedMips()) {
2917 if (!framebuffer->IsCleared()) {
2918 // Can we clear them?
[email protected]73276522012-11-09 05:50:202919 if (framebuffer->GetStatus(texture_manager(), target) !=
2920 GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512921 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432922 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2923 "framebuffer incomplete (clear)");
[email protected]0d6bfdc2011-11-02 01:32:202924 return false;
2925 }
2926 ClearUnclearedAttachments(target, framebuffer);
2927 }
2928 }
2929
[email protected]968351b2011-12-20 08:26:512930 if (!framebuffer_manager()->IsComplete(framebuffer)) {
[email protected]73276522012-11-09 05:50:202931 if (framebuffer->GetStatus(texture_manager(), target) !=
2932 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,
2935 "framebuffer incomplete (check)");
[email protected]968351b2011-12-20 08:26:512936 return false;
2937 }
2938 framebuffer_manager()->MarkAsComplete(framebuffer);
2939 }
2940
[email protected]0d6bfdc2011-11-02 01:32:202941 // NOTE: At this point we don't know if the framebuffer is complete but
2942 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272943 return true;
2944}
2945
[email protected]0d6bfdc2011-11-02 01:32:202946bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
[email protected]62e155e2012-10-23 22:43:152947 if (!features().chromium_framebuffer_multisample) {
[email protected]28718a92013-04-04 12:12:512948 bool valid = CheckFramebufferValid(
[email protected]9d3b2e12013-10-02 01:04:342949 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
2950 func_name);
[email protected]28718a92013-04-04 12:12:512951
2952 if (valid)
2953 OnUseFramebuffer();
2954
2955 return valid;
[email protected]0d6bfdc2011-11-02 01:32:202956 }
[email protected]9d3b2e12013-10-02 01:04:342957 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
[email protected]7cd76fd2013-06-02 21:11:112958 GL_DRAW_FRAMEBUFFER_EXT,
2959 func_name) &&
[email protected]9d3b2e12013-10-02 01:04:342960 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
[email protected]7cd76fd2013-06-02 21:11:112961 GL_READ_FRAMEBUFFER_EXT,
2962 func_name);
[email protected]0d6bfdc2011-11-02 01:32:202963}
2964
[email protected]8e3e0662010-08-23 18:46:302965gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]ed9f9cd2013-02-27 21:12:352966 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452967 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202968 if (framebuffer != NULL) {
[email protected]ed9f9cd2013-02-27 21:12:352969 const Framebuffer::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202970 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262971 if (attachment) {
2972 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502973 }
[email protected]9edc6b22010-12-23 02:00:262974 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022975 } else if (offscreen_target_frame_buffer_.get()) {
2976 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352977 } else {
[email protected]f62a5ab2011-05-23 20:34:152978 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022979 }
[email protected]246a70452010-03-05 21:53:502980}
2981
[email protected]9edc6b22010-12-23 02:00:262982GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]ed9f9cd2013-02-27 21:12:352983 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452984 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202985 if (framebuffer != NULL) {
2986 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462987 } else if (offscreen_target_frame_buffer_.get()) {
2988 return offscreen_target_color_format_;
2989 } else {
2990 return back_buffer_color_format_;
2991 }
2992}
2993
2994GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]ed9f9cd2013-02-27 21:12:352995 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452996 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202997 if (framebuffer != NULL) {
2998 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262999 } else if (offscreen_target_frame_buffer_.get()) {
3000 return offscreen_target_color_format_;
3001 } else {
[email protected]32fe9aa2011-01-21 23:47:133002 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:263003 }
3004}
3005
[email protected]9a5afa432011-07-22 18:16:393006void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]2ad674132013-06-05 07:48:513007 if (!offscreen_saved_color_texture_info_.get())
3008 return;
3009 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3010 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3011 texture_manager()->SetLevelInfo(
3012 offscreen_saved_color_texture_info_.get(),
3013 GL_TEXTURE_2D,
3014 0, // level
3015 GL_RGBA,
3016 offscreen_size_.width(),
3017 offscreen_size_.height(),
3018 1, // depth
3019 0, // border
3020 GL_RGBA,
3021 GL_UNSIGNED_BYTE,
3022 true);
3023 texture_manager()->SetParameter(
3024 "UpdateParentTextureInfo",
3025 GetErrorState(),
3026 offscreen_saved_color_texture_info_.get(),
3027 GL_TEXTURE_MAG_FILTER,
3028 GL_NEAREST);
3029 texture_manager()->SetParameter(
3030 "UpdateParentTextureInfo",
3031 GetErrorState(),
3032 offscreen_saved_color_texture_info_.get(),
3033 GL_TEXTURE_MIN_FILTER,
3034 GL_NEAREST);
3035 texture_manager()->SetParameter(
3036 "UpdateParentTextureInfo",
3037 GetErrorState(),
3038 offscreen_saved_color_texture_info_.get(),
3039 GL_TEXTURE_WRAP_S,
3040 GL_CLAMP_TO_EDGE);
3041 texture_manager()->SetParameter(
3042 "UpdateParentTextureInfo",
3043 GetErrorState(),
3044 offscreen_saved_color_texture_info_.get(),
3045 GL_TEXTURE_WRAP_T,
3046 GL_CLAMP_TO_EDGE);
[email protected]c986af502013-08-14 01:04:443047 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3048 &state_, target);
[email protected]2ad674132013-06-05 07:48:513049 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
[email protected]6217d392010-03-25 22:08:353050}
3051
[email protected]799b4b22011-08-22 17:09:593052void GLES2DecoderImpl::SetResizeCallback(
[email protected]729c0b42013-05-26 02:05:073053 const base::Callback<void(gfx::Size, float)>& callback) {
[email protected]9d37f062011-11-22 01:24:523054 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:003055}
3056
[email protected]1d82e822013-04-10 21:32:323057Logger* GLES2DecoderImpl::GetLogger() {
3058 return &logger_;
[email protected]6b6e7ee2011-12-13 08:04:523059}
3060
[email protected]d3eba342013-04-18 21:11:503061ErrorState* GLES2DecoderImpl::GetErrorState() {
3062 return state_.GetErrorState();
3063}
3064
[email protected]e3932abb2013-03-13 00:01:373065void GLES2DecoderImpl::SetShaderCacheCallback(
3066 const ShaderCacheCallback& callback) {
3067 shader_cache_callback_ = callback;
3068}
3069
[email protected]840a7e462013-02-27 01:29:513070void GLES2DecoderImpl::SetWaitSyncPointCallback(
3071 const WaitSyncPointCallback& callback) {
3072 wait_sync_point_callback_ = callback;
3073}
3074
[email protected]85a4ac22013-05-31 01:58:473075AsyncPixelTransferManager*
3076 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3077 return async_pixel_transfer_manager_.get();
3078}
3079
3080void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3081 async_pixel_transfer_manager_.reset();
[email protected]32145a92012-12-17 09:01:593082}
3083
[email protected]498b5c072013-06-04 19:30:073084void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3085 AsyncPixelTransferManager* manager) {
3086 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3087}
3088
[email protected]1318e922010-09-17 22:03:163089bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3090 uint32* service_texture_id) {
[email protected]370eaf12013-05-18 09:19:493091 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3092 if (texture_ref) {
3093 *service_texture_id = texture_ref->service_id();
[email protected]1318e922010-09-17 22:03:163094 return true;
3095 }
3096 return false;
3097}
3098
[email protected]63b465922012-09-06 02:04:523099uint32 GLES2DecoderImpl::GetTextureUploadCount() {
[email protected]c986af502013-08-14 01:04:443100 return texture_state_.texture_upload_count +
[email protected]b68b100752013-06-05 08:34:483101 async_pixel_transfer_manager_->GetTextureUploadCount();
[email protected]63b465922012-09-06 02:04:523102}
3103
3104base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
[email protected]c986af502013-08-14 01:04:443105 return texture_state_.total_texture_upload_time +
[email protected]b68b100752013-06-05 08:34:483106 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
[email protected]63b465922012-09-06 02:04:523107}
3108
3109base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3110 return total_processing_commands_time_;
3111}
3112
[email protected]dc25dda2012-09-27 21:36:303113void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3114 total_processing_commands_time_ += time;
3115}
3116
[email protected]63c9b052012-05-17 18:27:383117void GLES2DecoderImpl::Destroy(bool have_context) {
[email protected]55e136f2013-04-03 18:50:063118 if (!initialized())
3119 return;
3120
[email protected]63c9b052012-05-17 18:27:383121 DCHECK(!have_context || context_->IsCurrent(NULL));
[email protected]97872062010-11-03 19:07:053122
[email protected]80eb6b52012-01-19 00:14:413123 // Unbind everything.
[email protected]e259eb412012-10-13 05:47:243124 state_.vertex_attrib_manager = NULL;
[email protected]944b62f32012-09-27 02:20:463125 default_vertex_attrib_manager_ = NULL;
[email protected]1868a342012-11-07 15:56:023126 state_.texture_units.clear();
[email protected]e259eb412012-10-13 05:47:243127 state_.bound_array_buffer = NULL;
3128 state_.current_query = NULL;
[email protected]9d3b2e12013-10-02 01:04:343129 framebuffer_state_.bound_read_framebuffer = NULL;
3130 framebuffer_state_.bound_draw_framebuffer = NULL;
[email protected]e259eb412012-10-13 05:47:243131 state_.bound_renderbuffer = NULL;
[email protected]80eb6b52012-01-19 00:14:413132
[email protected]cadac622013-06-11 16:46:363133 if (offscreen_saved_color_texture_info_.get()) {
[email protected]2ad674132013-06-05 07:48:513134 DCHECK(offscreen_target_color_texture_);
3135 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3136 offscreen_saved_color_texture_->id());
3137 offscreen_saved_color_texture_->Invalidate();
3138 offscreen_saved_color_texture_info_ = NULL;
3139 }
[email protected]eadc96792010-10-27 19:39:393140 if (have_context) {
[email protected]c322e882012-05-23 18:06:183141 if (copy_texture_CHROMIUM_.get()) {
3142 copy_texture_CHROMIUM_->Destroy();
3143 copy_texture_CHROMIUM_.reset();
3144 }
[email protected]43410e92012-04-20 17:06:283145
[email protected]7cd76fd2013-06-02 21:11:113146 if (state_.current_program.get()) {
3147 program_manager()->UnuseProgram(shader_manager(),
3148 state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:143149 }
3150
[email protected]b1122982010-05-17 23:04:243151 if (attrib_0_buffer_id_) {
3152 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3153 }
[email protected]8fbedc02010-11-18 18:43:403154 if (fixed_attrib_buffer_id_) {
3155 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3156 }
[email protected]b1122982010-05-17 23:04:243157
[email protected]4a4c18b2013-09-13 22:50:103158 if (validation_texture_) {
3159 glDeleteTextures(1, &validation_texture_);
3160 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3161 glDeleteFramebuffersEXT(1, &validation_fbo_);
3162 }
3163
[email protected]97872062010-11-03 19:07:053164 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:543165 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053166 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:543167 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:053168 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:023169 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053170 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:153171 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053172 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:153173 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053174 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:023175 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053176 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:543177 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:273178 if (offscreen_resolved_frame_buffer_.get())
3179 offscreen_resolved_frame_buffer_->Destroy();
3180 if (offscreen_resolved_color_texture_.get())
3181 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:053182 } else {
3183 if (offscreen_target_frame_buffer_.get())
3184 offscreen_target_frame_buffer_->Invalidate();
3185 if (offscreen_target_color_texture_.get())
3186 offscreen_target_color_texture_->Invalidate();
3187 if (offscreen_target_color_render_buffer_.get())
3188 offscreen_target_color_render_buffer_->Invalidate();
3189 if (offscreen_target_depth_render_buffer_.get())
3190 offscreen_target_depth_render_buffer_->Invalidate();
3191 if (offscreen_target_stencil_render_buffer_.get())
3192 offscreen_target_stencil_render_buffer_->Invalidate();
3193 if (offscreen_saved_frame_buffer_.get())
3194 offscreen_saved_frame_buffer_->Invalidate();
3195 if (offscreen_saved_color_texture_.get())
3196 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:273197 if (offscreen_resolved_frame_buffer_.get())
3198 offscreen_resolved_frame_buffer_->Invalidate();
3199 if (offscreen_resolved_color_texture_.get())
3200 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:023201 }
[email protected]83a52d032013-07-24 10:30:373202
3203 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3204 // Otherwise, we can leak objects. http://crbug.com/258772.
3205 // state_.current_program must be reset before group_ is reset because
3206 // the later deletes the ProgramManager object that referred by
3207 // state_.current_program object.
3208 state_.current_program = NULL;
3209
[email protected]43410e92012-04-20 17:06:283210 copy_texture_CHROMIUM_.reset();
[email protected]97872062010-11-03 19:07:053211
[email protected]882ba1e22012-03-08 19:02:533212 if (query_manager_.get()) {
3213 query_manager_->Destroy(have_context);
3214 query_manager_.reset();
3215 }
3216
[email protected]944b62f32012-09-27 02:20:463217 if (vertex_array_manager_ .get()) {
3218 vertex_array_manager_->Destroy(have_context);
3219 vertex_array_manager_.reset();
3220 }
3221
[email protected]97872062010-11-03 19:07:053222 offscreen_target_frame_buffer_.reset();
3223 offscreen_target_color_texture_.reset();
3224 offscreen_target_color_render_buffer_.reset();
3225 offscreen_target_depth_render_buffer_.reset();
3226 offscreen_target_stencil_render_buffer_.reset();
3227 offscreen_saved_frame_buffer_.reset();
3228 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:273229 offscreen_resolved_frame_buffer_.reset();
3230 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:463231
[email protected]85a4ac22013-05-31 01:58:473232 // Should destroy the transfer manager before the texture manager held
3233 // by the context group.
3234 async_pixel_transfer_manager_.reset();
3235
[email protected]91c94eb2013-10-22 10:32:543236 framebuffer_manager()->RemoveObserver(this);
3237
[email protected]7cd76fd2013-06-02 21:11:113238 if (group_.get()) {
[email protected]2d9d3b92013-01-18 01:07:233239 group_->Destroy(this, have_context);
3240 group_ = NULL;
3241 }
3242
3243 if (context_.get()) {
3244 context_->ReleaseCurrent(NULL);
3245 context_ = NULL;
3246 }
3247
[email protected]e51bdf32011-11-23 22:21:463248#if defined(OS_MACOSX)
3249 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3250 it != texture_to_io_surface_map_.end(); ++it) {
3251 CFRelease(it->second);
3252 }
3253 texture_to_io_surface_map_.clear();
3254#endif
[email protected]96449d2c2009-11-25 00:01:323255}
3256
[email protected]63c9b052012-05-17 18:27:383257void GLES2DecoderImpl::SetSurface(
3258 const scoped_refptr<gfx::GLSurface>& surface) {
3259 DCHECK(context_->IsCurrent(NULL));
3260 DCHECK(surface_.get());
3261 surface_ = surface;
3262 RestoreCurrentFramebufferBindings();
3263}
3264
[email protected]2ad674132013-06-05 07:48:513265bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
[email protected]9a5afa432011-07-22 18:16:393266 if (!offscreen_saved_color_texture_.get())
3267 return false;
[email protected]2ad674132013-06-05 07:48:513268 if (!offscreen_saved_color_texture_info_.get()) {
[email protected]3c644d82011-06-20 19:58:243269 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]f46476932013-06-08 05:36:073270 offscreen_saved_color_texture_info_ = TextureRef::Create(
3271 texture_manager(), 0, service_id);
[email protected]2ad674132013-06-05 07:48:513272 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3273 GL_TEXTURE_2D);
[email protected]9a5afa432011-07-22 18:16:393274 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:243275 }
[email protected]2ad674132013-06-05 07:48:513276 gpu::gles2::MailboxName name;
3277 memcpy(name.key, mailbox.name, sizeof(mailbox.name));
3278 return mailbox_manager()->ProduceTexture(
3279 GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture());
[email protected]3c644d82011-06-20 19:58:243280}
3281
[email protected]260ddc4e2012-06-28 00:01:533282size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() {
[email protected]1078f912011-12-23 13:12:143283 size_t total = 0;
3284 if (offscreen_target_frame_buffer_.get()) {
3285 if (offscreen_target_color_texture_.get()) {
3286 total += offscreen_target_color_texture_->estimated_size();
3287 }
3288 if (offscreen_target_color_render_buffer_.get()) {
3289 total += offscreen_target_color_render_buffer_->estimated_size();
3290 }
3291 if (offscreen_target_depth_render_buffer_.get()) {
3292 total += offscreen_target_depth_render_buffer_->estimated_size();
3293 }
3294 if (offscreen_target_stencil_render_buffer_.get()) {
3295 total += offscreen_target_stencil_render_buffer_->estimated_size();
3296 }
3297 if (offscreen_saved_color_texture_.get()) {
3298 total += offscreen_saved_color_texture_->estimated_size();
3299 }
3300 if (offscreen_resolved_color_texture_.get()) {
3301 total += offscreen_resolved_color_texture_->estimated_size();
3302 }
3303 } else {
3304 gfx::Size size = surface_->GetSize();
3305 total += size.width() * size.height() *
3306 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
3307 }
[email protected]260ddc4e2012-06-28 00:01:533308 return total;
[email protected]1078f912011-12-23 13:12:143309}
3310
[email protected]799b4b22011-08-22 17:09:593311bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3312 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3313 if (!is_offscreen) {
3314 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3315 << " with an onscreen framebuffer.";
3316 return false;
3317 }
3318
3319 if (offscreen_size_ == size)
3320 return true;
3321
3322 offscreen_size_ = size;
3323 int w = offscreen_size_.width();
3324 int h = offscreen_size_.height();
3325 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3326 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3327 << "to allocate storage due to excessive dimensions.";
3328 return false;
3329 }
3330
3331 // Reallocate the offscreen target buffers.
3332 DCHECK(offscreen_target_color_format_);
3333 if (IsOffscreenBufferMultisampled()) {
3334 if (!offscreen_target_color_render_buffer_->AllocateStorage(
[email protected]f42f05b2013-11-15 21:46:183335 feature_info_, offscreen_size_, offscreen_target_color_format_,
[email protected]799b4b22011-08-22 17:09:593336 offscreen_target_samples_)) {
3337 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3338 << "to allocate storage for offscreen target color buffer.";
3339 return false;
3340 }
3341 } else {
3342 if (!offscreen_target_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:093343 offscreen_size_, offscreen_target_color_format_, false)) {
[email protected]799b4b22011-08-22 17:09:593344 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3345 << "to allocate storage for offscreen target color texture.";
3346 return false;
3347 }
3348 }
3349 if (offscreen_target_depth_format_ &&
3350 !offscreen_target_depth_render_buffer_->AllocateStorage(
[email protected]f42f05b2013-11-15 21:46:183351 feature_info_, offscreen_size_, offscreen_target_depth_format_,
[email protected]799b4b22011-08-22 17:09:593352 offscreen_target_samples_)) {
3353 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3354 << "to allocate storage for offscreen target depth buffer.";
3355 return false;
3356 }
3357 if (offscreen_target_stencil_format_ &&
3358 !offscreen_target_stencil_render_buffer_->AllocateStorage(
[email protected]f42f05b2013-11-15 21:46:183359 feature_info_, offscreen_size_, offscreen_target_stencil_format_,
[email protected]799b4b22011-08-22 17:09:593360 offscreen_target_samples_)) {
3361 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3362 << "to allocate storage for offscreen target stencil buffer.";
3363 return false;
3364 }
3365
3366 // Attach the offscreen target buffers to the target frame buffer.
3367 if (IsOffscreenBufferMultisampled()) {
3368 offscreen_target_frame_buffer_->AttachRenderBuffer(
3369 GL_COLOR_ATTACHMENT0,
3370 offscreen_target_color_render_buffer_.get());
3371 } else {
3372 offscreen_target_frame_buffer_->AttachRenderTexture(
3373 offscreen_target_color_texture_.get());
3374 }
3375 if (offscreen_target_depth_format_) {
3376 offscreen_target_frame_buffer_->AttachRenderBuffer(
3377 GL_DEPTH_ATTACHMENT,
3378 offscreen_target_depth_render_buffer_.get());
3379 }
3380 const bool packed_depth_stencil =
3381 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3382 if (packed_depth_stencil) {
3383 offscreen_target_frame_buffer_->AttachRenderBuffer(
3384 GL_STENCIL_ATTACHMENT,
3385 offscreen_target_depth_render_buffer_.get());
3386 } else if (offscreen_target_stencil_format_) {
3387 offscreen_target_frame_buffer_->AttachRenderBuffer(
3388 GL_STENCIL_ATTACHMENT,
3389 offscreen_target_stencil_render_buffer_.get());
3390 }
3391
3392 if (offscreen_target_frame_buffer_->CheckStatus() !=
3393 GL_FRAMEBUFFER_COMPLETE) {
3394 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3395 << "because offscreen FBO was incomplete.";
3396 return false;
3397 }
3398
3399 // Clear the target frame buffer.
3400 {
3401 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3402 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3403 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3404 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3405 glClearStencil(0);
3406 glStencilMaskSeparate(GL_FRONT, -1);
3407 glStencilMaskSeparate(GL_BACK, -1);
3408 glClearDepth(0);
3409 glDepthMask(GL_TRUE);
3410 glDisable(GL_SCISSOR_TEST);
3411 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3412 RestoreClearState();
3413 }
[email protected]d85ef76d2011-09-08 22:21:433414
3415 // Destroy the offscreen resolved framebuffers.
3416 if (offscreen_resolved_frame_buffer_.get())
3417 offscreen_resolved_frame_buffer_->Destroy();
3418 if (offscreen_resolved_color_texture_.get())
3419 offscreen_resolved_color_texture_->Destroy();
3420 offscreen_resolved_color_texture_.reset();
3421 offscreen_resolved_frame_buffer_.reset();
3422
[email protected]799b4b22011-08-22 17:09:593423 return true;
[email protected]6217d392010-03-25 22:08:353424}
3425
[email protected]799b4b22011-08-22 17:09:593426error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:353427 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
[email protected]09e17272012-11-30 10:30:443428 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
[email protected]452120872012-09-27 15:21:023429 return error::kDeferCommandUntilLater;
3430
[email protected]799b4b22011-08-22 17:09:593431 GLuint width = static_cast<GLuint>(c.width);
3432 GLuint height = static_cast<GLuint>(c.height);
[email protected]729c0b42013-05-26 02:05:073433 GLfloat scale_factor = c.scale_factor;
[email protected]799b4b22011-08-22 17:09:593434 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]d16aa4b2013-02-14 22:35:413435
3436 width = std::max(1U, width);
3437 height = std::max(1U, height);
3438
[email protected]a0d989162011-11-22 13:15:073439#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3440 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003441 // Make sure that we are done drawing to the back buffer before resizing.
3442 glFinish();
3443#endif
[email protected]799b4b22011-08-22 17:09:593444 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3445 if (is_offscreen) {
[email protected]7794d512012-04-17 20:36:493446 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3447 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3448 << "ResizeOffscreenFrameBuffer failed.";
[email protected]799b4b22011-08-22 17:09:593449 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493450 }
[email protected]7ff86b92010-11-25 17:50:003451 }
[email protected]799b4b22011-08-22 17:09:593452
[email protected]9d37f062011-11-22 01:24:523453 if (!resize_callback_.is_null()) {
[email protected]729c0b42013-05-26 02:05:073454 resize_callback_.Run(gfx::Size(width, height), scale_factor);
[email protected]0e9346b2013-03-16 16:35:443455 DCHECK(context_->IsCurrent(surface_.get()));
[email protected]7794d512012-04-17 20:36:493456 if (!context_->IsCurrent(surface_.get())) {
3457 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3458 << "current after resize callback.";
[email protected]658f7562011-09-09 05:24:053459 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493460 }
[email protected]658f7562011-09-09 05:24:053461 }
[email protected]799b4b22011-08-22 17:09:593462
3463 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393464}
3465
[email protected]96449d2c2009-11-25 00:01:323466const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3467 if (command_id > kStartPoint && command_id < kNumCommands) {
3468 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3469 }
3470 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3471}
3472
3473// Decode command with its arguments, and call the corresponding GL function.
3474// Note: args is a pointer to the command buffer. As such, it could be changed
3475// by a (malicious) client at any time, so if validation has to happen, it
3476// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143477error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323478 unsigned int command,
3479 unsigned int arg_count,
3480 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143481 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263482 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003483 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3484 // LOG(INFO), tried VLOG(1), no luck.
[email protected]1d82e822013-04-10 21:32:323485 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
[email protected]d2a0e1a2012-08-12 02:25:013486 << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193487 }
[email protected]96449d2c2009-11-25 00:01:323488 unsigned int command_index = command - kStartPoint - 1;
3489 if (command_index < arraysize(g_command_info)) {
3490 const CommandInfo& info = g_command_info[command_index];
3491 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3492 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3493 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193494 uint32 immediate_data_size =
3495 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323496 switch (command) {
3497 #define GLES2_CMD_OP(name) \
[email protected]ed9f9cd2013-02-27 21:12:353498 case cmds::name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193499 result = Handle ## name( \
3500 immediate_data_size, \
[email protected]ed9f9cd2013-02-27 21:12:353501 *static_cast<const gles2::cmds::name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193502 break; \
[email protected]96449d2c2009-11-25 00:01:323503
3504 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323505 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383506 }
3507 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303508 GLenum error;
3509 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]1d82e822013-04-10 21:32:323510 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
[email protected]39ba4f02012-03-26 01:16:003511 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3512 << GetCommandName(command);
[email protected]ab09b612013-03-11 22:11:513513 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193514 }
[email protected]96449d2c2009-11-25 00:01:323515 }
3516 } else {
[email protected]f7a64ee2010-02-01 22:24:143517 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323518 }
[email protected]b9849abf2009-11-25 19:13:193519 } else {
3520 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323521 }
[email protected]a3a93e7b2010-08-28 00:48:563522 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3523 result = current_decoder_error_;
3524 current_decoder_error_ = error::kNoError;
3525 }
[email protected]b9849abf2009-11-25 19:13:193526 return result;
[email protected]96449d2c2009-11-25 00:01:323527}
3528
[email protected]ed9f9cd2013-02-27 21:12:353529void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3530 buffer_manager()->RemoveBuffer(client_id);
[email protected]3916c97e2010-02-25 03:20:503531}
3532
[email protected]ae51d192010-04-27 00:48:033533bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:353534 if (GetProgram(client_id)) {
[email protected]ae51d192010-04-27 00:48:033535 return false;
3536 }
[email protected]96449d2c2009-11-25 00:01:323537 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033538 if (service_id != 0) {
[email protected]ed9f9cd2013-02-27 21:12:353539 CreateProgram(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323540 }
[email protected]ae51d192010-04-27 00:48:033541 return true;
[email protected]96449d2c2009-11-25 00:01:323542}
3543
[email protected]ae51d192010-04-27 00:48:033544bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:353545 if (GetShader(client_id)) {
[email protected]ae51d192010-04-27 00:48:033546 return false;
[email protected]96449d2c2009-11-25 00:01:323547 }
[email protected]ae51d192010-04-27 00:48:033548 GLuint service_id = glCreateShader(type);
3549 if (service_id != 0) {
[email protected]ed9f9cd2013-02-27 21:12:353550 CreateShader(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033551 }
3552 return true;
[email protected]96449d2c2009-11-25 00:01:323553}
3554
[email protected]882ba1e22012-03-08 19:02:533555void GLES2DecoderImpl::DoFinish() {
3556 glFinish();
[email protected]5a36dc132013-07-23 23:17:553557 ProcessPendingReadPixels();
[email protected]22e3f552012-03-13 01:54:193558 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533559}
3560
3561void GLES2DecoderImpl::DoFlush() {
3562 glFlush();
[email protected]22e3f552012-03-13 01:54:193563 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533564}
3565
[email protected]3916c97e2010-02-25 03:20:503566void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453567 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]1868a342012-11-07 15:56:023568 if (texture_index >= state_.texture_units.size()) {
[email protected]ab09b612013-03-11 22:11:513569 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:533570 "glActiveTexture", texture_unit, "texture_unit");
[email protected]3916c97e2010-02-25 03:20:503571 return;
3572 }
[email protected]e259eb412012-10-13 05:47:243573 state_.active_texture_unit = texture_index;
[email protected]36cef8ce2010-03-16 07:34:453574 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503575}
3576
[email protected]051b1372010-04-12 02:42:083577void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]b10492f2013-03-08 05:24:073578 Buffer* buffer = NULL;
[email protected]051b1372010-04-12 02:42:083579 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033580 if (client_id != 0) {
[email protected]b10492f2013-03-08 05:24:073581 buffer = GetBuffer(client_id);
3582 if (!buffer) {
[email protected]bf5a8d132011-08-16 08:39:353583 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153584 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3585 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353586 return;
3587 }
3588
[email protected]b10492f2013-03-08 05:24:073589 // It's a new id so make a buffer buffer for it.
[email protected]ae51d192010-04-27 00:48:033590 glGenBuffersARB(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353591 CreateBuffer(client_id, service_id);
[email protected]b10492f2013-03-08 05:24:073592 buffer = GetBuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573593 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103594 group_->GetIdAllocator(id_namespaces::kBuffers);
3595 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033596 }
[email protected]051b1372010-04-12 02:42:083597 }
[email protected]b10492f2013-03-08 05:24:073598 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3599 if (buffer) {
3600 if (!buffer_manager()->SetTarget(buffer, target)) {
[email protected]ab09b612013-03-11 22:11:513601 LOCAL_SET_GL_ERROR(
3602 GL_INVALID_OPERATION,
3603 "glBindBuffer", "buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473604 return;
3605 }
[email protected]b10492f2013-03-08 05:24:073606 service_id = buffer->service_id();
[email protected]a93bb842010-02-16 23:03:473607 }
[email protected]96449d2c2009-11-25 00:01:323608 switch (target) {
3609 case GL_ARRAY_BUFFER:
[email protected]b10492f2013-03-08 05:24:073610 state_.bound_array_buffer = buffer;
[email protected]96449d2c2009-11-25 00:01:323611 break;
3612 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]b10492f2013-03-08 05:24:073613 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
[email protected]96449d2c2009-11-25 00:01:323614 break;
3615 default:
[email protected]a93bb842010-02-16 23:03:473616 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323617 break;
3618 }
[email protected]051b1372010-04-12 02:42:083619 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323620}
3621
[email protected]f3b191b2013-06-19 03:43:543622bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3623 bool all_draw_buffers) {
3624 Framebuffer* framebuffer =
3625 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3626 if (!all_draw_buffers || !framebuffer) {
3627 return (GLES2Util::GetChannelsForFormat(
3628 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3629 }
3630 return framebuffer->HasAlphaMRT();
[email protected]297ca1c2011-06-20 23:08:463631}
3632
3633bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]ed9f9cd2013-02-27 21:12:353634 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453635 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203636 if (framebuffer) {
3637 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463638 }
3639 if (offscreen_target_frame_buffer_.get()) {
3640 return offscreen_target_depth_format_ != 0;
3641 }
3642 return back_buffer_has_depth_;
3643}
3644
3645bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]ed9f9cd2013-02-27 21:12:353646 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453647 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203648 if (framebuffer) {
3649 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463650 }
3651 if (offscreen_target_frame_buffer_.get()) {
3652 return offscreen_target_stencil_format_ != 0 ||
3653 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3654 }
3655 return back_buffer_has_stencil_;
3656}
3657
3658void GLES2DecoderImpl::ApplyDirtyState() {
[email protected]c986af502013-08-14 01:04:443659 if (framebuffer_state_.clear_state_dirty) {
[email protected]297ca1c2011-06-20 23:08:463660 glColorMask(
[email protected]e259eb412012-10-13 05:47:243661 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3662 state_.color_mask_alpha &&
[email protected]f3b191b2013-06-19 03:43:543663 BoundFramebufferHasColorAttachmentWithAlpha(true));
[email protected]297ca1c2011-06-20 23:08:463664 bool have_depth = BoundFramebufferHasDepthAttachment();
[email protected]e259eb412012-10-13 05:47:243665 glDepthMask(state_.depth_mask && have_depth);
[email protected]f731b9462012-10-30 00:35:223666 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
[email protected]297ca1c2011-06-20 23:08:463667 bool have_stencil = BoundFramebufferHasStencilAttachment();
[email protected]e259eb412012-10-13 05:47:243668 glStencilMaskSeparate(
[email protected]88a61bf2012-10-27 13:00:423669 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
[email protected]e259eb412012-10-13 05:47:243670 glStencilMaskSeparate(
[email protected]88a61bf2012-10-27 13:00:423671 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
[email protected]f731b9462012-10-30 00:35:223672 EnableDisable(
3673 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3674 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3675 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3676 EnableDisable(GL_BLEND, state_.enable_flags.blend);
[email protected]c986af502013-08-14 01:04:443677 framebuffer_state_.clear_state_dirty = false;
[email protected]297ca1c2011-06-20 23:08:463678 }
3679}
3680
[email protected]1868a342012-11-07 15:56:023681GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
[email protected]7cd76fd2013-06-02 21:11:113682 return (offscreen_target_frame_buffer_.get())
3683 ? offscreen_target_frame_buffer_->id()
3684 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
[email protected]1868a342012-11-07 15:56:023685}
3686
3687void GLES2DecoderImpl::RestoreState() const {
[email protected]962bfbe72013-05-24 11:16:143688 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3689 "context", logger_.GetLogPrefix());
[email protected]29a4d902013-02-26 20:18:063690 // Restore the Framebuffer first because of bugs in Intel drivers.
3691 // Intel drivers incorrectly clip the viewport settings to
3692 // the size of the current framebuffer object.
3693 RestoreFramebufferBindings();
3694 state_.RestoreState();
3695}
3696
3697void GLES2DecoderImpl::RestoreFramebufferBindings() const {
[email protected]9d3b2e12013-10-02 01:04:343698 GLuint service_id =
3699 framebuffer_state_.bound_draw_framebuffer.get()
3700 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3701 : GetBackbufferServiceId();
[email protected]29a4d902013-02-26 20:18:063702 if (!features().chromium_framebuffer_multisample) {
3703 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3704 } else {
3705 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
[email protected]9d3b2e12013-10-02 01:04:343706 service_id = framebuffer_state_.bound_read_framebuffer.get()
3707 ? framebuffer_state_.bound_read_framebuffer->service_id()
[email protected]7cd76fd2013-06-02 21:11:113708 : GetBackbufferServiceId();
[email protected]29a4d902013-02-26 20:18:063709 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3710 }
[email protected]70d34263c2013-01-09 00:27:453711 OnFboChanged();
[email protected]29a4d902013-02-26 20:18:063712}
3713
3714void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
[email protected]62e65f02013-05-29 22:28:103715 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3716 if (texture) {
[email protected]9bc9a2e82013-04-03 03:56:253717 GLenum target = texture->target();
3718 glBindTexture(target, service_id);
[email protected]29a4d902013-02-26 20:18:063719 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253720 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
[email protected]29a4d902013-02-26 20:18:063721 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253722 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
[email protected]29a4d902013-02-26 20:18:063723 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253724 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
[email protected]29a4d902013-02-26 20:18:063725 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253726 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
[email protected]29a4d902013-02-26 20:18:063727 RestoreTextureUnitBindings(state_.active_texture_unit);
3728 }
[email protected]70d34263c2013-01-09 00:27:453729}
3730
3731void GLES2DecoderImpl::OnFboChanged() const {
3732 if (workarounds().restore_scissor_on_fbo_change)
[email protected]28718a92013-04-04 12:12:513733 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3734}
3735
3736// Called after the FBO is checked for completeness.
3737void GLES2DecoderImpl::OnUseFramebuffer() const {
3738 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3739 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
[email protected]81fc9d02013-03-14 23:53:323740 // The driver forgets the correct scissor when modifying the FBO binding.
[email protected]28718a92013-04-04 12:12:513741 glScissor(state_.scissor_x,
3742 state_.scissor_y,
3743 state_.scissor_width,
3744 state_.scissor_height);
3745
3746 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3747 // it's unclear how this bug works.
3748 glFlush();
3749 }
[email protected]b177ae22011-11-01 03:29:113750}
3751
[email protected]051b1372010-04-12 02:42:083752void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
[email protected]4d8f0dd2013-03-09 14:37:063753 Framebuffer* framebuffer = NULL;
[email protected]051b1372010-04-12 02:42:083754 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033755 if (client_id != 0) {
[email protected]4d8f0dd2013-03-09 14:37:063756 framebuffer = GetFramebuffer(client_id);
3757 if (!framebuffer) {
[email protected]bf5a8d132011-08-16 08:39:353758 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153759 LOG(ERROR)
3760 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3761 current_decoder_error_ = error::kGenericError;
3762 return;
[email protected]bf5a8d132011-08-16 08:39:353763 }
3764
[email protected]4d8f0dd2013-03-09 14:37:063765 // It's a new id so make a framebuffer framebuffer for it.
[email protected]ae51d192010-04-27 00:48:033766 glGenFramebuffersEXT(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353767 CreateFramebuffer(client_id, service_id);
[email protected]4d8f0dd2013-03-09 14:37:063768 framebuffer = GetFramebuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573769 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103770 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3771 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033772 } else {
[email protected]4d8f0dd2013-03-09 14:37:063773 service_id = framebuffer->service_id();
[email protected]051b1372010-04-12 02:42:083774 }
[email protected]4d8f0dd2013-03-09 14:37:063775 framebuffer->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083776 }
[email protected]4d8f0dd2013-03-09 14:37:063777 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
[email protected]8e3e0662010-08-23 18:46:303778
3779 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
[email protected]9d3b2e12013-10-02 01:04:343780 framebuffer_state_.bound_draw_framebuffer = framebuffer;
[email protected]8e3e0662010-08-23 18:46:303781 }
3782 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]9d3b2e12013-10-02 01:04:343783 framebuffer_state_.bound_read_framebuffer = framebuffer;
[email protected]8e3e0662010-08-23 18:46:303784 }
[email protected]6217d392010-03-25 22:08:353785
[email protected]c986af502013-08-14 01:04:443786 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:463787
[email protected]b177ae22011-11-01 03:29:113788 // If we are rendering to the backbuffer get the FBO id for any simulated
3789 // backbuffer.
[email protected]4d8f0dd2013-03-09 14:37:063790 if (framebuffer == NULL) {
[email protected]b177ae22011-11-01 03:29:113791 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463792 }
[email protected]6217d392010-03-25 22:08:353793
[email protected]051b1372010-04-12 02:42:083794 glBindFramebufferEXT(target, service_id);
[email protected]70d34263c2013-01-09 00:27:453795 OnFboChanged();
[email protected]86093972010-03-11 00:13:563796}
3797
[email protected]051b1372010-04-12 02:42:083798void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
[email protected]ee2a79c32013-03-10 03:50:273799 Renderbuffer* renderbuffer = NULL;
[email protected]051b1372010-04-12 02:42:083800 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033801 if (client_id != 0) {
[email protected]ee2a79c32013-03-10 03:50:273802 renderbuffer = GetRenderbuffer(client_id);
3803 if (!renderbuffer) {
[email protected]bf5a8d132011-08-16 08:39:353804 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153805 LOG(ERROR)
3806 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3807 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353808 return;
3809 }
3810
[email protected]ee2a79c32013-03-10 03:50:273811 // It's a new id so make a renderbuffer renderbuffer for it.
[email protected]ae51d192010-04-27 00:48:033812 glGenRenderbuffersEXT(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353813 CreateRenderbuffer(client_id, service_id);
[email protected]ee2a79c32013-03-10 03:50:273814 renderbuffer = GetRenderbuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573815 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103816 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3817 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033818 } else {
[email protected]ee2a79c32013-03-10 03:50:273819 service_id = renderbuffer->service_id();
[email protected]051b1372010-04-12 02:42:083820 }
[email protected]ee2a79c32013-03-10 03:50:273821 renderbuffer->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083822 }
[email protected]ee2a79c32013-03-10 03:50:273823 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer");
3824 state_.bound_renderbuffer = renderbuffer;
[email protected]051b1372010-04-12 02:42:083825 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563826}
3827
[email protected]051b1372010-04-12 02:42:083828void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]370eaf12013-05-18 09:19:493829 TextureRef* texture_ref = NULL;
[email protected]051b1372010-04-12 02:42:083830 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033831 if (client_id != 0) {
[email protected]370eaf12013-05-18 09:19:493832 texture_ref = GetTexture(client_id);
3833 if (!texture_ref) {
[email protected]bf5a8d132011-08-16 08:39:353834 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153835 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3836 current_decoder_error_ = error::kGenericError;
3837 return;
[email protected]bf5a8d132011-08-16 08:39:353838 }
3839
[email protected]02965c22013-03-09 02:40:073840 // It's a new id so make a texture texture for it.
[email protected]ae51d192010-04-27 00:48:033841 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413842 DCHECK_NE(0u, service_id);
[email protected]ed9f9cd2013-02-27 21:12:353843 CreateTexture(client_id, service_id);
[email protected]370eaf12013-05-18 09:19:493844 texture_ref = GetTexture(client_id);
[email protected]3b1ecc262011-08-03 22:49:573845 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103846 group_->GetIdAllocator(id_namespaces::kTextures);
3847 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033848 }
3849 } else {
[email protected]370eaf12013-05-18 09:19:493850 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083851 }
[email protected]370eaf12013-05-18 09:19:493852 Texture* texture = texture_ref->texture();
[email protected]ae51d192010-04-27 00:48:033853
[email protected]1958e0e2010-04-22 05:17:153854 // Check the texture exists
3855 // Check that we are not trying to bind it to a different target.
[email protected]02965c22013-03-09 02:40:073856 if (texture->target() != 0 && texture->target() != target) {
[email protected]ab09b612013-03-11 22:11:513857 LOCAL_SET_GL_ERROR(
3858 GL_INVALID_OPERATION,
3859 "glBindTexture", "texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153860 return;
3861 }
[email protected]02965c22013-03-09 02:40:073862 if (texture->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
[email protected]ab09b612013-03-11 22:11:513863 LOCAL_SET_GL_ERROR(
3864 GL_INVALID_OPERATION,
3865 "glBindTexture", "illegal target for stream texture.");
[email protected]b0af4f52011-09-28 22:04:423866 return;
3867 }
[email protected]02965c22013-03-09 02:40:073868 LogClientServiceForInfo(texture, client_id, "glBindTexture");
3869 if (texture->target() == 0) {
[email protected]370eaf12013-05-18 09:19:493870 texture_manager()->SetTarget(texture_ref, target);
[email protected]a93bb842010-02-16 23:03:473871 }
[email protected]02965c22013-03-09 02:40:073872 glBindTexture(target, texture->service_id());
[email protected]32145a92012-12-17 09:01:593873
[email protected]e259eb412012-10-13 05:47:243874 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]3916c97e2010-02-25 03:20:503875 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473876 switch (target) {
3877 case GL_TEXTURE_2D:
[email protected]370eaf12013-05-18 09:19:493878 unit.bound_texture_2d = texture_ref;
[email protected]a93bb842010-02-16 23:03:473879 break;
3880 case GL_TEXTURE_CUBE_MAP:
[email protected]370eaf12013-05-18 09:19:493881 unit.bound_texture_cube_map = texture_ref;
[email protected]a93bb842010-02-16 23:03:473882 break;
[email protected]61eeb33f2011-07-26 15:30:313883 case GL_TEXTURE_EXTERNAL_OES:
[email protected]370eaf12013-05-18 09:19:493884 unit.bound_texture_external_oes = texture_ref;
[email protected]61eeb33f2011-07-26 15:30:313885 break;
[email protected]e51bdf32011-11-23 22:21:463886 case GL_TEXTURE_RECTANGLE_ARB:
[email protected]370eaf12013-05-18 09:19:493887 unit.bound_texture_rectangle_arb = texture_ref;
[email protected]e51bdf32011-11-23 22:21:463888 break;
[email protected]a93bb842010-02-16 23:03:473889 default:
3890 NOTREACHED(); // Validation should prevent us getting here.
3891 break;
3892 }
3893}
3894
[email protected]07f54fcc2009-12-22 02:46:303895void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]e259eb412012-10-13 05:47:243896 if (state_.vertex_attrib_manager->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123897 if (index != 0 ||
3898 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243899 glDisableVertexAttribArray(index);
3900 }
[email protected]07f54fcc2009-12-22 02:46:303901 } else {
[email protected]ab09b612013-03-11 22:11:513902 LOCAL_SET_GL_ERROR(
3903 GL_INVALID_VALUE,
3904 "glDisableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303905 }
3906}
3907
[email protected]60f22d32012-12-12 00:31:583908void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
3909 GLsizei numAttachments,
3910 const GLenum* attachments) {
[email protected]680aa412013-10-31 18:08:013911 if (!features().ext_discard_framebuffer) {
3912 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3913 "glDiscardFramebufferEXT",
3914 "function not available");
3915 return;
3916 }
3917
[email protected]ed9f9cd2013-02-27 21:12:353918 Framebuffer* framebuffer =
[email protected]60f22d32012-12-12 00:31:583919 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
3920
3921 // Validates the attachments. If one of them fails
3922 // the whole command fails.
3923 for (GLsizei i = 0; i < numAttachments; ++i) {
3924 if ((framebuffer &&
3925 !validators_->attachment.IsValid(attachments[i])) ||
3926 (!framebuffer &&
3927 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
[email protected]ab09b612013-03-11 22:11:513928 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3929 "glDiscardFramebufferEXT", attachments[i], "attachments");
[email protected]60f22d32012-12-12 00:31:583930 return;
3931 }
3932 }
3933
3934 // Marks each one of them as not cleared
3935 for (GLsizei i = 0; i < numAttachments; ++i) {
3936 if (framebuffer) {
3937 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
3938 texture_manager(),
3939 attachments[i],
3940 false);
3941 } else {
3942 switch (attachments[i]) {
3943 case GL_COLOR_EXT:
3944 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
3945 break;
3946 case GL_DEPTH_EXT:
3947 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
3948 case GL_STENCIL_EXT:
3949 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
3950 break;
3951 default:
3952 NOTREACHED();
3953 break;
3954 }
3955 }
3956 }
3957
[email protected]d49c5402013-09-11 15:39:023958 // If the default framebuffer is bound but we are still rendering to an
3959 // FBO, translate attachment names that refer to default framebuffer
3960 // channels to corresponding framebuffer attachments.
3961 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
3962 for (GLsizei i = 0; i < numAttachments; ++i) {
3963 GLenum attachment = attachments[i];
3964 if (!framebuffer && GetBackbufferServiceId()) {
3965 switch (attachment) {
3966 case GL_COLOR_EXT:
3967 attachment = GL_COLOR_ATTACHMENT0;
3968 break;
3969 case GL_DEPTH_EXT:
3970 attachment = GL_DEPTH_ATTACHMENT;
3971 break;
3972 case GL_STENCIL_EXT:
3973 attachment = GL_STENCIL_ATTACHMENT;
3974 break;
3975 default:
3976 NOTREACHED();
3977 return;
3978 }
3979 }
3980 translated_attachments[i] = attachment;
3981 }
3982
3983 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
[email protected]60f22d32012-12-12 00:31:583984}
3985
[email protected]07f54fcc2009-12-22 02:46:303986void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]e259eb412012-10-13 05:47:243987 if (state_.vertex_attrib_manager->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303988 glEnableVertexAttribArray(index);
3989 } else {
[email protected]ab09b612013-03-11 22:11:513990 LOCAL_SET_GL_ERROR(
3991 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303992 }
3993}
3994
[email protected]a93bb842010-02-16 23:03:473995void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]c986af502013-08-14 01:04:443996 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3997 &state_, target);
[email protected]370eaf12013-05-18 09:19:493998 if (!texture_ref ||
3999 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:514000 LOCAL_SET_GL_ERROR(
4001 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
[email protected]a93bb842010-02-16 23:03:474002 return;
4003 }
[email protected]38c0a972012-05-12 00:48:024004
[email protected]12d95352012-12-14 07:23:544005 if (target == GL_TEXTURE_CUBE_MAP) {
4006 for (int i = 0; i < 6; ++i) {
4007 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
[email protected]370eaf12013-05-18 09:19:494008 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
[email protected]ab09b612013-03-11 22:11:514009 LOCAL_SET_GL_ERROR(
4010 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
[email protected]12d95352012-12-14 07:23:544011 return;
4012 }
4013 }
4014 } else {
[email protected]370eaf12013-05-18 09:19:494015 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
[email protected]ab09b612013-03-11 22:11:514016 LOCAL_SET_GL_ERROR(
4017 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
[email protected]12d95352012-12-14 07:23:544018 return;
4019 }
[email protected]7687479c2012-05-14 23:54:044020 }
4021
[email protected]ab09b612013-03-11 22:11:514022 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
[email protected]59f3ca02011-03-26 22:24:194023 // Workaround for Mac driver bug. In the large scheme of things setting
4024 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:564025 // hit so there's probably no need to make this conditional. The bug appears
4026 // to be that if the filtering mode is set to something that doesn't require
4027 // mipmaps for rendering, or is never set to something other than the default,
4028 // then glGenerateMipmap misbehaves.
[email protected]62e155e2012-10-23 22:43:154029 if (workarounds().set_texture_filter_before_generating_mipmap) {
[email protected]c892a4e12012-05-08 18:20:194030 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4031 }
[email protected]a93bb842010-02-16 23:03:474032 glGenerateMipmapEXT(target);
[email protected]62e155e2012-10-23 22:43:154033 if (workarounds().set_texture_filter_before_generating_mipmap) {
[email protected]370eaf12013-05-18 09:19:494034 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4035 texture_ref->texture()->min_filter());
[email protected]c892a4e12012-05-08 18:20:194036 }
[email protected]ab09b612013-03-11 22:11:514037 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
[email protected]38c0a972012-05-12 00:48:024038 if (error == GL_NO_ERROR) {
[email protected]370eaf12013-05-18 09:19:494039 texture_manager()->MarkMipmapsGenerated(texture_ref);
[email protected]38c0a972012-05-12 00:48:024040 }
[email protected]a93bb842010-02-16 23:03:474041}
4042
[email protected]b273e432010-04-12 17:23:584043bool GLES2DecoderImpl::GetHelper(
4044 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:584045 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:154046 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4047 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:434048 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4049 *num_written = 1;
4050 if (params) {
4051 *params = GL_RGBA; // We don't support other formats.
4052 }
4053 return true;
4054 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4055 *num_written = 1;
4056 if (params) {
4057 *params = GL_UNSIGNED_BYTE; // We don't support other types.
4058 }
4059 return true;
4060 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4061 *num_written = 1;
4062 if (params) {
4063 *params = group_->max_fragment_uniform_vectors();
4064 }
4065 return true;
4066 case GL_MAX_VARYING_VECTORS:
4067 *num_written = 1;
4068 if (params) {
4069 *params = group_->max_varying_vectors();
4070 }
4071 return true;
4072 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4073 *num_written = 1;
4074 if (params) {
4075 *params = group_->max_vertex_uniform_vectors();
4076 }
4077 return true;
[email protected]4e8a5b122010-05-08 22:00:104078 }
[email protected]5cb735d2011-10-13 01:37:234079 }
4080 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:244081 case GL_MAX_VIEWPORT_DIMS:
4082 if (offscreen_target_frame_buffer_.get()) {
4083 *num_written = 2;
4084 if (params) {
4085 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4086 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4087 }
4088 return true;
4089 }
[email protected]5cb735d2011-10-13 01:37:234090 return false;
[email protected]84afefa2011-10-19 21:45:534091 case GL_MAX_SAMPLES:
4092 *num_written = 1;
4093 if (params) {
4094 params[0] = renderbuffer_manager()->max_samples();
4095 }
4096 return true;
4097 case GL_MAX_RENDERBUFFER_SIZE:
4098 *num_written = 1;
4099 if (params) {
4100 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4101 }
4102 return true;
[email protected]5cb735d2011-10-13 01:37:234103 case GL_MAX_TEXTURE_SIZE:
4104 *num_written = 1;
4105 if (params) {
4106 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4107 }
4108 return true;
4109 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4110 *num_written = 1;
4111 if (params) {
4112 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4113 }
4114 return true;
[email protected]2f143d482013-03-14 18:04:494115 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4116 *num_written = 1;
4117 if (params) {
4118 params[0] = group_->max_color_attachments();
4119 }
4120 return true;
4121 case GL_MAX_DRAW_BUFFERS_ARB:
4122 *num_written = 1;
4123 if (params) {
4124 params[0] = group_->max_draw_buffers();
4125 }
4126 return true;
[email protected]297ca1c2011-06-20 23:08:464127 case GL_ALPHA_BITS:
4128 *num_written = 1;
4129 if (params) {
4130 GLint v = 0;
4131 glGetIntegerv(GL_ALPHA_BITS, &v);
[email protected]f3b191b2013-06-19 03:43:544132 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
[email protected]297ca1c2011-06-20 23:08:464133 }
4134 return true;
4135 case GL_DEPTH_BITS:
4136 *num_written = 1;
4137 if (params) {
4138 GLint v = 0;
4139 glGetIntegerv(GL_DEPTH_BITS, &v);
4140 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4141 }
4142 return true;
4143 case GL_STENCIL_BITS:
4144 *num_written = 1;
4145 if (params) {
4146 GLint v = 0;
4147 glGetIntegerv(GL_STENCIL_BITS, &v);
4148 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4149 }
4150 return true;
[email protected]656dcaad2010-05-07 17:18:374151 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:114152 *num_written = validators_->compressed_texture_format.GetValues().size();
4153 if (params) {
4154 for (GLint ii = 0; ii < *num_written; ++ii) {
4155 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4156 }
4157 }
[email protected]656dcaad2010-05-07 17:18:374158 return true;
[email protected]b273e432010-04-12 17:23:584159 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4160 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104161 if (params) {
[email protected]302ce6d2011-07-07 23:28:114162 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:104163 }
[email protected]b273e432010-04-12 17:23:584164 return true;
4165 case GL_NUM_SHADER_BINARY_FORMATS:
4166 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104167 if (params) {
[email protected]302ce6d2011-07-07 23:28:114168 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:104169 }
[email protected]b273e432010-04-12 17:23:584170 return true;
4171 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:114172 *num_written = validators_->shader_binary_format.GetValues().size();
4173 if (params) {
4174 for (GLint ii = 0; ii < *num_written; ++ii) {
4175 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4176 }
4177 }
4178 return true;
[email protected]b273e432010-04-12 17:23:584179 case GL_SHADER_COMPILER:
4180 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104181 if (params) {
4182 *params = GL_TRUE;
4183 }
[email protected]b273e432010-04-12 17:23:584184 return true;
[email protected]6b8cf1a2010-05-06 16:13:584185 case GL_ARRAY_BUFFER_BINDING:
4186 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104187 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114188 if (state_.bound_array_buffer.get()) {
[email protected]4e8a5b122010-05-08 22:00:104189 GLuint client_id = 0;
[email protected]e259eb412012-10-13 05:47:244190 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
[email protected]4e8a5b122010-05-08 22:00:104191 &client_id);
4192 *params = client_id;
4193 } else {
4194 *params = 0;
4195 }
[email protected]6b8cf1a2010-05-06 16:13:584196 }
4197 return true;
4198 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4199 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104200 if (params) {
[email protected]e259eb412012-10-13 05:47:244201 if (state_.vertex_attrib_manager->element_array_buffer()) {
[email protected]4e8a5b122010-05-08 22:00:104202 GLuint client_id = 0;
4203 buffer_manager()->GetClientId(
[email protected]b04e24c2013-01-08 18:35:254204 state_.vertex_attrib_manager->element_array_buffer()->
4205 service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104206 *params = client_id;
4207 } else {
4208 *params = 0;
4209 }
[email protected]6b8cf1a2010-05-06 16:13:584210 }
4211 return true;
4212 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:304213 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:584214 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104215 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354216 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:454217 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
[email protected]0d6bfdc2011-11-02 01:32:204218 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:104219 GLuint client_id = 0;
4220 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:204221 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:304222 *params = client_id;
4223 } else {
4224 *params = 0;
4225 }
4226 }
4227 return true;
[email protected]ebfb73c2012-08-15 02:37:454228 case GL_READ_FRAMEBUFFER_BINDING_EXT:
[email protected]8e3e0662010-08-23 18:46:304229 *num_written = 1;
4230 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354231 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:454232 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:204233 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:304234 GLuint client_id = 0;
4235 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:204236 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104237 *params = client_id;
4238 } else {
4239 *params = 0;
4240 }
[email protected]6b8cf1a2010-05-06 16:13:584241 }
4242 return true;
4243 case GL_RENDERBUFFER_BINDING:
4244 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104245 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354246 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:204247 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4248 if (renderbuffer) {
[email protected]62e65f02013-05-29 22:28:104249 *params = renderbuffer->client_id();
[email protected]4e8a5b122010-05-08 22:00:104250 } else {
4251 *params = 0;
4252 }
[email protected]6b8cf1a2010-05-06 16:13:584253 }
4254 return true;
4255 case GL_CURRENT_PROGRAM:
4256 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104257 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114258 if (state_.current_program.get()) {
[email protected]4e8a5b122010-05-08 22:00:104259 GLuint client_id = 0;
4260 program_manager()->GetClientId(
[email protected]e259eb412012-10-13 05:47:244261 state_.current_program->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104262 *params = client_id;
4263 } else {
4264 *params = 0;
4265 }
[email protected]6b8cf1a2010-05-06 16:13:584266 }
4267 return true;
[email protected]bf835842012-11-19 15:21:514268 case GL_VERTEX_ARRAY_BINDING_OES:
4269 *num_written = 1;
4270 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114271 if (state_.vertex_attrib_manager.get() !=
4272 default_vertex_attrib_manager_.get()) {
[email protected]bf835842012-11-19 15:21:514273 GLuint client_id = 0;
4274 vertex_array_manager_->GetClientId(
4275 state_.vertex_attrib_manager->service_id(), &client_id);
4276 *params = client_id;
4277 } else {
4278 *params = 0;
4279 }
4280 }
4281 return true;
[email protected]4e8a5b122010-05-08 22:00:104282 case GL_TEXTURE_BINDING_2D:
4283 *num_written = 1;
4284 if (params) {
[email protected]e259eb412012-10-13 05:47:244285 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114286 if (unit.bound_texture_2d.get()) {
[email protected]62e65f02013-05-29 22:28:104287 *params = unit.bound_texture_2d->client_id();
[email protected]6b8cf1a2010-05-06 16:13:584288 } else {
4289 *params = 0;
4290 }
[email protected]6b8cf1a2010-05-06 16:13:584291 }
[email protected]4e8a5b122010-05-08 22:00:104292 return true;
4293 case GL_TEXTURE_BINDING_CUBE_MAP:
4294 *num_written = 1;
4295 if (params) {
[email protected]e259eb412012-10-13 05:47:244296 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114297 if (unit.bound_texture_cube_map.get()) {
[email protected]62e65f02013-05-29 22:28:104298 *params = unit.bound_texture_cube_map->client_id();
[email protected]6b8cf1a2010-05-06 16:13:584299 } else {
4300 *params = 0;
4301 }
[email protected]6b8cf1a2010-05-06 16:13:584302 }
[email protected]4e8a5b122010-05-08 22:00:104303 return true;
[email protected]61eeb33f2011-07-26 15:30:314304 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4305 *num_written = 1;
4306 if (params) {
[email protected]e259eb412012-10-13 05:47:244307 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114308 if (unit.bound_texture_external_oes.get()) {
[email protected]62e65f02013-05-29 22:28:104309 *params = unit.bound_texture_external_oes->client_id();
[email protected]61eeb33f2011-07-26 15:30:314310 } else {
4311 *params = 0;
4312 }
4313 }
4314 return true;
[email protected]e51bdf32011-11-23 22:21:464315 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4316 *num_written = 1;
4317 if (params) {
[email protected]e259eb412012-10-13 05:47:244318 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114319 if (unit.bound_texture_rectangle_arb.get()) {
[email protected]62e65f02013-05-29 22:28:104320 *params = unit.bound_texture_rectangle_arb->client_id();
[email protected]e51bdf32011-11-23 22:21:464321 } else {
4322 *params = 0;
4323 }
4324 }
4325 return true;
[email protected]6c75c712012-06-19 15:43:174326 case GL_UNPACK_FLIP_Y_CHROMIUM:
4327 *num_written = 1;
4328 if (params) {
4329 params[0] = unpack_flip_y_;
4330 }
4331 return true;
4332 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4333 *num_written = 1;
4334 if (params) {
4335 params[0] = unpack_premultiply_alpha_;
4336 }
4337 return true;
4338 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4339 *num_written = 1;
4340 if (params) {
4341 params[0] = unpack_unpremultiply_alpha_;
4342 }
4343 return true;
[email protected]b273e432010-04-12 17:23:584344 default:
[email protected]2f143d482013-03-14 18:04:494345 if (pname >= GL_DRAW_BUFFER0_ARB &&
4346 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4347 *num_written = 1;
4348 if (params) {
4349 Framebuffer* framebuffer =
4350 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4351 if (framebuffer) {
4352 params[0] = framebuffer->GetDrawBuffer(pname);
4353 } else { // backbuffer
4354 if (pname == GL_DRAW_BUFFER0_ARB)
4355 params[0] = group_->draw_buffer();
4356 else
4357 params[0] = GL_NONE;
4358 }
4359 }
4360 return true;
4361 }
[email protected]4e8a5b122010-05-08 22:00:104362 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:534363 return false;
[email protected]b273e432010-04-12 17:23:584364 }
4365}
4366
[email protected]4e8a5b122010-05-08 22:00:104367bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4368 GLenum pname, GLsizei* num_values) {
[email protected]d058bca2012-11-26 10:27:264369 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
[email protected]f63b1232012-10-31 07:03:534370 return true;
4371 }
[email protected]4e8a5b122010-05-08 22:00:104372 return GetHelper(pname, NULL, num_values);
4373}
4374
[email protected]7d3c36e2013-07-12 14:13:164375GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4376 if (GL_MAX_SAMPLES == pname &&
4377 features().use_img_for_multisampled_render_to_texture) {
4378 return GL_MAX_SAMPLES_IMG;
4379 }
4380 return pname;
4381}
4382
[email protected]b273e432010-04-12 17:23:584383void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4384 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:104385 GLsizei num_written = 0;
[email protected]f63b1232012-10-31 07:03:534386 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
[email protected]40d90a22013-04-09 03:39:554387 scoped_ptr<GLint[]> values(new GLint[num_written]);
[email protected]d058bca2012-11-26 10:27:264388 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
[email protected]f63b1232012-10-31 07:03:534389 GetHelper(pname, values.get(), &num_written);
4390 }
[email protected]b273e432010-04-12 17:23:584391 for (GLsizei ii = 0; ii < num_written; ++ii) {
4392 params[ii] = static_cast<GLboolean>(values[ii]);
4393 }
4394 } else {
[email protected]7d3c36e2013-07-12 14:13:164395 pname = AdjustGetPname(pname);
[email protected]b273e432010-04-12 17:23:584396 glGetBooleanv(pname, params);
4397 }
4398}
4399
4400void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4401 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:104402 GLsizei num_written = 0;
[email protected]d058bca2012-11-26 10:27:264403 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
[email protected]f63b1232012-10-31 07:03:534404 if (GetHelper(pname, NULL, &num_written)) {
[email protected]40d90a22013-04-09 03:39:554405 scoped_ptr<GLint[]> values(new GLint[num_written]);
[email protected]f63b1232012-10-31 07:03:534406 GetHelper(pname, values.get(), &num_written);
4407 for (GLsizei ii = 0; ii < num_written; ++ii) {
4408 params[ii] = static_cast<GLfloat>(values[ii]);
4409 }
4410 } else {
[email protected]7d3c36e2013-07-12 14:13:164411 pname = AdjustGetPname(pname);
[email protected]f63b1232012-10-31 07:03:534412 glGetFloatv(pname, params);
[email protected]b273e432010-04-12 17:23:584413 }
[email protected]b273e432010-04-12 17:23:584414 }
4415}
4416
4417void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4418 DCHECK(params);
4419 GLsizei num_written;
[email protected]d058bca2012-11-26 10:27:264420 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
[email protected]f63b1232012-10-31 07:03:534421 !GetHelper(pname, params, &num_written)) {
[email protected]7d3c36e2013-07-12 14:13:164422 pname = AdjustGetPname(pname);
[email protected]b273e432010-04-12 17:23:584423 glGetIntegerv(pname, params);
4424 }
4425}
4426
[email protected]a0c3e972010-04-21 00:49:134427void GLES2DecoderImpl::DoGetProgramiv(
4428 GLuint program_id, GLenum pname, GLint* params) {
[email protected]df37b9932013-03-08 05:21:424429 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4430 if (!program) {
[email protected]a0c3e972010-04-21 00:49:134431 return;
4432 }
[email protected]df37b9932013-03-08 05:21:424433 program->GetProgramiv(pname, params);
[email protected]a0c3e972010-04-21 00:49:134434}
4435
[email protected]17cfbe0e2013-03-07 01:26:084436void GLES2DecoderImpl::DoGetBufferParameteriv(
4437 GLenum target, GLenum pname, GLint* params) {
[email protected]0fbba3732013-07-17 15:40:134438 // Just delegate it. Some validation is actually done before this.
4439 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4440 &state_, target, pname, params);
[email protected]17cfbe0e2013-03-07 01:26:084441}
4442
[email protected]258a3313f2011-10-18 20:13:574443void GLES2DecoderImpl::DoBindAttribLocation(
[email protected]df37b9932013-03-08 05:21:424444 GLuint program_id, GLuint index, const char* name) {
[email protected]258a3313f2011-10-18 20:13:574445 if (!StringIsValidForGLES(name)) {
[email protected]ab09b612013-03-11 22:11:514446 LOCAL_SET_GL_ERROR(
4447 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:574448 return;
4449 }
[email protected]68dcb1f2012-04-07 00:14:564450 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ab09b612013-03-11 22:11:514451 LOCAL_SET_GL_ERROR(
4452 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
[email protected]68dcb1f2012-04-07 00:14:564453 return;
4454 }
4455 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:514456 LOCAL_SET_GL_ERROR(
4457 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
[email protected]68dcb1f2012-04-07 00:14:564458 return;
4459 }
[email protected]df37b9932013-03-08 05:21:424460 Program* program = GetProgramInfoNotShader(
4461 program_id, "glBindAttribLocation");
4462 if (!program) {
[email protected]258a3313f2011-10-18 20:13:574463 return;
[email protected]558847a2010-03-24 07:02:544464 }
[email protected]df37b9932013-03-08 05:21:424465 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4466 glBindAttribLocation(program->service_id(), index, name);
[email protected]258a3313f2011-10-18 20:13:574467}
4468
4469error::Error GLES2DecoderImpl::HandleBindAttribLocation(
[email protected]ed9f9cd2013-02-27 21:12:354470 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
[email protected]258a3313f2011-10-18 20:13:574471 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544472 GLuint index = static_cast<GLuint>(c.index);
4473 uint32 name_size = c.data_size;
4474 const char* name = GetSharedMemoryAs<const char*>(
4475 c.name_shm_id, c.name_shm_offset, name_size);
4476 if (name == NULL) {
4477 return error::kOutOfBounds;
4478 }
4479 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:574480 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544481 return error::kNoError;
4482}
4483
[email protected]558847a2010-03-24 07:02:544484error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:354485 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:584486 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544487 GLuint index = static_cast<GLuint>(c.index);
4488 Bucket* bucket = GetBucket(c.name_bucket_id);
4489 if (!bucket || bucket->size() == 0) {
4490 return error::kInvalidArguments;
4491 }
4492 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184493 if (!bucket->GetAsString(&name_str)) {
4494 return error::kInvalidArguments;
4495 }
[email protected]258a3313f2011-10-18 20:13:574496 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544497 return error::kNoError;
4498}
4499
[email protected]2be6abf32012-06-26 00:28:334500void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
[email protected]df37b9932013-03-08 05:21:424501 GLuint program_id, GLint location, const char* name) {
[email protected]2be6abf32012-06-26 00:28:334502 if (!StringIsValidForGLES(name)) {
[email protected]ab09b612013-03-11 22:11:514503 LOCAL_SET_GL_ERROR(
4504 GL_INVALID_VALUE,
4505 "glBindUniformLocationCHROMIUM", "Invalid character");
[email protected]2be6abf32012-06-26 00:28:334506 return;
4507 }
4508 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ab09b612013-03-11 22:11:514509 LOCAL_SET_GL_ERROR(
4510 GL_INVALID_OPERATION,
4511 "glBindUniformLocationCHROMIUM", "reserved prefix");
[email protected]2be6abf32012-06-26 00:28:334512 return;
4513 }
4514 if (location < 0 || static_cast<uint32>(location) >=
4515 (group_->max_fragment_uniform_vectors() +
4516 group_->max_vertex_uniform_vectors()) * 4) {
[email protected]ab09b612013-03-11 22:11:514517 LOCAL_SET_GL_ERROR(
4518 GL_INVALID_VALUE,
4519 "glBindUniformLocationCHROMIUM", "location out of range");
[email protected]2be6abf32012-06-26 00:28:334520 return;
4521 }
[email protected]df37b9932013-03-08 05:21:424522 Program* program = GetProgramInfoNotShader(
4523 program_id, "glBindUniformLocationCHROMIUM");
4524 if (!program) {
[email protected]2be6abf32012-06-26 00:28:334525 return;
4526 }
[email protected]df37b9932013-03-08 05:21:424527 if (!program->SetUniformLocationBinding(name, location)) {
[email protected]ab09b612013-03-11 22:11:514528 LOCAL_SET_GL_ERROR(
4529 GL_INVALID_VALUE,
4530 "glBindUniformLocationCHROMIUM", "location out of range");
[email protected]2be6abf32012-06-26 00:28:334531 }
4532}
4533
4534error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354535 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
[email protected]2be6abf32012-06-26 00:28:334536 GLuint program = static_cast<GLuint>(c.program);
4537 GLint location = static_cast<GLint>(c.location);
4538 uint32 name_size = c.data_size;
4539 const char* name = GetSharedMemoryAs<const char*>(
4540 c.name_shm_id, c.name_shm_offset, name_size);
4541 if (name == NULL) {
4542 return error::kOutOfBounds;
4543 }
4544 String name_str(name, name_size);
4545 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4546 return error::kNoError;
4547}
4548
[email protected]2be6abf32012-06-26 00:28:334549error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4550 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:354551 const cmds::BindUniformLocationCHROMIUMBucket& c) {
[email protected]2be6abf32012-06-26 00:28:334552 GLuint program = static_cast<GLuint>(c.program);
4553 GLint location = static_cast<GLint>(c.location);
4554 Bucket* bucket = GetBucket(c.name_bucket_id);
4555 if (!bucket || bucket->size() == 0) {
4556 return error::kInvalidArguments;
4557 }
4558 std::string name_str;
4559 if (!bucket->GetAsString(&name_str)) {
4560 return error::kInvalidArguments;
4561 }
4562 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4563 return error::kNoError;
4564}
4565
[email protected]f7a64ee2010-02-01 22:24:144566error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ed9f9cd2013-02-27 21:12:354567 uint32 immediate_data_size, const cmds::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:034568 GLuint client_id = c.shader;
4569 if (client_id) {
[email protected]df37b9932013-03-08 05:21:424570 Shader* shader = GetShader(client_id);
4571 if (shader) {
4572 if (!shader->IsDeleted()) {
4573 glDeleteShader(shader->service_id());
4574 shader_manager()->MarkAsDeleted(shader);
[email protected]ca488e12010-12-13 20:06:144575 }
[email protected]ae51d192010-04-27 00:48:034576 } else {
[email protected]ab09b612013-03-11 22:11:514577 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
[email protected]ae51d192010-04-27 00:48:034578 }
[email protected]96449d2c2009-11-25 00:01:324579 }
[email protected]f7a64ee2010-02-01 22:24:144580 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324581}
4582
[email protected]f7a64ee2010-02-01 22:24:144583error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ed9f9cd2013-02-27 21:12:354584 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:034585 GLuint client_id = c.program;
4586 if (client_id) {
[email protected]df37b9932013-03-08 05:21:424587 Program* program = GetProgram(client_id);
4588 if (program) {
4589 if (!program->IsDeleted()) {
4590 program_manager()->MarkAsDeleted(shader_manager(), program);
[email protected]ca488e12010-12-13 20:06:144591 }
[email protected]ae51d192010-04-27 00:48:034592 } else {
[email protected]ab09b612013-03-11 22:11:514593 LOCAL_SET_GL_ERROR(
4594 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
[email protected]ae51d192010-04-27 00:48:034595 }
[email protected]96449d2c2009-11-25 00:01:324596 }
[email protected]f7a64ee2010-02-01 22:24:144597 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324598}
4599
[email protected]269200b12010-11-18 22:53:064600void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104601 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574602 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104603 for (GLsizei ii = 0; ii < n; ++ii) {
4604 id_allocator->FreeID(ids[ii]);
4605 }
4606}
4607
[email protected]269200b12010-11-18 22:53:064608error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354609 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104610 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4611 GLsizei n = static_cast<GLsizei>(c.n);
4612 uint32 data_size;
4613 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4614 return error::kOutOfBounds;
4615 }
4616 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4617 c.ids_shm_id, c.ids_shm_offset, data_size);
4618 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514619 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104620 return error::kNoError;
4621 }
4622 if (ids == NULL) {
4623 return error::kOutOfBounds;
4624 }
[email protected]269200b12010-11-18 22:53:064625 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104626 return error::kNoError;
4627}
4628
[email protected]269200b12010-11-18 22:53:064629void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104630 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574631 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104632 if (id_offset == 0) {
4633 for (GLsizei ii = 0; ii < n; ++ii) {
4634 ids[ii] = id_allocator->AllocateID();
4635 }
4636 } else {
4637 for (GLsizei ii = 0; ii < n; ++ii) {
4638 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4639 id_offset = ids[ii] + 1;
4640 }
4641 }
4642}
4643
[email protected]269200b12010-11-18 22:53:064644error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354645 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104646 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4647 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4648 GLsizei n = static_cast<GLsizei>(c.n);
4649 uint32 data_size;
4650 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4651 return error::kOutOfBounds;
4652 }
4653 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4654 c.ids_shm_id, c.ids_shm_offset, data_size);
4655 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514656 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104657 return error::kNoError;
4658 }
4659 if (ids == NULL) {
4660 return error::kOutOfBounds;
4661 }
[email protected]269200b12010-11-18 22:53:064662 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:104663 return error::kNoError;
4664}
4665
[email protected]269200b12010-11-18 22:53:064666void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104667 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574668 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104669 for (GLsizei ii = 0; ii < n; ++ii) {
4670 if (!id_allocator->MarkAsUsed(ids[ii])) {
4671 for (GLsizei jj = 0; jj < ii; ++jj) {
4672 id_allocator->FreeID(ids[jj]);
4673 }
[email protected]ab09b612013-03-11 22:11:514674 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:434675 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4676 "attempt to register id that already exists");
[email protected]066849e32010-05-03 19:14:104677 return;
4678 }
4679 }
4680}
4681
[email protected]269200b12010-11-18 22:53:064682error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354683 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104684 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4685 GLsizei n = static_cast<GLsizei>(c.n);
4686 uint32 data_size;
4687 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4688 return error::kOutOfBounds;
4689 }
4690 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4691 c.ids_shm_id, c.ids_shm_offset, data_size);
4692 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514693 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104694 return error::kNoError;
4695 }
4696 if (ids == NULL) {
4697 return error::kOutOfBounds;
4698 }
[email protected]269200b12010-11-18 22:53:064699 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104700 return error::kNoError;
4701}
4702
[email protected]a7266a92012-06-28 02:11:084703error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]09e17272012-11-30 10:30:444704 DCHECK(!ShouldDeferDraws());
[email protected]0d6bfdc2011-11-02 01:32:204705 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]297ca1c2011-06-20 23:08:464706 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:274707 glClear(mask);
4708 }
[email protected]a7266a92012-06-28 02:11:084709 return error::kNoError;
4710}
4711
[email protected]36cef8ce2010-03-16 07:34:454712void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4713 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034714 GLuint client_renderbuffer_id) {
[email protected]4d8f0dd2013-03-09 14:37:064715 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4716 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514717 LOCAL_SET_GL_ERROR(
4718 GL_INVALID_OPERATION,
4719 "glFramebufferRenderbuffer", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454720 return;
4721 }
[email protected]ae51d192010-04-27 00:48:034722 GLuint service_id = 0;
[email protected]ee2a79c32013-03-10 03:50:274723 Renderbuffer* renderbuffer = NULL;
[email protected]ae51d192010-04-27 00:48:034724 if (client_renderbuffer_id) {
[email protected]ee2a79c32013-03-10 03:50:274725 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4726 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:514727 LOCAL_SET_GL_ERROR(
4728 GL_INVALID_OPERATION,
4729 "glFramebufferRenderbuffer", "unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034730 return;
4731 }
[email protected]ee2a79c32013-03-10 03:50:274732 service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:034733 }
[email protected]ab09b612013-03-11 22:11:514734 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
[email protected]ae51d192010-04-27 00:48:034735 glFramebufferRenderbufferEXT(
4736 target, attachment, renderbuffertarget, service_id);
[email protected]ab09b612013-03-11 22:11:514737 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
[email protected]9edc6b22010-12-23 02:00:264738 if (error == GL_NO_ERROR) {
[email protected]ee2a79c32013-03-10 03:50:274739 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
[email protected]3a2e7c7b2010-08-06 01:12:284740 }
[email protected]9d3b2e12013-10-02 01:04:344741 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
[email protected]c986af502013-08-14 01:04:444742 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:464743 }
[email protected]81fc9d02013-03-14 23:53:324744 OnFboChanged();
[email protected]3a2e7c7b2010-08-06 01:12:284745}
4746
[email protected]3a2e7c7b2010-08-06 01:12:284747void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464748 if (SetCapabilityState(cap, false)) {
4749 glDisable(cap);
4750 }
[email protected]3a2e7c7b2010-08-06 01:12:284751}
4752
4753void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464754 if (SetCapabilityState(cap, true)) {
4755 glEnable(cap);
4756 }
[email protected]3a2e7c7b2010-08-06 01:12:284757}
4758
[email protected]88a61bf2012-10-27 13:00:424759void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4760 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4761 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4762 glDepthRange(znear, zfar);
[email protected]3a2e7c7b2010-08-06 01:12:284763}
4764
[email protected]b04e24c2013-01-08 18:35:254765void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
[email protected]88a61bf2012-10-27 13:00:424766 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4767 state_.sample_coverage_invert = (invert != 0);
4768 glSampleCoverage(state_.sample_coverage_value, invert);
[email protected]3a2e7c7b2010-08-06 01:12:284769}
4770
[email protected]0d6bfdc2011-11-02 01:32:204771// Assumes framebuffer is complete.
4772void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]4d8f0dd2013-03-09 14:37:064773 GLenum target, Framebuffer* framebuffer) {
[email protected]8e3e0662010-08-23 18:46:304774 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204775 // bind this to the DRAW point, clear then bind back to READ
4776 // TODO(gman): I don't think there is any guarantee that an FBO that
4777 // is complete on the READ attachment will be complete as a DRAW
4778 // attachment.
4779 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
[email protected]4d8f0dd2013-03-09 14:37:064780 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
[email protected]8e3e0662010-08-23 18:46:304781 }
[email protected]3a2e7c7b2010-08-06 01:12:284782 GLbitfield clear_bits = 0;
[email protected]4d8f0dd2013-03-09 14:37:064783 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464784 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204785 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464786 (GLES2Util::GetChannelsForFormat(
[email protected]4d8f0dd2013-03-09 14:37:064787 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4788 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284789 glColorMask(true, true, true, true);
4790 clear_bits |= GL_COLOR_BUFFER_BIT;
4791 }
4792
[email protected]4d8f0dd2013-03-09 14:37:064793 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4794 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
[email protected]3a2e7c7b2010-08-06 01:12:284795 glClearStencil(0);
4796 glStencilMask(-1);
4797 clear_bits |= GL_STENCIL_BUFFER_BIT;
4798 }
4799
[email protected]4d8f0dd2013-03-09 14:37:064800 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4801 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
[email protected]3a2e7c7b2010-08-06 01:12:284802 glClearDepth(1.0f);
4803 glDepthMask(true);
4804 clear_bits |= GL_DEPTH_BUFFER_BIT;
4805 }
4806
4807 glDisable(GL_SCISSOR_TEST);
4808 glClear(clear_bits);
4809
[email protected]968351b2011-12-20 08:26:514810 framebuffer_manager()->MarkAttachmentsAsCleared(
[email protected]4d8f0dd2013-03-09 14:37:064811 framebuffer, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284812
[email protected]c007aa02010-09-02 22:22:404813 RestoreClearState();
4814
4815 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]4d8f0dd2013-03-09 14:37:064816 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4817 Framebuffer* draw_framebuffer =
[email protected]87d1a3fe2011-12-01 04:25:484818 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]4d8f0dd2013-03-09 14:37:064819 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4820 GetBackbufferServiceId();
[email protected]87d1a3fe2011-12-01 04:25:484821 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404822 }
4823}
4824
4825void GLES2DecoderImpl::RestoreClearState() {
[email protected]c986af502013-08-14 01:04:444826 framebuffer_state_.clear_state_dirty = true;
[email protected]e259eb412012-10-13 05:47:244827 glClearColor(
4828 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4829 state_.color_clear_alpha);
4830 glClearStencil(state_.stencil_clear);
4831 glClearDepth(state_.depth_clear);
[email protected]f731b9462012-10-30 00:35:224832 if (state_.enable_flags.scissor_test) {
[email protected]3a2e7c7b2010-08-06 01:12:284833 glEnable(GL_SCISSOR_TEST);
4834 }
[email protected]36cef8ce2010-03-16 07:34:454835}
4836
4837GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]ed9f9cd2013-02-27 21:12:354838 Framebuffer* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304839 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204840 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454841 return GL_FRAMEBUFFER_COMPLETE;
4842 }
[email protected]0d6bfdc2011-11-02 01:32:204843 GLenum completeness = framebuffer->IsPossiblyComplete();
4844 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4845 return completeness;
4846 }
[email protected]73276522012-11-09 05:50:204847 return framebuffer->GetStatus(texture_manager(), target);
[email protected]36cef8ce2010-03-16 07:34:454848}
4849
4850void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034851 GLenum target, GLenum attachment, GLenum textarget,
4852 GLuint client_texture_id, GLint level) {
[email protected]7d3c36e2013-07-12 14:13:164853 DoFramebufferTexture2DCommon(
4854 "glFramebufferTexture2D", target, attachment,
4855 textarget, client_texture_id, level, 0);
4856}
4857
4858void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
4859 GLenum target, GLenum attachment, GLenum textarget,
4860 GLuint client_texture_id, GLint level, GLsizei samples) {
4861 if (!features().multisampled_render_to_texture) {
4862 LOCAL_SET_GL_ERROR(
4863 GL_INVALID_OPERATION,
4864 "glFramebufferTexture2DMultisample", "function not available");
4865 return;
4866 }
4867 DoFramebufferTexture2DCommon(
4868 "glFramebufferTexture2DMultisample", target, attachment,
4869 textarget, client_texture_id, level, samples);
4870}
4871
4872void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
4873 const char* name, GLenum target, GLenum attachment, GLenum textarget,
4874 GLuint client_texture_id, GLint level, GLsizei samples) {
4875 if (samples > renderbuffer_manager()->max_samples()) {
4876 LOCAL_SET_GL_ERROR(
4877 GL_INVALID_VALUE,
4878 "glFramebufferTexture2DMultisample", "samples too large");
4879 return;
4880 }
[email protected]4d8f0dd2013-03-09 14:37:064881 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4882 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514883 LOCAL_SET_GL_ERROR(
4884 GL_INVALID_OPERATION,
[email protected]7d3c36e2013-07-12 14:13:164885 name, "no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454886 return;
4887 }
[email protected]ae51d192010-04-27 00:48:034888 GLuint service_id = 0;
[email protected]370eaf12013-05-18 09:19:494889 TextureRef* texture_ref = NULL;
[email protected]ae51d192010-04-27 00:48:034890 if (client_texture_id) {
[email protected]370eaf12013-05-18 09:19:494891 texture_ref = GetTexture(client_texture_id);
4892 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:514893 LOCAL_SET_GL_ERROR(
4894 GL_INVALID_OPERATION,
[email protected]7d3c36e2013-07-12 14:13:164895 name, "unknown texture_ref");
[email protected]ae51d192010-04-27 00:48:034896 return;
4897 }
[email protected]370eaf12013-05-18 09:19:494898 service_id = texture_ref->service_id();
[email protected]ae51d192010-04-27 00:48:034899 }
[email protected]0d6bfdc2011-11-02 01:32:204900
[email protected]80eb6b52012-01-19 00:14:414901 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]ab09b612013-03-11 22:11:514902 LOCAL_SET_GL_ERROR(
4903 GL_INVALID_VALUE,
[email protected]7d3c36e2013-07-12 14:13:164904 name, "level out of range");
[email protected]0d6bfdc2011-11-02 01:32:204905 return;
4906 }
4907
[email protected]91c94eb2013-10-22 10:32:544908 if (texture_ref)
4909 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
4910
[email protected]7d3c36e2013-07-12 14:13:164911 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
4912 if (0 == samples) {
4913 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
4914 } else {
4915 if (features().use_img_for_multisampled_render_to_texture) {
4916 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
4917 service_id, level, samples);
4918 } else {
4919 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
4920 service_id, level, samples);
4921 }
4922 }
4923 GLenum error = LOCAL_PEEK_GL_ERROR(name);
[email protected]9edc6b22010-12-23 02:00:264924 if (error == GL_NO_ERROR) {
[email protected]7d3c36e2013-07-12 14:13:164925 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
4926 samples);
[email protected]3a2e7c7b2010-08-06 01:12:284927 }
[email protected]9d3b2e12013-10-02 01:04:344928 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
[email protected]c986af502013-08-14 01:04:444929 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:464930 }
[email protected]91c94eb2013-10-22 10:32:544931
4932 if (texture_ref)
4933 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
4934
[email protected]81fc9d02013-03-14 23:53:324935 OnFboChanged();
[email protected]36cef8ce2010-03-16 07:34:454936}
4937
4938void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4939 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]4d8f0dd2013-03-09 14:37:064940 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4941 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514942 LOCAL_SET_GL_ERROR(
4943 GL_INVALID_OPERATION,
4944 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454945 return;
4946 }
[email protected]74c1ec42010-08-12 01:55:574947 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
[email protected]62e65f02013-05-29 22:28:104948 const Framebuffer::Attachment* attachment_object =
4949 framebuffer->GetAttachment(attachment);
4950 *params = attachment_object ? attachment_object->object_name() : 0;
4951 } else {
[email protected]7d3c36e2013-07-12 14:13:164952 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
4953 features().use_img_for_multisampled_render_to_texture) {
4954 pname = GL_TEXTURE_SAMPLES_IMG;
4955 }
[email protected]62e65f02013-05-29 22:28:104956 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574957 }
[email protected]36cef8ce2010-03-16 07:34:454958}
4959
4960void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4961 GLenum target, GLenum pname, GLint* params) {
[email protected]ed9f9cd2013-02-27 21:12:354962 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:204963 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4964 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:514965 LOCAL_SET_GL_ERROR(
4966 GL_INVALID_OPERATION,
4967 "glGetRenderbufferParameteriv", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454968 return;
4969 }
[email protected]3a03a8f2011-03-19 00:51:274970 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:434971 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4972 *params = renderbuffer->internal_format();
4973 break;
4974 case GL_RENDERBUFFER_WIDTH:
4975 *params = renderbuffer->width();
4976 break;
4977 case GL_RENDERBUFFER_HEIGHT:
4978 *params = renderbuffer->height();
4979 break;
[email protected]7d3c36e2013-07-12 14:13:164980 case GL_RENDERBUFFER_SAMPLES_EXT:
4981 if (features().use_img_for_multisampled_render_to_texture) {
4982 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
4983 params);
4984 } else {
4985 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
4986 params);
4987 }
[email protected]ad84a3a2012-06-08 21:42:434988 default:
4989 glGetRenderbufferParameterivEXT(target, pname, params);
4990 break;
[email protected]b71f52c2010-06-18 22:20:204991 }
[email protected]36cef8ce2010-03-16 07:34:454992}
4993
[email protected]49cabed2013-11-13 18:15:184994void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
[email protected]8e3e0662010-08-23 18:46:304995 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4996 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4997 GLbitfield mask, GLenum filter) {
[email protected]09e17272012-11-30 10:30:444998 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
[email protected]62e155e2012-10-23 22:43:154999 if (!features().chromium_framebuffer_multisample) {
[email protected]ab09b612013-03-11 22:11:515000 LOCAL_SET_GL_ERROR(
5001 GL_INVALID_OPERATION,
[email protected]49cabed2013-11-13 18:15:185002 "glBlitFramebufferCHROMIUM", "function not available");
[email protected]680aa412013-10-31 18:08:015003 return;
[email protected]8e3e0662010-08-23 18:46:305004 }
[email protected]0c16343f2013-03-08 20:40:165005
[email protected]49cabed2013-11-13 18:15:185006 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
[email protected]0c16343f2013-03-08 20:40:165007 return;
5008 }
5009
[email protected]d058bca2012-11-26 10:27:265010 glDisable(GL_SCISSOR_TEST);
[email protected]f42f05b2013-11-15 21:46:185011 BlitFramebufferHelper(
5012 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5013 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
5014}
5015
5016void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5017 const FeatureInfo* feature_info,
5018 GLenum target,
5019 GLsizei samples,
5020 GLenum internal_format,
5021 GLsizei width,
5022 GLsizei height) {
5023 // TODO(sievers): This could be resolved at the GL binding level, but the
5024 // binding process is currently a bit too 'brute force'.
5025 if (feature_info->feature_flags().is_angle) {
5026 glRenderbufferStorageMultisampleANGLE(
5027 target, samples, internal_format, width, height);
5028 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5029 glRenderbufferStorageMultisample(
5030 target, samples, internal_format, width, height);
5031 } else {
5032 glRenderbufferStorageMultisampleEXT(
5033 target, samples, internal_format, width, height);
5034 }
5035}
5036
5037void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5038 GLint srcY0,
5039 GLint srcX1,
5040 GLint srcY1,
5041 GLint dstX0,
5042 GLint dstY0,
5043 GLint dstX1,
5044 GLint dstY1,
5045 GLbitfield mask,
5046 GLenum filter) {
5047 // TODO(sievers): This could be resolved at the GL binding level, but the
5048 // binding process is currently a bit too 'brute force'.
5049 if (feature_info_->feature_flags().is_angle) {
[email protected]5094b0f2010-11-09 19:45:245050 glBlitFramebufferANGLE(
5051 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
[email protected]f42f05b2013-11-15 21:46:185052 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5053 glBlitFramebuffer(
5054 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
[email protected]5094b0f2010-11-09 19:45:245055 } else {
5056 glBlitFramebufferEXT(
5057 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5058 }
[email protected]8e3e0662010-08-23 18:46:305059}
5060
[email protected]49cabed2013-11-13 18:15:185061bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5062 GLsizei samples,
5063 GLenum internalformat,
5064 GLsizei width,
5065 GLsizei height) {
[email protected]84afefa2011-10-19 21:45:535066 if (samples > renderbuffer_manager()->max_samples()) {
[email protected]ab09b612013-03-11 22:11:515067 LOCAL_SET_GL_ERROR(
5068 GL_INVALID_VALUE,
5069 "glRenderbufferStorageMultisample", "samples too large");
[email protected]49cabed2013-11-13 18:15:185070 return false;
[email protected]84afefa2011-10-19 21:45:535071 }
5072
5073 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5074 height > renderbuffer_manager()->max_renderbuffer_size()) {
[email protected]ab09b612013-03-11 22:11:515075 LOCAL_SET_GL_ERROR(
5076 GL_INVALID_VALUE,
5077 "glRenderbufferStorageMultisample", "dimensions too large");
[email protected]49cabed2013-11-13 18:15:185078 return false;
[email protected]84afefa2011-10-19 21:45:535079 }
5080
[email protected]7989c9e2013-01-23 06:39:265081 uint32 estimated_size = 0;
[email protected]8e102e102013-09-20 22:50:235082 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5083 width, height, samples, internalformat, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515084 LOCAL_SET_GL_ERROR(
5085 GL_OUT_OF_MEMORY,
5086 "glRenderbufferStorageMultsample", "dimensions too large");
[email protected]49cabed2013-11-13 18:15:185087 return false;
[email protected]8e3e0662010-08-23 18:46:305088 }
5089
[email protected]7989c9e2013-01-23 06:39:265090 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515091 LOCAL_SET_GL_ERROR(
5092 GL_OUT_OF_MEMORY,
5093 "glRenderbufferStorageMultsample", "out of memory");
[email protected]49cabed2013-11-13 18:15:185094 return false;
5095 }
5096
5097 return true;
5098}
5099
5100void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5101 GLenum target, GLsizei samples, GLenum internalformat,
5102 GLsizei width, GLsizei height) {
5103 if (!features().chromium_framebuffer_multisample) {
5104 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5105 "glRenderbufferStorageMultisampleCHROMIUM",
5106 "function not available");
5107 return;
5108 }
5109
5110 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5111 if (!renderbuffer) {
5112 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5113 "glRenderbufferStorageMultisampleCHROMIUM",
5114 "no renderbuffer bound");
5115 return;
5116 }
5117
5118 if (!ValidateRenderbufferStorageMultisample(
5119 samples, internalformat, width, height)) {
[email protected]7989c9e2013-01-23 06:39:265120 return;
5121 }
5122
[email protected]8e102e102013-09-20 22:50:235123 GLenum impl_format =
5124 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5125 internalformat);
[email protected]49cabed2013-11-13 18:15:185126 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5127 "glRenderbufferStorageMultisampleCHROMIUM");
[email protected]f42f05b2013-11-15 21:46:185128 RenderbufferStorageMultisampleHelper(
5129 feature_info_, target, samples, impl_format, width, height);
[email protected]49cabed2013-11-13 18:15:185130 GLenum error =
5131 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
[email protected]9edc6b22010-12-23 02:00:265132 if (error == GL_NO_ERROR) {
[email protected]4a4c18b2013-09-13 22:50:105133
5134 if (workarounds().validate_multisample_buffer_allocation) {
5135 if (!VerifyMultisampleRenderbufferIntegrity(
5136 renderbuffer->service_id(), impl_format)) {
5137 LOCAL_SET_GL_ERROR(
5138 GL_OUT_OF_MEMORY,
[email protected]49cabed2013-11-13 18:15:185139 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
[email protected]4a4c18b2013-09-13 22:50:105140 return;
5141 }
5142 }
5143
[email protected]968351b2011-12-20 08:26:515144 // TODO(gman): If renderbuffers tracked which framebuffers they were
5145 // attached to we could just mark those framebuffers as not complete.
5146 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:205147 renderbuffer_manager()->SetInfo(
5148 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:265149 }
[email protected]8e3e0662010-08-23 18:46:305150}
5151
[email protected]49cabed2013-11-13 18:15:185152// This is the handler for multisampled_render_to_texture extensions.
5153void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5154 GLenum target, GLsizei samples, GLenum internalformat,
5155 GLsizei width, GLsizei height) {
5156 if (!features().multisampled_render_to_texture) {
5157 LOCAL_SET_GL_ERROR(
5158 GL_INVALID_OPERATION,
5159 "glRenderbufferStorageMultisampleEXT", "function not available");
5160 return;
5161 }
5162
5163 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5164 if (!renderbuffer) {
5165 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5166 "glRenderbufferStorageMultisampleEXT",
5167 "no renderbuffer bound");
5168 return;
5169 }
5170
5171 if (!ValidateRenderbufferStorageMultisample(
5172 samples, internalformat, width, height)) {
5173 return;
5174 }
5175
5176 GLenum impl_format =
5177 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5178 internalformat);
5179 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5180 if (features().use_img_for_multisampled_render_to_texture) {
5181 glRenderbufferStorageMultisampleIMG(
5182 target, samples, impl_format, width, height);
5183 } else {
5184 glRenderbufferStorageMultisampleEXT(
5185 target, samples, impl_format, width, height);
5186 }
5187 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5188 if (error == GL_NO_ERROR) {
5189 // TODO(gman): If renderbuffers tracked which framebuffers they were
5190 // attached to we could just mark those framebuffers as not complete.
5191 framebuffer_manager()->IncFramebufferStateChangeCount();
5192 renderbuffer_manager()->SetInfo(
5193 renderbuffer, samples, internalformat, width, height);
5194 }
5195}
5196
[email protected]4a4c18b2013-09-13 22:50:105197// This function validates the allocation of a multisampled renderbuffer
5198// by clearing it to a key color, blitting the contents to a texture, and
5199// reading back the color to ensure it matches the key.
5200bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5201 GLuint renderbuffer, GLenum format) {
5202
5203 // Only validate color buffers.
5204 // These formats have been selected because they are very common or are known
5205 // to be used by the WebGL backbuffer. If problems are observed with other
5206 // color formats they can be added here.
5207 switch(format) {
5208 case GL_RGB:
5209 case GL_RGB8:
5210 case GL_RGBA:
5211 case GL_RGBA8:
5212 break;
5213 default:
5214 return true;
5215 }
5216
5217 GLint draw_framebuffer, read_framebuffer;
5218
5219 // Cache framebuffer and texture bindings.
5220 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5221 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5222
5223 if (!validation_texture_) {
5224 GLint bound_texture;
5225 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5226
5227 // Create additional resources needed for the verification.
5228 glGenTextures(1, &validation_texture_);
5229 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5230 glGenFramebuffersEXT(1, &validation_fbo_);
5231
5232 // Texture only needs to be 1x1.
5233 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5234 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5235 GL_UNSIGNED_BYTE, NULL);
5236
5237 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5238 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5239 GL_TEXTURE_2D, validation_texture_, 0);
5240
5241 glBindTexture(GL_TEXTURE_2D, bound_texture);
5242 }
5243
5244 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5245 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5246 GL_RENDERBUFFER, renderbuffer);
5247
5248 // Cache current state and reset it to the values we require.
5249 GLboolean scissor_enabled = false;
5250 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5251 if (scissor_enabled)
5252 glDisable(GL_SCISSOR_TEST);
5253
5254 GLboolean color_mask[4] = {true, true, true, true};
5255 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5256 glColorMask(true, true, true, true);
5257
5258 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5259 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5260 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5261
5262 // Clear the buffer to the desired key color.
5263 glClear(GL_COLOR_BUFFER_BIT);
5264
5265 // Blit from the multisample buffer to a standard texture.
5266 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5267 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5268
[email protected]f42f05b2013-11-15 21:46:185269 BlitFramebufferHelper(
5270 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
[email protected]4a4c18b2013-09-13 22:50:105271
5272 // Read a pixel from the buffer.
5273 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5274
5275 unsigned char pixel[3] = {0, 0, 0};
5276 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5277
5278 // Detach the renderbuffer.
5279 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5280 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5281 GL_RENDERBUFFER, 0);
5282
5283 // Restore cached state.
5284 if (scissor_enabled)
5285 glEnable(GL_SCISSOR_TEST);
5286
5287 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5288 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5289 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5290 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5291
5292 // Return true if the pixel matched the desired key color.
5293 return (pixel[0] == 0xFF &&
5294 pixel[1] == 0x00 &&
5295 pixel[2] == 0xFF);
5296}
5297
[email protected]36cef8ce2010-03-16 07:34:455298void GLES2DecoderImpl::DoRenderbufferStorage(
5299 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]ed9f9cd2013-02-27 21:12:355300 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:205301 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5302 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:515303 LOCAL_SET_GL_ERROR(
5304 GL_INVALID_OPERATION,
5305 "glRenderbufferStorage", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:455306 return;
5307 }
[email protected]876f6fee2010-08-02 23:10:325308
[email protected]84afefa2011-10-19 21:45:535309 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5310 height > renderbuffer_manager()->max_renderbuffer_size()) {
[email protected]ab09b612013-03-11 22:11:515311 LOCAL_SET_GL_ERROR(
5312 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
[email protected]84afefa2011-10-19 21:45:535313 return;
5314 }
5315
[email protected]7989c9e2013-01-23 06:39:265316 uint32 estimated_size = 0;
[email protected]8e102e102013-09-20 22:50:235317 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5318 width, height, 1, internalformat, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515319 LOCAL_SET_GL_ERROR(
5320 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:265321 return;
5322 }
5323
5324 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515325 LOCAL_SET_GL_ERROR(
5326 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
[email protected]7989c9e2013-01-23 06:39:265327 return;
[email protected]b71f52c2010-06-18 22:20:205328 }
[email protected]876f6fee2010-08-02 23:10:325329
[email protected]ab09b612013-03-11 22:11:515330 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
[email protected]7989c9e2013-01-23 06:39:265331 glRenderbufferStorageEXT(
[email protected]8e102e102013-09-20 22:50:235332 target,
5333 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5334 internalformat),
5335 width,
5336 height);
[email protected]ab09b612013-03-11 22:11:515337 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
[email protected]9edc6b22010-12-23 02:00:265338 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:515339 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5340 // we could just mark those framebuffers as not complete.
5341 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:205342 renderbuffer_manager()->SetInfo(
[email protected]7989c9e2013-01-23 06:39:265343 renderbuffer, 1, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:265344 }
[email protected]36cef8ce2010-03-16 07:34:455345}
5346
[email protected]df37b9932013-03-08 05:21:425347void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
[email protected]43ed3a72012-05-30 22:55:385348 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]df37b9932013-03-08 05:21:425349 Program* program = GetProgramInfoNotShader(
5350 program_id, "glLinkProgram");
5351 if (!program) {
[email protected]a93bb842010-02-16 23:03:475352 return;
5353 }
[email protected]05afda12011-01-20 00:17:345354
[email protected]df37b9932013-03-08 05:21:425355 LogClientServiceForInfo(program, program_id, "glLinkProgram");
[email protected]65dfc602012-07-23 20:39:395356 ShaderTranslator* vertex_translator = NULL;
5357 ShaderTranslator* fragment_translator = NULL;
5358 if (use_shader_translator_) {
[email protected]7cd76fd2013-06-02 21:11:115359 vertex_translator = vertex_translator_.get();
5360 fragment_translator = fragment_translator_.get();
[email protected]65dfc602012-07-23 20:39:395361 }
[email protected]df37b9932013-03-08 05:21:425362 if (program->Link(shader_manager(),
[email protected]7cd76fd2013-06-02 21:11:115363 vertex_translator,
5364 fragment_translator,
5365 feature_info_.get(),
5366 shader_cache_callback_)) {
[email protected]df37b9932013-03-08 05:21:425367 if (program == state_.current_program.get()) {
[email protected]62e155e2012-10-23 22:43:155368 if (workarounds().use_current_program_after_successful_link) {
[email protected]df37b9932013-03-08 05:21:425369 glUseProgram(program->service_id());
[email protected]c2a3caf12012-10-23 19:32:005370 }
[email protected]df37b9932013-03-08 05:21:425371 program_manager()->ClearUniforms(program);
[email protected]2df73892012-04-28 01:09:545372 }
5373 }
[email protected]07f54fcc2009-12-22 02:46:305374};
5375
[email protected]3916c97e2010-02-25 03:20:505376void GLES2DecoderImpl::DoTexParameterf(
5377 GLenum target, GLenum pname, GLfloat param) {
[email protected]c986af502013-08-14 01:04:445378 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5379 &state_, target);
[email protected]02965c22013-03-09 02:40:075380 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515381 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245382 return;
[email protected]07f54fcc2009-12-22 02:46:305383 }
[email protected]cbb22e42011-05-12 23:36:245384
[email protected]02965c22013-03-09 02:40:075385 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505386 "glTexParameterf", GetErrorState(), texture, pname,
5387 static_cast<GLint>(param));
[email protected]07f54fcc2009-12-22 02:46:305388}
5389
[email protected]3916c97e2010-02-25 03:20:505390void GLES2DecoderImpl::DoTexParameteri(
5391 GLenum target, GLenum pname, GLint param) {
[email protected]c986af502013-08-14 01:04:445392 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5393 &state_, target);
[email protected]02965c22013-03-09 02:40:075394 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515395 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245396 return;
[email protected]3916c97e2010-02-25 03:20:505397 }
[email protected]cbb22e42011-05-12 23:36:245398
[email protected]02965c22013-03-09 02:40:075399 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505400 "glTexParameteri", GetErrorState(), texture, pname, param);
[email protected]3916c97e2010-02-25 03:20:505401}
5402
5403void GLES2DecoderImpl::DoTexParameterfv(
5404 GLenum target, GLenum pname, const GLfloat* params) {
[email protected]c986af502013-08-14 01:04:445405 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5406 &state_, target);
[email protected]02965c22013-03-09 02:40:075407 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515408 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245409 return;
[email protected]3916c97e2010-02-25 03:20:505410 }
[email protected]cbb22e42011-05-12 23:36:245411
[email protected]02965c22013-03-09 02:40:075412 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505413 "glTexParameterfv", GetErrorState(), texture, pname,
5414 static_cast<GLint>(params[0]));
[email protected]3916c97e2010-02-25 03:20:505415}
5416
5417void GLES2DecoderImpl::DoTexParameteriv(
5418 GLenum target, GLenum pname, const GLint* params) {
[email protected]c986af502013-08-14 01:04:445419 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5420 &state_, target);
[email protected]02965c22013-03-09 02:40:075421 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515422 LOCAL_SET_GL_ERROR(
5423 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245424 return;
[email protected]3916c97e2010-02-25 03:20:505425 }
[email protected]cbb22e42011-05-12 23:36:245426
[email protected]02965c22013-03-09 02:40:075427 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505428 "glTexParameteriv", GetErrorState(), texture, pname, *params);
[email protected]3916c97e2010-02-25 03:20:505429}
5430
[email protected]939e7362010-05-13 20:49:105431bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]7cd76fd2013-06-02 21:11:115432 if (!state_.current_program.get()) {
[email protected]ad84a3a2012-06-08 21:42:435433 // The program does not exist.
[email protected]ab09b612013-03-11 22:11:515434 LOCAL_SET_GL_ERROR(
5435 GL_INVALID_OPERATION, function_name, "no program in use");
[email protected]ad84a3a2012-06-08 21:42:435436 return false;
[email protected]939e7362010-05-13 20:49:105437 }
[email protected]e259eb412012-10-13 05:47:245438 if (!state_.current_program->InUse()) {
[email protected]ab09b612013-03-11 22:11:515439 LOCAL_SET_GL_ERROR(
5440 GL_INVALID_OPERATION, function_name, "program not linked");
[email protected]939e7362010-05-13 20:49:105441 return false;
5442 }
5443 return true;
5444}
5445
5446bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5447 GLint location, const char* function_name) {
5448 if (!CheckCurrentProgram(function_name)) {
5449 return false;
5450 }
5451 return location != -1;
5452}
5453
[email protected]476ccb72012-12-06 15:52:525454namespace {
5455
5456static const GLenum valid_int_vec1_types_list[] = {
5457 GL_INT,
5458 GL_BOOL,
5459 GL_SAMPLER_2D,
5460 GL_SAMPLER_2D_RECT_ARB,
5461 GL_SAMPLER_CUBE,
5462 GL_SAMPLER_EXTERNAL_OES,
5463};
5464
5465static const GLenum valid_int_vec2_types_list[] = {
5466 GL_INT_VEC2,
5467 GL_BOOL_VEC2,
5468};
5469
5470static const GLenum valid_int_vec3_types_list[] = {
5471 GL_INT_VEC3,
5472 GL_BOOL_VEC3,
5473};
5474
5475static const GLenum valid_int_vec4_types_list[] = {
5476 GL_INT_VEC4,
5477 GL_BOOL_VEC4,
5478};
5479
5480static const GLenum valid_float_vec1_types_list[] = {
5481 GL_FLOAT,
5482 GL_BOOL,
5483};
5484
5485static const GLenum valid_float_vec2_types_list[] = {
5486 GL_FLOAT_VEC2,
5487 GL_BOOL_VEC2,
5488};
5489
5490static const GLenum valid_float_vec3_types_list[] = {
5491 GL_FLOAT_VEC3,
5492 GL_BOOL_VEC3,
5493};
5494
5495static const GLenum valid_float_vec4_types_list[] = {
5496 GL_FLOAT_VEC4,
5497 GL_BOOL_VEC4,
5498};
5499
5500static const GLenum valid_float_mat2_types_list[] = {
5501 GL_FLOAT_MAT2,
5502};
5503
5504static const GLenum valid_float_mat3_types_list[] = {
5505 GL_FLOAT_MAT3,
5506};
5507
5508static const GLenum valid_float_mat4_types_list[] = {
5509 GL_FLOAT_MAT4,
5510};
5511
5512static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info = {
5513 valid_int_vec1_types_list,
5514 arraysize(valid_int_vec1_types_list),
5515};
5516
5517static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info = {
5518 valid_int_vec2_types_list,
5519 arraysize(valid_int_vec2_types_list),
5520};
5521
5522static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info = {
5523 valid_int_vec3_types_list,
5524 arraysize(valid_int_vec3_types_list),
5525};
5526
5527static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info = {
5528 valid_int_vec4_types_list,
5529 arraysize(valid_int_vec4_types_list),
5530};
5531
5532static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info = {
5533 valid_float_vec1_types_list,
5534 arraysize(valid_float_vec1_types_list),
5535};
5536
5537static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info = {
5538 valid_float_vec2_types_list,
5539 arraysize(valid_float_vec2_types_list),
5540};
5541
5542static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info = {
5543 valid_float_vec3_types_list,
5544 arraysize(valid_float_vec3_types_list),
5545};
5546
5547static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info = {
5548 valid_float_vec4_types_list,
5549 arraysize(valid_float_vec4_types_list),
5550};
5551
5552static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info = {
5553 valid_float_mat2_types_list,
5554 arraysize(valid_float_mat2_types_list),
5555};
5556
5557static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info = {
5558 valid_float_mat3_types_list,
5559 arraysize(valid_float_mat3_types_list),
5560};
5561
5562static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info = {
5563 valid_float_mat4_types_list,
5564 arraysize(valid_float_mat4_types_list),
5565};
5566
5567} // anonymous namespace.
5568
[email protected]43c2f1f2011-03-25 18:35:365569bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:125570 GLint fake_location, const char* function_name,
[email protected]476ccb72012-12-06 15:52:525571 const GLES2DecoderImpl::BaseUniformInfo& base_info,
[email protected]1b0a6752012-02-22 03:44:125572 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:365573 DCHECK(type);
5574 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:125575 DCHECK(real_location);
[email protected]476ccb72012-12-06 15:52:525576
[email protected]1b0a6752012-02-22 03:44:125577 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:105578 return false;
5579 }
[email protected]43c2f1f2011-03-25 18:35:365580 GLint array_index = -1;
[email protected]ed9f9cd2013-02-27 21:12:355581 const Program::UniformInfo* info =
[email protected]e259eb412012-10-13 05:47:245582 state_.current_program->GetUniformInfoByFakeLocation(
[email protected]1b0a6752012-02-22 03:44:125583 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:365584 if (!info) {
[email protected]ab09b612013-03-11 22:11:515585 LOCAL_SET_GL_ERROR(
5586 GL_INVALID_OPERATION, function_name, "unknown location");
[email protected]939e7362010-05-13 20:49:105587 return false;
5588 }
[email protected]476ccb72012-12-06 15:52:525589 bool okay = false;
5590 for (size_t ii = 0; ii < base_info.num_valid_types; ++ii) {
5591 if (base_info.valid_types[ii] == info->type) {
5592 okay = true;
5593 break;
5594 }
5595 }
5596 if (!okay) {
[email protected]ab09b612013-03-11 22:11:515597 LOCAL_SET_GL_ERROR(
5598 GL_INVALID_OPERATION, function_name,
5599 "wrong uniform function for type");
[email protected]476ccb72012-12-06 15:52:525600 return false;
5601 }
[email protected]43c2f1f2011-03-25 18:35:365602 if (*count > 1 && !info->is_array) {
[email protected]ab09b612013-03-11 22:11:515603 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:435604 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
[email protected]43c2f1f2011-03-25 18:35:365605 return false;
5606 }
5607 *count = std::min(info->size - array_index, *count);
5608 if (*count <= 0) {
5609 return false;
5610 }
5611 *type = info->type;
[email protected]939e7362010-05-13 20:49:105612 return true;
5613}
5614
[email protected]1b0a6752012-02-22 03:44:125615void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5616 GLenum type = 0;
5617 GLsizei count = 1;
5618 GLint real_location = -1;
5619 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525620 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5621 &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:505622 return;
5623 }
[email protected]e259eb412012-10-13 05:47:245624 if (!state_.current_program->SetSamplers(
[email protected]1868a342012-11-07 15:56:025625 state_.texture_units.size(), fake_location, 1, &v0)) {
[email protected]ab09b612013-03-11 22:11:515626 LOCAL_SET_GL_ERROR(
5627 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:465628 return;
5629 }
[email protected]1b0a6752012-02-22 03:44:125630 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:505631}
5632
5633void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:125634 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:365635 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125636 GLint real_location = -1;
5637 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525638 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5639 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365640 return;
5641 }
[email protected]74727112012-06-13 21:18:085642 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5643 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]e259eb412012-10-13 05:47:245644 if (!state_.current_program->SetSamplers(
[email protected]1868a342012-11-07 15:56:025645 state_.texture_units.size(), fake_location, count, value)) {
[email protected]ab09b612013-03-11 22:11:515646 LOCAL_SET_GL_ERROR(
5647 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:465648 return;
5649 }
[email protected]43c2f1f2011-03-25 18:35:365650 }
[email protected]1b0a6752012-02-22 03:44:125651 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:505652}
5653
[email protected]939e7362010-05-13 20:49:105654void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:125655 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365656 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125657 GLint real_location = -1;
5658 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525659 fake_location, "glUniform1fv", valid_float_vec1_base_info,
5660 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105661 return;
5662 }
5663 if (type == GL_BOOL) {
[email protected]40d90a22013-04-09 03:39:555664 scoped_ptr<GLint[]> temp(new GLint[count]);
[email protected]939e7362010-05-13 20:49:105665 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:535666 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105667 }
[email protected]1b0a6752012-02-22 03:44:125668 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105669 } else {
[email protected]1b0a6752012-02-22 03:44:125670 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105671 }
5672}
5673
5674void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:125675 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365676 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125677 GLint real_location = -1;
5678 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525679 fake_location, "glUniform2fv", valid_float_vec2_base_info,
5680 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105681 return;
5682 }
5683 if (type == GL_BOOL_VEC2) {
5684 GLsizei num_values = count * 2;
[email protected]40d90a22013-04-09 03:39:555685 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105686 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535687 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105688 }
[email protected]1b0a6752012-02-22 03:44:125689 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105690 } else {
[email protected]1b0a6752012-02-22 03:44:125691 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105692 }
5693}
5694
5695void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:125696 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365697 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125698 GLint real_location = -1;
5699 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525700 fake_location, "glUniform3fv", valid_float_vec3_base_info,
5701 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105702 return;
5703 }
5704 if (type == GL_BOOL_VEC3) {
5705 GLsizei num_values = count * 3;
[email protected]40d90a22013-04-09 03:39:555706 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105707 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535708 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105709 }
[email protected]1b0a6752012-02-22 03:44:125710 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105711 } else {
[email protected]1b0a6752012-02-22 03:44:125712 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105713 }
5714}
5715
5716void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:125717 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365718 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125719 GLint real_location = -1;
5720 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525721 fake_location, "glUniform4fv", valid_float_vec4_base_info,
5722 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105723 return;
5724 }
5725 if (type == GL_BOOL_VEC4) {
5726 GLsizei num_values = count * 4;
[email protected]40d90a22013-04-09 03:39:555727 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105728 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535729 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105730 }
[email protected]1b0a6752012-02-22 03:44:125731 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105732 } else {
[email protected]1b0a6752012-02-22 03:44:125733 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105734 }
5735}
5736
[email protected]43c2f1f2011-03-25 18:35:365737void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:125738 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365739 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125740 GLint real_location = -1;
5741 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525742 fake_location, "glUniform2iv", valid_int_vec2_base_info,
5743 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365744 return;
5745 }
[email protected]1b0a6752012-02-22 03:44:125746 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365747}
5748
5749void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:125750 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365751 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125752 GLint real_location = -1;
5753 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525754 fake_location, "glUniform3iv", valid_int_vec3_base_info,
5755 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365756 return;
5757 }
[email protected]1b0a6752012-02-22 03:44:125758 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365759}
5760
5761void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:125762 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365763 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125764 GLint real_location = -1;
5765 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525766 fake_location, "glUniform4iv", valid_int_vec4_base_info,
5767 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365768 return;
5769 }
[email protected]1b0a6752012-02-22 03:44:125770 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365771}
5772
5773void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:125774 GLint fake_location, GLsizei count, GLboolean transpose,
5775 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365776 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125777 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365778 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525779 fake_location, "glUniformMatrix2fv", valid_float_mat2_base_info,
5780 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365781 return;
5782 }
[email protected]1b0a6752012-02-22 03:44:125783 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365784}
5785
5786void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:125787 GLint fake_location, GLsizei count, GLboolean transpose,
5788 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365789 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125790 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365791 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525792 fake_location, "glUniformMatrix3fv", valid_float_mat3_base_info,
5793 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365794 return;
5795 }
[email protected]1b0a6752012-02-22 03:44:125796 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365797}
5798
5799void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:125800 GLint fake_location, GLsizei count, GLboolean transpose,
5801 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365802 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125803 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365804 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525805 fake_location, "glUniformMatrix4fv", valid_float_mat4_base_info,
5806 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365807 return;
5808 }
[email protected]1b0a6752012-02-22 03:44:125809 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365810}
5811
[email protected]df37b9932013-03-08 05:21:425812void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
[email protected]ae51d192010-04-27 00:48:035813 GLuint service_id = 0;
[email protected]df37b9932013-03-08 05:21:425814 Program* program = NULL;
5815 if (program_id) {
5816 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5817 if (!program) {
[email protected]ae51d192010-04-27 00:48:035818 return;
5819 }
[email protected]df37b9932013-03-08 05:21:425820 if (!program->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:505821 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ab09b612013-03-11 22:11:515822 LOCAL_SET_GL_ERROR(
5823 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
[email protected]3916c97e2010-02-25 03:20:505824 return;
5825 }
[email protected]df37b9932013-03-08 05:21:425826 service_id = program->service_id();
[email protected]3916c97e2010-02-25 03:20:505827 }
[email protected]7cd76fd2013-06-02 21:11:115828 if (state_.current_program.get()) {
5829 program_manager()->UnuseProgram(shader_manager(),
5830 state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:145831 }
[email protected]df37b9932013-03-08 05:21:425832 state_.current_program = program;
5833 LogClientServiceMapping("glUseProgram", program_id, service_id);
[email protected]2df73892012-04-28 01:09:545834 glUseProgram(service_id);
[email protected]7cd76fd2013-06-02 21:11:115835 if (state_.current_program.get()) {
5836 program_manager()->UseProgram(state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:145837 }
[email protected]3916c97e2010-02-25 03:20:505838}
5839
[email protected]ab09b612013-03-11 22:11:515840void GLES2DecoderImpl::RenderWarning(
5841 const char* filename, int line, const std::string& msg) {
[email protected]1d82e822013-04-10 21:32:325842 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
[email protected]0f8afe82012-05-14 23:43:015843}
5844
[email protected]ab09b612013-03-11 22:11:515845void GLES2DecoderImpl::PerformanceWarning(
5846 const char* filename, int line, const std::string& msg) {
[email protected]d3eba342013-04-18 21:11:505847 logger_.LogMessage(filename, line,
5848 std::string("PERFORMANCE WARNING: ") + msg);
[email protected]0f8afe82012-05-14 23:43:015849}
5850
[email protected]e8dc5662013-10-17 23:28:295851void GLES2DecoderImpl::UpdateStreamTextureIfNeeded(Texture* texture,
5852 GLuint texture_unit_index) {
[email protected]e56131d22013-07-28 16:14:115853 if (texture && texture->IsStreamTexture()) {
5854 DCHECK(stream_texture_manager());
5855 StreamTexture* stream_tex =
5856 stream_texture_manager()->LookupStreamTexture(texture->service_id());
[email protected]e8dc5662013-10-17 23:28:295857 if (stream_tex) {
5858 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
[email protected]e56131d22013-07-28 16:14:115859 stream_tex->Update();
[email protected]e8dc5662013-10-17 23:28:295860 }
[email protected]e56131d22013-07-28 16:14:115861 }
5862}
5863
[email protected]91c94eb2013-10-22 10:32:545864void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
5865 Texture* texture, GLenum textarget) {
5866 // This might be supported in the future.
5867 if (textarget != GL_TEXTURE_2D)
5868 return;
5869 // Image is already in use if texture is attached to a framebuffer.
5870 if (texture && !texture->IsAttachedToFramebuffer()) {
5871 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5872 if (image) {
5873 ScopedGLErrorSuppressor suppressor(
5874 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
5875 GetErrorState());
5876 glBindTexture(textarget, texture->service_id());
5877 image->WillUseTexImage();
[email protected]ce296892013-10-24 22:04:365878 RestoreCurrentTexture2DBindings(&state_);
[email protected]91c94eb2013-10-22 10:32:545879 }
5880 }
5881}
5882
5883void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
5884 Texture* texture, GLenum textarget) {
5885 // This might be supported in the future.
5886 if (textarget != GL_TEXTURE_2D)
5887 return;
5888 // Image is still in use if texture is attached to a framebuffer.
5889 if (texture && !texture->IsAttachedToFramebuffer()) {
5890 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5891 if (image) {
5892 ScopedGLErrorSuppressor suppressor(
5893 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
5894 GetErrorState());
5895 glBindTexture(textarget, texture->service_id());
5896 image->DidUseTexImage();
[email protected]ce296892013-10-24 22:04:365897 RestoreCurrentTexture2DBindings(&state_);
[email protected]91c94eb2013-10-22 10:32:545898 }
5899 }
5900}
5901
[email protected]e56131d22013-07-28 16:14:115902bool GLES2DecoderImpl::PrepareTexturesForRender() {
[email protected]7cd76fd2013-06-02 21:11:115903 DCHECK(state_.current_program.get());
[email protected]91c94eb2013-10-22 10:32:545904 if (!texture_manager()->HaveUnrenderableTextures() &&
5905 !texture_manager()->HaveImages() &&
5906 !features().oes_egl_image_external) {
[email protected]e56131d22013-07-28 16:14:115907 return true;
[email protected]ef526492010-06-02 23:12:255908 }
[email protected]e2367b42013-05-31 03:37:215909
[email protected]ef526492010-06-02 23:12:255910 bool textures_set = false;
[email protected]ed9f9cd2013-02-27 21:12:355911 const Program::SamplerIndices& sampler_indices =
[email protected]e259eb412012-10-13 05:47:245912 state_.current_program->sampler_indices();
[email protected]3916c97e2010-02-25 03:20:505913 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355914 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245915 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]3916c97e2010-02-25 03:20:505916 DCHECK(uniform_info);
5917 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5918 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025919 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245920 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]91c94eb2013-10-22 10:32:545921 TextureRef* texture_ref =
[email protected]cadac622013-06-11 16:46:365922 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
[email protected]91c94eb2013-10-22 10:32:545923 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
5924 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
[email protected]ef526492010-06-02 23:12:255925 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:505926 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5927 glBindTexture(
[email protected]91c94eb2013-10-22 10:32:545928 textarget,
[email protected]00f893d2010-08-24 18:55:495929 texture_manager()->black_texture_id(uniform_info->type));
[email protected]ab09b612013-03-11 22:11:515930 LOCAL_RENDER_WARNING(
[email protected]0f8afe82012-05-14 23:43:015931 std::string("texture bound to texture unit ") +
5932 base::IntToString(texture_unit_index) +
[email protected]ad9b7f8b2013-06-17 07:36:295933 " is not renderable. It maybe non-power-of-2 and have"
5934 " incompatible texture filtering or is not"
5935 " 'texture complete'");
[email protected]91c94eb2013-10-22 10:32:545936 continue;
[email protected]3916c97e2010-02-25 03:20:505937 }
[email protected]91c94eb2013-10-22 10:32:545938
5939 Texture* texture = texture_ref->texture();
5940 if (textarget == GL_TEXTURE_2D) {
5941 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5942 if (image && !texture->IsAttachedToFramebuffer()) {
5943 ScopedGLErrorSuppressor suppressor(
5944 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
5945 textures_set = true;
5946 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5947 image->WillUseTexImage();
5948 continue;
5949 }
5950 }
5951
5952 UpdateStreamTextureIfNeeded(texture, texture_unit_index);
[email protected]3916c97e2010-02-25 03:20:505953 }
5954 // else: should this be an error?
5955 }
5956 }
[email protected]e56131d22013-07-28 16:14:115957 return !textures_set;
[email protected]3916c97e2010-02-25 03:20:505958}
5959
[email protected]91c94eb2013-10-22 10:32:545960void GLES2DecoderImpl::RestoreStateForTextures() {
[email protected]7cd76fd2013-06-02 21:11:115961 DCHECK(state_.current_program.get());
[email protected]ed9f9cd2013-02-27 21:12:355962 const Program::SamplerIndices& sampler_indices =
[email protected]7cd76fd2013-06-02 21:11:115963 state_.current_program->sampler_indices();
[email protected]3916c97e2010-02-25 03:20:505964 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355965 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245966 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]3916c97e2010-02-25 03:20:505967 DCHECK(uniform_info);
5968 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5969 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025970 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245971 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]7cd76fd2013-06-02 21:11:115972 TextureRef* texture_ref =
[email protected]91c94eb2013-10-22 10:32:545973 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
[email protected]370eaf12013-05-18 09:19:495974 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
[email protected]3916c97e2010-02-25 03:20:505975 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
[email protected]370eaf12013-05-18 09:19:495976 // Get the texture_ref info that was previously bound here.
[email protected]7cd76fd2013-06-02 21:11:115977 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
5978 ? texture_unit.bound_texture_2d.get()
5979 : texture_unit.bound_texture_cube_map.get();
[email protected]3916c97e2010-02-25 03:20:505980 glBindTexture(texture_unit.bind_target,
[email protected]370eaf12013-05-18 09:19:495981 texture_ref ? texture_ref->service_id() : 0);
[email protected]91c94eb2013-10-22 10:32:545982 continue;
5983 }
5984
5985 Texture* texture = texture_ref->texture();
5986 if (texture_unit.bind_target == GL_TEXTURE_2D) {
5987 gfx::GLImage* image = texture->GetLevelImage(
5988 texture_unit.bind_target, 0);
5989 if (image && !texture->IsAttachedToFramebuffer()) {
5990 ScopedGLErrorSuppressor suppressor(
5991 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
5992 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5993 image->DidUseTexImage();
5994 continue;
5995 }
[email protected]3916c97e2010-02-25 03:20:505996 }
5997 }
5998 }
5999 }
6000 // Set the active texture back to whatever the user had it as.
[email protected]e259eb412012-10-13 05:47:246001 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]07f54fcc2009-12-22 02:46:306002}
6003
[email protected]0d6bfdc2011-11-02 01:32:206004bool GLES2DecoderImpl::ClearUnclearedTextures() {
6005 // Only check if there are some uncleared textures.
6006 if (!texture_manager()->HaveUnsafeTextures()) {
6007 return true;
6008 }
6009
6010 // 1: Check all textures we are about to render with.
[email protected]7cd76fd2013-06-02 21:11:116011 if (state_.current_program.get()) {
[email protected]ed9f9cd2013-02-27 21:12:356012 const Program::SamplerIndices& sampler_indices =
[email protected]7cd76fd2013-06-02 21:11:116013 state_.current_program->sampler_indices();
[email protected]0d6bfdc2011-11-02 01:32:206014 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:356015 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:246016 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]0d6bfdc2011-11-02 01:32:206017 DCHECK(uniform_info);
6018 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6019 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:026020 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:246021 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]370eaf12013-05-18 09:19:496022 TextureRef* texture_ref =
[email protected]cadac622013-06-11 16:46:366023 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
[email protected]370eaf12013-05-18 09:19:496024 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6025 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
[email protected]0d6bfdc2011-11-02 01:32:206026 return false;
6027 }
6028 }
6029 }
6030 }
6031 }
6032 }
6033 return true;
6034}
6035
[email protected]c6aef902012-02-14 03:31:426036bool GLES2DecoderImpl::IsDrawValid(
[email protected]ad84a3a2012-06-08 21:42:436037 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:036038 // NOTE: We specifically do not check current_program->IsValid() because
6039 // it could never be invalid since glUseProgram would have failed. While
6040 // glLinkProgram could later mark the program as invalid the previous
6041 // valid program will still function if it is still the current program.
[email protected]7cd76fd2013-06-02 21:11:116042 if (!state_.current_program.get()) {
[email protected]3916c97e2010-02-25 03:20:506043 // The program does not exist.
6044 // But GL says no ERROR.
[email protected]ab09b612013-03-11 22:11:516045 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
[email protected]3916c97e2010-02-25 03:20:506046 return false;
6047 }
[email protected]c6aef902012-02-14 03:31:426048
[email protected]7cd76fd2013-06-02 21:11:116049 return state_.vertex_attrib_manager
6050 ->ValidateBindings(function_name,
6051 this,
6052 feature_info_.get(),
6053 state_.current_program.get(),
6054 max_vertex_accessed,
6055 primcount);
[email protected]b1122982010-05-17 23:04:246056}
6057
[email protected]c13e1da62011-09-09 21:48:306058bool GLES2DecoderImpl::SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:436059 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
[email protected]c13e1da62011-09-09 21:48:306060 DCHECK(simulated);
6061 *simulated = false;
6062
[email protected]876f6fee2010-08-02 23:10:326063 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:306064 return true;
[email protected]876f6fee2010-08-02 23:10:326065
[email protected]ac77603c72013-03-08 13:52:066066 const VertexAttrib* attrib =
[email protected]ed9f9cd2013-02-27 21:12:356067 state_.vertex_attrib_manager->GetVertexAttrib(0);
[email protected]b1122982010-05-17 23:04:246068 // If it's enabled or it's not used then we don't need to do anything.
[email protected]e259eb412012-10-13 05:47:246069 bool attrib_0_used =
6070 state_.current_program->GetAttribInfoByLocation(0) != NULL;
[email protected]ac77603c72013-03-08 13:52:066071 if (attrib->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:306072 return true;
[email protected]b1122982010-05-17 23:04:246073 }
6074
[email protected]b1122982010-05-17 23:04:246075 // Make a buffer with a single repeated vec4 value enough to
6076 // simulate the constant value that is supposed to be here.
6077 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:306078 GLuint num_vertices = max_vertex_accessed + 1;
[email protected]3aad1a32012-09-07 20:54:476079 uint32 size_needed = 0;
[email protected]c13e1da62011-09-09 21:48:306080
6081 if (num_vertices == 0 ||
[email protected]3aad1a32012-09-07 20:54:476082 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
[email protected]c13e1da62011-09-09 21:48:306083 size_needed > 0x7FFFFFFFU) {
[email protected]ab09b612013-03-11 22:11:516084 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:306085 return false;
6086 }
6087
[email protected]ab09b612013-03-11 22:11:516088 LOCAL_PERFORMANCE_WARNING(
[email protected]0f8afe82012-05-14 23:43:016089 "Attribute 0 is disabled. This has signficant performance penalty");
6090
[email protected]ab09b612013-03-11 22:11:516091 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
[email protected]c13e1da62011-09-09 21:48:306092 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6093
[email protected]8f0b86c2f2012-04-10 05:48:286094 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6095 if (new_buffer) {
[email protected]fc753442011-02-04 19:49:496096 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:306097 GLenum error = glGetError();
6098 if (error != GL_NO_ERROR) {
[email protected]ab09b612013-03-11 22:11:516099 LOCAL_SET_GL_ERROR(
6100 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:306101 return false;
6102 }
[email protected]fc753442011-02-04 19:49:496103 }
[email protected]af6380962012-11-29 23:24:136104
6105 const Vec4& value = state_.attrib_values[0];
[email protected]8f0b86c2f2012-04-10 05:48:286106 if (new_buffer ||
6107 (attrib_0_used &&
6108 (!attrib_0_buffer_matches_value_ ||
[email protected]af6380962012-11-29 23:24:136109 (value.v[0] != attrib_0_value_.v[0] ||
6110 value.v[1] != attrib_0_value_.v[1] ||
6111 value.v[2] != attrib_0_value_.v[2] ||
6112 value.v[3] != attrib_0_value_.v[3])))) {
6113 std::vector<Vec4> temp(num_vertices, value);
[email protected]fc753442011-02-04 19:49:496114 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6115 attrib_0_buffer_matches_value_ = true;
[email protected]af6380962012-11-29 23:24:136116 attrib_0_value_ = value;
[email protected]b1122982010-05-17 23:04:246117 attrib_0_size_ = size_needed;
6118 }
6119
6120 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6121
[email protected]ac77603c72013-03-08 13:52:066122 if (attrib->divisor())
[email protected]c6aef902012-02-14 03:31:426123 glVertexAttribDivisorANGLE(0, 0);
6124
[email protected]c13e1da62011-09-09 21:48:306125 *simulated = true;
[email protected]b1122982010-05-17 23:04:246126 return true;
[email protected]b1122982010-05-17 23:04:246127}
6128
[email protected]ac77603c72013-03-08 13:52:066129void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
6130 const VertexAttrib* attrib =
6131 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6132 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6133 Buffer* buffer = attrib->buffer();
[email protected]b10492f2013-03-08 05:24:076134 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
[email protected]b1122982010-05-17 23:04:246135 glVertexAttribPointer(
[email protected]ac77603c72013-03-08 13:52:066136 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6137 attrib->gl_stride(), ptr);
6138 if (attrib->divisor())
6139 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
[email protected]e259eb412012-10-13 05:47:246140 glBindBuffer(
6141 GL_ARRAY_BUFFER,
[email protected]7cd76fd2013-06-02 21:11:116142 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6143 : 0);
[email protected]43410e92012-04-20 17:06:286144
[email protected]265f8992012-07-20 01:03:146145 // Never touch vertex attribute 0's state (in particular, never
6146 // disable it) when running on desktop GL because it will never be
6147 // re-enabled.
[email protected]ac77603c72013-03-08 13:52:066148 if (attrib_index != 0 ||
[email protected]265f8992012-07-20 01:03:146149 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]ac77603c72013-03-08 13:52:066150 if (attrib->enabled()) {
6151 glEnableVertexAttribArray(attrib_index);
[email protected]265f8992012-07-20 01:03:146152 } else {
[email protected]ac77603c72013-03-08 13:52:066153 glDisableVertexAttribArray(attrib_index);
[email protected]265f8992012-07-20 01:03:146154 }
[email protected]43410e92012-04-20 17:06:286155 }
[email protected]b1122982010-05-17 23:04:246156}
[email protected]07f54fcc2009-12-22 02:46:306157
[email protected]8fbedc02010-11-18 18:43:406158bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:436159 const char* function_name,
[email protected]c6aef902012-02-14 03:31:426160 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:406161 DCHECK(simulated);
6162 *simulated = false;
6163 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6164 return true;
6165
[email protected]e259eb412012-10-13 05:47:246166 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:406167 return true;
6168 }
6169
[email protected]ab09b612013-03-11 22:11:516170 LOCAL_PERFORMANCE_WARNING(
[email protected]0f8afe82012-05-14 23:43:016171 "GL_FIXED attributes have a signficant performance penalty");
6172
[email protected]8fbedc02010-11-18 18:43:406173 // NOTE: we could be smart and try to check if a buffer is used
6174 // twice in 2 different attribs, find the overlapping parts and therefore
6175 // duplicate the minimum amount of data but this whole code path is not meant
6176 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6177 // tests so we just add to the buffer attrib used.
6178
[email protected]c13e1da62011-09-09 21:48:306179 GLuint elements_needed = 0;
[email protected]ac77603c72013-03-08 13:52:066180 const VertexAttribManager::VertexAttribList& enabled_attribs =
6181 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6182 for (VertexAttribManager::VertexAttribList::const_iterator it =
6183 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6184 const VertexAttrib* attrib = *it;
[email protected]ed9f9cd2013-02-27 21:12:356185 const Program::VertexAttrib* attrib_info =
[email protected]ac77603c72013-03-08 13:52:066186 state_.current_program->GetAttribInfoByLocation(attrib->index());
6187 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6188 max_vertex_accessed);
[email protected]c6aef902012-02-14 03:31:426189 GLuint num_vertices = max_accessed + 1;
6190 if (num_vertices == 0) {
[email protected]ab09b612013-03-11 22:11:516191 LOCAL_SET_GL_ERROR(
6192 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:426193 return false;
6194 }
[email protected]8fbedc02010-11-18 18:43:406195 if (attrib_info &&
[email protected]ac77603c72013-03-08 13:52:066196 attrib->CanAccess(max_accessed) &&
6197 attrib->type() == GL_FIXED) {
[email protected]3aad1a32012-09-07 20:54:476198 uint32 elements_used = 0;
[email protected]ac77603c72013-03-08 13:52:066199 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
[email protected]3aad1a32012-09-07 20:54:476200 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
[email protected]ab09b612013-03-11 22:11:516201 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:436202 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:406203 return false;
6204 }
6205 }
6206 }
6207
[email protected]3aad1a32012-09-07 20:54:476208 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6209 uint32 size_needed = 0;
6210 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
[email protected]c13e1da62011-09-09 21:48:306211 size_needed > 0x7FFFFFFFU) {
[email protected]ab09b612013-03-11 22:11:516212 LOCAL_SET_GL_ERROR(
6213 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:406214 return false;
6215 }
6216
[email protected]ab09b612013-03-11 22:11:516217 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
[email protected]8fbedc02010-11-18 18:43:406218
6219 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:306220 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:406221 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:306222 GLenum error = glGetError();
6223 if (error != GL_NO_ERROR) {
[email protected]ab09b612013-03-11 22:11:516224 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:436225 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]c13e1da62011-09-09 21:48:306226 return false;
6227 }
[email protected]8fbedc02010-11-18 18:43:406228 }
6229
6230 // Copy the elements and convert to float
6231 GLintptr offset = 0;
[email protected]ac77603c72013-03-08 13:52:066232 for (VertexAttribManager::VertexAttribList::const_iterator it =
6233 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6234 const VertexAttrib* attrib = *it;
[email protected]ed9f9cd2013-02-27 21:12:356235 const Program::VertexAttrib* attrib_info =
[email protected]ac77603c72013-03-08 13:52:066236 state_.current_program->GetAttribInfoByLocation(attrib->index());
6237 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
[email protected]c6aef902012-02-14 03:31:426238 max_vertex_accessed);
6239 GLuint num_vertices = max_accessed + 1;
6240 if (num_vertices == 0) {
[email protected]ab09b612013-03-11 22:11:516241 LOCAL_SET_GL_ERROR(
6242 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:426243 return false;
6244 }
[email protected]8fbedc02010-11-18 18:43:406245 if (attrib_info &&
[email protected]ac77603c72013-03-08 13:52:066246 attrib->CanAccess(max_accessed) &&
6247 attrib->type() == GL_FIXED) {
6248 int num_elements = attrib->size() * kSizeOfFloat;
[email protected]8fbedc02010-11-18 18:43:406249 int size = num_elements * num_vertices;
[email protected]40d90a22013-04-09 03:39:556250 scoped_ptr<float[]> data(new float[size]);
[email protected]8fbedc02010-11-18 18:43:406251 const int32* src = reinterpret_cast<const int32 *>(
[email protected]ac77603c72013-03-08 13:52:066252 attrib->buffer()->GetRange(attrib->offset(), size));
[email protected]8fbedc02010-11-18 18:43:406253 const int32* end = src + num_elements;
6254 float* dst = data.get();
6255 while (src != end) {
6256 *dst++ = static_cast<float>(*src++) / 65536.0f;
6257 }
6258 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6259 glVertexAttribPointer(
[email protected]ac77603c72013-03-08 13:52:066260 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
[email protected]8fbedc02010-11-18 18:43:406261 reinterpret_cast<GLvoid*>(offset));
6262 offset += size;
6263 }
6264 }
6265 *simulated = true;
6266 return true;
6267}
6268
6269void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6270 // There's no need to call glVertexAttribPointer because we shadow all the
6271 // settings and passing GL_FIXED to it will not work.
[email protected]e259eb412012-10-13 05:47:246272 glBindBuffer(
6273 GL_ARRAY_BUFFER,
[email protected]7cd76fd2013-06-02 21:11:116274 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6275 : 0);
[email protected]8fbedc02010-11-18 18:43:406276}
6277
[email protected]ad84a3a2012-06-08 21:42:436278error::Error GLES2DecoderImpl::DoDrawArrays(
6279 const char* function_name,
6280 bool instanced,
6281 GLenum mode,
6282 GLint first,
6283 GLsizei count,
6284 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:086285 if (ShouldDeferDraws())
6286 return error::kDeferCommandUntilLater;
[email protected]38d139d2011-07-14 00:38:436287 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ab09b612013-03-11 22:11:516288 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
[email protected]38d139d2011-07-14 00:38:436289 return error::kNoError;
6290 }
6291 if (count < 0) {
[email protected]ab09b612013-03-11 22:11:516292 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]38d139d2011-07-14 00:38:436293 return error::kNoError;
6294 }
[email protected]c6aef902012-02-14 03:31:426295 if (primcount < 0) {
[email protected]ab09b612013-03-11 22:11:516296 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:426297 return error::kNoError;
6298 }
[email protected]ad84a3a2012-06-08 21:42:436299 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]38d139d2011-07-14 00:38:436300 return error::kNoError;
6301 }
6302 // We have to check this here because the prototype for glDrawArrays
6303 // is GLint not GLsizei.
6304 if (first < 0) {
[email protected]ab09b612013-03-11 22:11:516305 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
[email protected]38d139d2011-07-14 00:38:436306 return error::kNoError;
6307 }
6308
[email protected]c6aef902012-02-14 03:31:426309 if (count == 0 || (instanced && primcount == 0)) {
[email protected]ab09b612013-03-11 22:11:516310 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
[email protected]38d139d2011-07-14 00:38:436311 return error::kNoError;
6312 }
6313
6314 GLuint max_vertex_accessed = first + count - 1;
[email protected]ad84a3a2012-06-08 21:42:436315 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:206316 if (!ClearUnclearedTextures()) {
[email protected]ab09b612013-03-11 22:11:516317 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:206318 return error::kNoError;
6319 }
[email protected]c13e1da62011-09-09 21:48:306320 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:436321 if (!SimulateAttrib0(
6322 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:306323 return error::kNoError;
6324 }
[email protected]38d139d2011-07-14 00:38:436325 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:436326 if (SimulateFixedAttribs(
6327 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6328 primcount)) {
[email protected]e56131d22013-07-28 16:14:116329 bool textures_set = !PrepareTexturesForRender();
[email protected]38d139d2011-07-14 00:38:436330 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:426331 if (!instanced) {
6332 glDrawArrays(mode, first, count);
6333 } else {
6334 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6335 }
[email protected]22e3f552012-03-13 01:54:196336 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:436337 if (textures_set) {
[email protected]91c94eb2013-10-22 10:32:546338 RestoreStateForTextures();
[email protected]38d139d2011-07-14 00:38:436339 }
6340 if (simulated_fixed_attribs) {
6341 RestoreStateForSimulatedFixedAttribs();
6342 }
6343 }
6344 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:286345 RestoreStateForAttrib(0);
[email protected]38d139d2011-07-14 00:38:436346 }
[email protected]38d139d2011-07-14 00:38:436347 }
6348 return error::kNoError;
6349}
6350
[email protected]c6aef902012-02-14 03:31:426351error::Error GLES2DecoderImpl::HandleDrawArrays(
[email protected]ed9f9cd2013-02-27 21:12:356352 uint32 immediate_data_size, const cmds::DrawArrays& c) {
[email protected]ad84a3a2012-06-08 21:42:436353 return DoDrawArrays("glDrawArrays",
6354 false,
[email protected]c6aef902012-02-14 03:31:426355 static_cast<GLenum>(c.mode),
6356 static_cast<GLint>(c.first),
6357 static_cast<GLsizei>(c.count),
6358 0);
6359}
6360
6361error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356362 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156363 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516364 LOCAL_SET_GL_ERROR(
6365 GL_INVALID_OPERATION,
6366 "glDrawArraysInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426367 return error::kNoError;
6368 }
[email protected]ad84a3a2012-06-08 21:42:436369 return DoDrawArrays("glDrawArraysIntancedANGLE",
6370 true,
[email protected]c6aef902012-02-14 03:31:426371 static_cast<GLenum>(c.mode),
6372 static_cast<GLint>(c.first),
6373 static_cast<GLsizei>(c.count),
6374 static_cast<GLsizei>(c.primcount));
6375}
6376
[email protected]ad84a3a2012-06-08 21:42:436377error::Error GLES2DecoderImpl::DoDrawElements(
6378 const char* function_name,
6379 bool instanced,
6380 GLenum mode,
6381 GLsizei count,
6382 GLenum type,
6383 int32 offset,
6384 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:086385 if (ShouldDeferDraws())
6386 return error::kDeferCommandUntilLater;
[email protected]e259eb412012-10-13 05:47:246387 if (!state_.vertex_attrib_manager->element_array_buffer()) {
[email protected]ab09b612013-03-11 22:11:516388 LOCAL_SET_GL_ERROR(
6389 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
[email protected]8eee29c2010-04-29 03:38:296390 return error::kNoError;
6391 }
6392
[email protected]8eee29c2010-04-29 03:38:296393 if (count < 0) {
[email protected]ab09b612013-03-11 22:11:516394 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]8eee29c2010-04-29 03:38:296395 return error::kNoError;
6396 }
6397 if (offset < 0) {
[email protected]ab09b612013-03-11 22:11:516398 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296399 return error::kNoError;
6400 }
[email protected]9438b012010-06-15 22:55:056401 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ab09b612013-03-11 22:11:516402 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
[email protected]8eee29c2010-04-29 03:38:296403 return error::kNoError;
6404 }
[email protected]9438b012010-06-15 22:55:056405 if (!validators_->index_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:516406 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
[email protected]8eee29c2010-04-29 03:38:296407 return error::kNoError;
6408 }
[email protected]c6aef902012-02-14 03:31:426409 if (primcount < 0) {
[email protected]ab09b612013-03-11 22:11:516410 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:426411 return error::kNoError;
6412 }
[email protected]8eee29c2010-04-29 03:38:296413
[email protected]ad84a3a2012-06-08 21:42:436414 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]3a03a8f2011-03-19 00:51:276415 return error::kNoError;
6416 }
6417
[email protected]c6aef902012-02-14 03:31:426418 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:316419 return error::kNoError;
6420 }
6421
[email protected]8eee29c2010-04-29 03:38:296422 GLuint max_vertex_accessed;
[email protected]17cfbe0e2013-03-07 01:26:086423 Buffer* element_array_buffer =
6424 state_.vertex_attrib_manager->element_array_buffer();
6425
6426 if (!element_array_buffer->GetMaxValueForRange(
6427 offset, count, type, &max_vertex_accessed)) {
[email protected]ab09b612013-03-11 22:11:516428 LOCAL_SET_GL_ERROR(
6429 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
[email protected]8eee29c2010-04-29 03:38:296430 return error::kNoError;
6431 }
6432
[email protected]ad84a3a2012-06-08 21:42:436433 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:206434 if (!ClearUnclearedTextures()) {
[email protected]ab09b612013-03-11 22:11:516435 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:206436 return error::kNoError;
6437 }
[email protected]c13e1da62011-09-09 21:48:306438 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:436439 if (!SimulateAttrib0(
6440 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:306441 return error::kNoError;
6442 }
[email protected]8fbedc02010-11-18 18:43:406443 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:436444 if (SimulateFixedAttribs(
6445 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6446 primcount)) {
[email protected]e56131d22013-07-28 16:14:116447 bool textures_set = !PrepareTexturesForRender();
[email protected]297ca1c2011-06-20 23:08:466448 ApplyDirtyState();
[email protected]17cfbe0e2013-03-07 01:26:086449 // TODO(gman): Refactor to hide these details in BufferManager or
6450 // VertexAttribManager.
[email protected]8fbedc02010-11-18 18:43:406451 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]17cfbe0e2013-03-07 01:26:086452 bool used_client_side_array = false;
6453 if (element_array_buffer->IsClientSideArray()) {
6454 used_client_side_array = true;
6455 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6456 indices = element_array_buffer->GetRange(offset, 0);
6457 }
6458
[email protected]c6aef902012-02-14 03:31:426459 if (!instanced) {
6460 glDrawElements(mode, count, type, indices);
6461 } else {
6462 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6463 }
[email protected]17cfbe0e2013-03-07 01:26:086464
6465 if (used_client_side_array) {
6466 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6467 element_array_buffer->service_id());
6468 }
6469
[email protected]22e3f552012-03-13 01:54:196470 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:406471 if (textures_set) {
[email protected]91c94eb2013-10-22 10:32:546472 RestoreStateForTextures();
[email protected]8fbedc02010-11-18 18:43:406473 }
6474 if (simulated_fixed_attribs) {
6475 RestoreStateForSimulatedFixedAttribs();
6476 }
[email protected]ba3176a2009-12-16 18:19:466477 }
[email protected]b1122982010-05-17 23:04:246478 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:286479 RestoreStateForAttrib(0);
[email protected]b1122982010-05-17 23:04:246480 }
[email protected]96449d2c2009-11-25 00:01:326481 }
[email protected]f7a64ee2010-02-01 22:24:146482 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326483}
6484
[email protected]c6aef902012-02-14 03:31:426485error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]ed9f9cd2013-02-27 21:12:356486 uint32 immediate_data_size, const cmds::DrawElements& c) {
[email protected]ad84a3a2012-06-08 21:42:436487 return DoDrawElements("glDrawElements",
6488 false,
[email protected]c6aef902012-02-14 03:31:426489 static_cast<GLenum>(c.mode),
6490 static_cast<GLsizei>(c.count),
6491 static_cast<GLenum>(c.type),
6492 static_cast<int32>(c.index_offset),
6493 0);
6494}
6495
6496error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356497 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156498 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516499 LOCAL_SET_GL_ERROR(
6500 GL_INVALID_OPERATION,
6501 "glDrawElementsInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426502 return error::kNoError;
6503 }
[email protected]ad84a3a2012-06-08 21:42:436504 return DoDrawElements("glDrawElementsInstancedANGLE",
6505 true,
[email protected]c6aef902012-02-14 03:31:426506 static_cast<GLenum>(c.mode),
6507 static_cast<GLsizei>(c.count),
6508 static_cast<GLenum>(c.type),
6509 static_cast<int32>(c.index_offset),
6510 static_cast<GLsizei>(c.primcount));
6511}
6512
[email protected]269200b12010-11-18 22:53:066513GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:236514 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6515 GLuint max_vertex_accessed = 0;
[email protected]b10492f2013-03-08 05:24:076516 Buffer* buffer = GetBuffer(buffer_id);
6517 if (!buffer) {
[email protected]ae51d192010-04-27 00:48:036518 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]ab09b612013-03-11 22:11:516519 LOCAL_SET_GL_ERROR(
6520 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
[email protected]29a9eb52010-04-13 09:04:236521 } else {
[email protected]b10492f2013-03-08 05:24:076522 if (!buffer->GetMaxValueForRange(
6523 offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:036524 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]ab09b612013-03-11 22:11:516525 LOCAL_SET_GL_ERROR(
[email protected]269200b12010-11-18 22:53:066526 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436527 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:236528 }
6529 }
6530 return max_vertex_accessed;
6531}
6532
[email protected]96449d2c2009-11-25 00:01:326533// Calls glShaderSource for the various versions of the ShaderSource command.
6534// Assumes that data / data_size points to a piece of memory that is in range
6535// of whatever context it came from (shared memory, immediate memory, bucket
6536// memory.)
[email protected]45bf5152010-02-12 00:11:316537error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:036538 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:576539 std::string str(data, data + data_size);
[email protected]df37b9932013-03-08 05:21:426540 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6541 if (!shader) {
[email protected]45bf5152010-02-12 00:11:316542 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326543 }
[email protected]45bf5152010-02-12 00:11:316544 // Note: We don't actually call glShaderSource here. We wait until
6545 // the call to glCompileShader.
[email protected]df37b9932013-03-08 05:21:426546 shader->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:146547 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326548}
6549
[email protected]f7a64ee2010-02-01 22:24:146550error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]ed9f9cd2013-02-27 21:12:356551 uint32 immediate_data_size, const cmds::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:326552 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:316553 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:326554 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:466555 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146556 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:326557 }
[email protected]ae51d192010-04-27 00:48:036558 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:326559}
6560
[email protected]558847a2010-03-24 07:02:546561error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
[email protected]ed9f9cd2013-02-27 21:12:356562 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:546563 Bucket* bucket = GetBucket(c.data_bucket_id);
6564 if (!bucket || bucket->size() == 0) {
6565 return error::kInvalidArguments;
6566 }
6567 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:036568 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:546569 bucket->size() - 1);
6570}
6571
[email protected]ae51d192010-04-27 00:48:036572void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]43ed3a72012-05-30 22:55:386573 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]df37b9932013-03-08 05:21:426574 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6575 if (!shader) {
[email protected]45bf5152010-02-12 00:11:316576 return;
6577 }
[email protected]f57bb282010-11-12 00:51:346578 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:186579 if (use_shader_translator_) {
[email protected]df37b9932013-03-08 05:21:426580 translator = shader->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:456581 vertex_translator_.get() : fragment_translator_.get();
[email protected]de17df392010-04-23 21:09:416582 }
[email protected]de17df392010-04-23 21:09:416583
[email protected]7cd76fd2013-06-02 21:11:116584 program_manager()->DoCompileShader(shader, translator, feature_info_.get());
[email protected]45bf5152010-02-12 00:11:316585};
6586
[email protected]ddd968b82010-03-02 00:44:296587void GLES2DecoderImpl::DoGetShaderiv(
[email protected]df37b9932013-03-08 05:21:426588 GLuint shader_id, GLenum pname, GLint* params) {
6589 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6590 if (!shader) {
[email protected]ddd968b82010-03-02 00:44:296591 return;
6592 }
[email protected]8f1ccdac2010-05-19 21:01:486593 switch (pname) {
6594 case GL_SHADER_SOURCE_LENGTH:
[email protected]df37b9932013-03-08 05:21:426595 *params = shader->source() ? shader->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:486596 return;
6597 case GL_COMPILE_STATUS:
[email protected]df37b9932013-03-08 05:21:426598 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
[email protected]e5186162010-06-14 18:54:416599 return;
[email protected]8f1ccdac2010-05-19 21:01:486600 case GL_INFO_LOG_LENGTH:
[email protected]df37b9932013-03-08 05:21:426601 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:416602 return;
[email protected]d6a53e42011-10-05 00:09:366603 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
[email protected]df37b9932013-03-08 05:21:426604 *params = shader->translated_source() ?
6605 shader->translated_source()->size() + 1 : 0;
[email protected]d6a53e42011-10-05 00:09:366606 return;
[email protected]8f1ccdac2010-05-19 21:01:486607 default:
6608 break;
[email protected]ddd968b82010-03-02 00:44:296609 }
[email protected]df37b9932013-03-08 05:21:426610 glGetShaderiv(shader->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:296611}
6612
[email protected]ae51d192010-04-27 00:48:036613error::Error GLES2DecoderImpl::HandleGetShaderSource(
[email protected]ed9f9cd2013-02-27 21:12:356614 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
[email protected]df37b9932013-03-08 05:21:426615 GLuint shader_id = c.shader;
[email protected]ae51d192010-04-27 00:48:036616 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6617 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426618 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6619 if (!shader || !shader->source()) {
[email protected]8eee29c2010-04-29 03:38:296620 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:296621 return error::kNoError;
6622 }
[email protected]df37b9932013-03-08 05:21:426623 bucket->SetFromString(shader->source()->c_str());
[email protected]ae51d192010-04-27 00:48:036624 return error::kNoError;
6625}
6626
[email protected]d6a53e42011-10-05 00:09:366627error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6628 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:356629 const cmds::GetTranslatedShaderSourceANGLE& c) {
[email protected]df37b9932013-03-08 05:21:426630 GLuint shader_id = c.shader;
[email protected]d6a53e42011-10-05 00:09:366631 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6632 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426633 Shader* shader = GetShaderInfoNotProgram(
6634 shader_id, "glTranslatedGetShaderSourceANGLE");
6635 if (!shader) {
[email protected]d6a53e42011-10-05 00:09:366636 bucket->SetSize(0);
6637 return error::kNoError;
6638 }
6639
[email protected]df37b9932013-03-08 05:21:426640 bucket->SetFromString(shader->translated_source() ?
6641 shader->translated_source()->c_str() : NULL);
[email protected]d6a53e42011-10-05 00:09:366642 return error::kNoError;
6643}
6644
[email protected]ae51d192010-04-27 00:48:036645error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
[email protected]ed9f9cd2013-02-27 21:12:356646 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
[email protected]df37b9932013-03-08 05:21:426647 GLuint program_id = c.program;
[email protected]6b8cf1a2010-05-06 16:13:586648 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6649 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426650 Program* program = GetProgramInfoNotShader(
6651 program_id, "glGetProgramInfoLog");
6652 if (!program || !program->log_info()) {
[email protected]9a14ae612011-08-08 17:51:466653 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:036654 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:316655 }
[email protected]df37b9932013-03-08 05:21:426656 bucket->SetFromString(program->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:036657 return error::kNoError;
6658}
6659
6660error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
[email protected]ed9f9cd2013-02-27 21:12:356661 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
[email protected]df37b9932013-03-08 05:21:426662 GLuint shader_id = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:586663 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6664 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426665 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6666 if (!shader || !shader->log_info()) {
[email protected]9a14ae612011-08-08 17:51:466667 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:036668 return error::kNoError;
6669 }
[email protected]df37b9932013-03-08 05:21:426670 bucket->SetFromString(shader->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:036671 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326672}
6673
[email protected]d058bca2012-11-26 10:27:266674bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6675 return state_.GetEnabled(cap);
6676}
6677
[email protected]1958e0e2010-04-22 05:17:156678bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]16ccec12013-02-28 03:40:216679 const Buffer* buffer = GetBuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106680 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156681}
6682
6683bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:356684 const Framebuffer* framebuffer =
6685 GetFramebuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106686 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156687}
6688
6689bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:366690 // IsProgram is true for programs as soon as they are created, until they are
6691 // deleted and no longer in use.
[email protected]ed9f9cd2013-02-27 21:12:356692 const Program* program = GetProgram(client_id);
[email protected]a0b78dc2011-11-11 10:43:106693 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156694}
6695
6696bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:356697 const Renderbuffer* renderbuffer =
6698 GetRenderbuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106699 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156700}
6701
6702bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:366703 // IsShader is true for shaders as soon as they are created, until they
6704 // are deleted and not attached to any programs.
[email protected]ed9f9cd2013-02-27 21:12:356705 const Shader* shader = GetShader(client_id);
[email protected]a0b78dc2011-11-11 10:43:106706 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156707}
6708
6709bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]370eaf12013-05-18 09:19:496710 const TextureRef* texture_ref = GetTexture(client_id);
6711 return texture_ref && texture_ref->texture()->IsValid();
[email protected]ae51d192010-04-27 00:48:036712}
6713
6714void GLES2DecoderImpl::DoAttachShader(
6715 GLuint program_client_id, GLint shader_client_id) {
[email protected]df37b9932013-03-08 05:21:426716 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586717 program_client_id, "glAttachShader");
[email protected]df37b9932013-03-08 05:21:426718 if (!program) {
[email protected]ae51d192010-04-27 00:48:036719 return;
[email protected]1958e0e2010-04-22 05:17:156720 }
[email protected]df37b9932013-03-08 05:21:426721 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6722 if (!shader) {
[email protected]ae51d192010-04-27 00:48:036723 return;
6724 }
[email protected]df37b9932013-03-08 05:21:426725 if (!program->AttachShader(shader_manager(), shader)) {
[email protected]ab09b612013-03-11 22:11:516726 LOCAL_SET_GL_ERROR(
6727 GL_INVALID_OPERATION,
6728 "glAttachShader",
6729 "can not attach more than one shader of the same type.");
[email protected]fb96c8e2010-08-12 04:10:316730 return;
6731 }
[email protected]df37b9932013-03-08 05:21:426732 glAttachShader(program->service_id(), shader->service_id());
[email protected]ae51d192010-04-27 00:48:036733}
6734
6735void GLES2DecoderImpl::DoDetachShader(
6736 GLuint program_client_id, GLint shader_client_id) {
[email protected]df37b9932013-03-08 05:21:426737 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586738 program_client_id, "glDetachShader");
[email protected]df37b9932013-03-08 05:21:426739 if (!program) {
[email protected]ae51d192010-04-27 00:48:036740 return;
6741 }
[email protected]df37b9932013-03-08 05:21:426742 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6743 if (!shader) {
[email protected]ae51d192010-04-27 00:48:036744 return;
6745 }
[email protected]df37b9932013-03-08 05:21:426746 if (!program->DetachShader(shader_manager(), shader)) {
[email protected]ab09b612013-03-11 22:11:516747 LOCAL_SET_GL_ERROR(
6748 GL_INVALID_OPERATION,
6749 "glDetachShader", "shader not attached to program");
[email protected]9a0ccd42011-03-16 23:58:226750 return;
6751 }
[email protected]df37b9932013-03-08 05:21:426752 glDetachShader(program->service_id(), shader->service_id());
[email protected]ae51d192010-04-27 00:48:036753}
6754
6755void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]df37b9932013-03-08 05:21:426756 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586757 program_client_id, "glValidateProgram");
[email protected]df37b9932013-03-08 05:21:426758 if (!program) {
[email protected]ae51d192010-04-27 00:48:036759 return;
6760 }
[email protected]df37b9932013-03-08 05:21:426761 program->Validate();
[email protected]1958e0e2010-04-22 05:17:156762}
6763
[email protected]ac77603c72013-03-08 13:52:066764void GLES2DecoderImpl::GetVertexAttribHelper(
6765 const VertexAttrib* attrib, GLenum pname, GLint* params) {
[email protected]b1122982010-05-17 23:04:246766 switch (pname) {
6767 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
[email protected]ac77603c72013-03-08 13:52:066768 Buffer* buffer = attrib->buffer();
[email protected]b1122982010-05-17 23:04:246769 if (buffer && !buffer->IsDeleted()) {
6770 GLuint client_id;
6771 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6772 *params = client_id;
6773 }
6774 break;
6775 }
6776 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
[email protected]ac77603c72013-03-08 13:52:066777 *params = attrib->enabled();
[email protected]b1122982010-05-17 23:04:246778 break;
6779 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
[email protected]ac77603c72013-03-08 13:52:066780 *params = attrib->size();
[email protected]b1122982010-05-17 23:04:246781 break;
6782 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
[email protected]ac77603c72013-03-08 13:52:066783 *params = attrib->gl_stride();
[email protected]b1122982010-05-17 23:04:246784 break;
6785 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
[email protected]ac77603c72013-03-08 13:52:066786 *params = attrib->type();
[email protected]b1122982010-05-17 23:04:246787 break;
6788 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
[email protected]ac77603c72013-03-08 13:52:066789 *params = attrib->normalized();
[email protected]b1122982010-05-17 23:04:246790 break;
[email protected]c6aef902012-02-14 03:31:426791 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
[email protected]ac77603c72013-03-08 13:52:066792 *params = attrib->divisor();
[email protected]c6aef902012-02-14 03:31:426793 break;
[email protected]ac77603c72013-03-08 13:52:066794 default:
6795 NOTREACHED();
6796 break;
6797 }
6798}
6799
6800void GLES2DecoderImpl::DoGetVertexAttribfv(
6801 GLuint index, GLenum pname, GLfloat* params) {
6802 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6803 if (!attrib) {
[email protected]ab09b612013-03-11 22:11:516804 LOCAL_SET_GL_ERROR(
6805 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
[email protected]ac77603c72013-03-08 13:52:066806 return;
6807 }
6808 switch (pname) {
6809 case GL_CURRENT_VERTEX_ATTRIB: {
6810 const Vec4& value = state_.attrib_values[index];
6811 params[0] = value.v[0];
6812 params[1] = value.v[1];
6813 params[2] = value.v[2];
6814 params[3] = value.v[3];
6815 break;
6816 }
6817 default: {
6818 GLint value = 0;
6819 GetVertexAttribHelper(attrib, pname, &value);
6820 *params = static_cast<GLfloat>(value);
6821 break;
6822 }
6823 }
6824}
6825
6826void GLES2DecoderImpl::DoGetVertexAttribiv(
6827 GLuint index, GLenum pname, GLint* params) {
6828 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6829 if (!attrib) {
[email protected]ab09b612013-03-11 22:11:516830 LOCAL_SET_GL_ERROR(
6831 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
[email protected]ac77603c72013-03-08 13:52:066832 return;
6833 }
6834 switch (pname) {
[email protected]af6380962012-11-29 23:24:136835 case GL_CURRENT_VERTEX_ATTRIB: {
6836 const Vec4& value = state_.attrib_values[index];
6837 params[0] = static_cast<GLint>(value.v[0]);
6838 params[1] = static_cast<GLint>(value.v[1]);
6839 params[2] = static_cast<GLint>(value.v[2]);
6840 params[3] = static_cast<GLint>(value.v[3]);
[email protected]b1122982010-05-17 23:04:246841 break;
[email protected]af6380962012-11-29 23:24:136842 }
[email protected]b1122982010-05-17 23:04:246843 default:
[email protected]ac77603c72013-03-08 13:52:066844 GetVertexAttribHelper(attrib, pname, params);
[email protected]b1122982010-05-17 23:04:246845 break;
6846 }
6847}
6848
[email protected]af6380962012-11-29 23:24:136849bool GLES2DecoderImpl::SetVertexAttribValue(
6850 const char* function_name, GLuint index, const GLfloat* value) {
6851 if (index >= state_.attrib_values.size()) {
[email protected]ab09b612013-03-11 22:11:516852 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
[email protected]af6380962012-11-29 23:24:136853 return false;
[email protected]b1122982010-05-17 23:04:246854 }
[email protected]af6380962012-11-29 23:24:136855 Vec4& v = state_.attrib_values[index];
6856 v.v[0] = value[0];
6857 v.v[1] = value[1];
6858 v.v[2] = value[2];
6859 v.v[3] = value[3];
6860 return true;
6861}
6862
6863void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6864 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6865 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6866 glVertexAttrib1f(index, v0);
6867 }
[email protected]b1122982010-05-17 23:04:246868}
6869
6870void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
[email protected]af6380962012-11-29 23:24:136871 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6872 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6873 glVertexAttrib2f(index, v0, v1);
[email protected]b1122982010-05-17 23:04:246874 }
[email protected]b1122982010-05-17 23:04:246875}
6876
6877void GLES2DecoderImpl::DoVertexAttrib3f(
6878 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
[email protected]af6380962012-11-29 23:24:136879 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6880 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6881 glVertexAttrib3f(index, v0, v1, v2);
[email protected]b1122982010-05-17 23:04:246882 }
[email protected]b1122982010-05-17 23:04:246883}
6884
6885void GLES2DecoderImpl::DoVertexAttrib4f(
6886 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
[email protected]af6380962012-11-29 23:24:136887 GLfloat v[4] = { v0, v1, v2, v3, };
6888 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6889 glVertexAttrib4f(index, v0, v1, v2, v3);
[email protected]b1122982010-05-17 23:04:246890 }
[email protected]b1122982010-05-17 23:04:246891}
6892
6893void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136894 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6895 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6896 glVertexAttrib1fv(index, v);
[email protected]b1122982010-05-17 23:04:246897 }
[email protected]b1122982010-05-17 23:04:246898}
6899
6900void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136901 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6902 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6903 glVertexAttrib2fv(index, v);
[email protected]b1122982010-05-17 23:04:246904 }
[email protected]b1122982010-05-17 23:04:246905}
6906
6907void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136908 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
6909 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
6910 glVertexAttrib3fv(index, v);
[email protected]b1122982010-05-17 23:04:246911 }
[email protected]b1122982010-05-17 23:04:246912}
6913
6914void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136915 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
6916 glVertexAttrib4fv(index, v);
[email protected]b1122982010-05-17 23:04:246917 }
[email protected]b1122982010-05-17 23:04:246918}
6919
[email protected]f7a64ee2010-02-01 22:24:146920error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]ed9f9cd2013-02-27 21:12:356921 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
[email protected]944b62f32012-09-27 02:20:466922
[email protected]7cd76fd2013-06-02 21:11:116923 if (!state_.bound_array_buffer.get() ||
6924 state_.bound_array_buffer->IsDeleted()) {
6925 if (state_.vertex_attrib_manager.get() ==
6926 default_vertex_attrib_manager_.get()) {
[email protected]ab09b612013-03-11 22:11:516927 LOCAL_SET_GL_ERROR(
6928 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
[email protected]944b62f32012-09-27 02:20:466929 return error::kNoError;
6930 } else if (c.offset != 0) {
[email protected]ab09b612013-03-11 22:11:516931 LOCAL_SET_GL_ERROR(
6932 GL_INVALID_VALUE,
6933 "glVertexAttribPointer", "client side arrays are not allowed");
[email protected]944b62f32012-09-27 02:20:466934 return error::kNoError;
6935 }
[email protected]96449d2c2009-11-25 00:01:326936 }
[email protected]8eee29c2010-04-29 03:38:296937
6938 GLuint indx = c.indx;
6939 GLint size = c.size;
6940 GLenum type = c.type;
6941 GLboolean normalized = c.normalized;
6942 GLsizei stride = c.stride;
6943 GLsizei offset = c.offset;
6944 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:056945 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:516946 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
[email protected]8eee29c2010-04-29 03:38:296947 return error::kNoError;
6948 }
[email protected]9438b012010-06-15 22:55:056949 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ab09b612013-03-11 22:11:516950 LOCAL_SET_GL_ERROR(
6951 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
[email protected]8eee29c2010-04-29 03:38:296952 return error::kNoError;
6953 }
6954 if (indx >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:516955 LOCAL_SET_GL_ERROR(
6956 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
[email protected]8eee29c2010-04-29 03:38:296957 return error::kNoError;
6958 }
6959 if (stride < 0) {
[email protected]ab09b612013-03-11 22:11:516960 LOCAL_SET_GL_ERROR(
6961 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
[email protected]8eee29c2010-04-29 03:38:296962 return error::kNoError;
6963 }
6964 if (stride > 255) {
[email protected]ab09b612013-03-11 22:11:516965 LOCAL_SET_GL_ERROR(
6966 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
[email protected]8eee29c2010-04-29 03:38:296967 return error::kNoError;
6968 }
6969 if (offset < 0) {
[email protected]ab09b612013-03-11 22:11:516970 LOCAL_SET_GL_ERROR(
6971 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296972 return error::kNoError;
6973 }
6974 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:316975 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:296976 if (offset % component_size > 0) {
[email protected]ab09b612013-03-11 22:11:516977 LOCAL_SET_GL_ERROR(
6978 GL_INVALID_OPERATION,
6979 "glVertexAttribPointer", "offset not valid for type");
[email protected]ff81c192011-01-07 23:04:316980 return error::kNoError;
6981 }
6982 if (stride % component_size > 0) {
[email protected]ab09b612013-03-11 22:11:516983 LOCAL_SET_GL_ERROR(
6984 GL_INVALID_OPERATION,
6985 "glVertexAttribPointer", "stride not valid for type");
[email protected]8eee29c2010-04-29 03:38:296986 return error::kNoError;
6987 }
[email protected]7cd76fd2013-06-02 21:11:116988 state_.vertex_attrib_manager
6989 ->SetAttribInfo(indx,
6990 state_.bound_array_buffer.get(),
6991 size,
6992 type,
6993 normalized,
6994 stride,
6995 stride != 0 ? stride : component_size * size,
6996 offset);
[email protected]8fbedc02010-11-18 18:43:406997 if (type != GL_FIXED) {
6998 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6999 }
[email protected]f7a64ee2010-02-01 22:24:147000 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327001}
7002
[email protected]43410e92012-04-20 17:06:287003void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7004 GLsizei height) {
[email protected]e259eb412012-10-13 05:47:247005 state_.viewport_x = x;
7006 state_.viewport_y = y;
[email protected]1868a342012-11-07 15:56:027007 state_.viewport_width = std::min(width, viewport_max_width_);
7008 state_.viewport_height = std::min(height, viewport_max_height_);
[email protected]43410e92012-04-20 17:06:287009 glViewport(x, y, width, height);
7010}
7011
[email protected]c6aef902012-02-14 03:31:427012error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
[email protected]ed9f9cd2013-02-27 21:12:357013 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
[email protected]62e155e2012-10-23 22:43:157014 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:517015 LOCAL_SET_GL_ERROR(
7016 GL_INVALID_OPERATION,
7017 "glVertexAttribDivisorANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:427018 }
7019 GLuint index = c.index;
7020 GLuint divisor = c.divisor;
7021 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:517022 LOCAL_SET_GL_ERROR(
7023 GL_INVALID_VALUE,
7024 "glVertexAttribDivisorANGLE", "index out of range");
[email protected]c6aef902012-02-14 03:31:427025 return error::kNoError;
7026 }
7027
[email protected]e259eb412012-10-13 05:47:247028 state_.vertex_attrib_manager->SetDivisor(
[email protected]c6aef902012-02-14 03:31:427029 index,
7030 divisor);
7031 glVertexAttribDivisorANGLE(index, divisor);
7032 return error::kNoError;
7033}
7034
[email protected]5a36dc132013-07-23 23:17:557035void GLES2DecoderImpl::FinishReadPixels(
7036 const cmds::ReadPixels& c,
7037 GLuint buffer) {
7038 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7039 GLsizei width = c.width;
7040 GLsizei height = c.height;
7041 GLenum format = c.format;
7042 GLenum type = c.type;
7043 typedef cmds::ReadPixels::Result Result;
7044 uint32 pixels_size;
7045 Result* result = NULL;
7046 if (c.result_shm_id != 0) {
7047 result = GetSharedMemoryAs<Result*>(
7048 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7049 if (!result) {
7050 if (buffer != 0) {
7051 glDeleteBuffersARB(1, &buffer);
7052 }
7053 return;
7054 }
7055 }
7056 GLES2Util::ComputeImageDataSizes(
7057 width, height, format, type, state_.pack_alignment, &pixels_size,
7058 NULL, NULL);
7059 void* pixels = GetSharedMemoryAs<void*>(
7060 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7061 if (!pixels) {
7062 if (buffer != 0) {
7063 glDeleteBuffersARB(1, &buffer);
7064 }
7065 return;
7066 }
7067
7068 if (buffer != 0) {
7069 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
[email protected]e585f9e22013-08-27 02:50:337070 void* data;
7071 if (features().map_buffer_range) {
7072 data = glMapBufferRange(
7073 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7074 } else {
7075 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7076 }
[email protected]5a36dc132013-07-23 23:17:557077 memcpy(pixels, data, pixels_size);
7078 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7079 // have to restore the state.
7080 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7081 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7082 glDeleteBuffersARB(1, &buffer);
7083 }
7084
7085 if (result != NULL) {
7086 *result = true;
7087 }
7088
7089 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7090 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7091 if ((channels_exist & 0x0008) == 0 &&
7092 workarounds().clear_alpha_in_readpixels) {
7093 // Set the alpha to 255 because some drivers are buggy in this regard.
7094 uint32 temp_size;
7095
7096 uint32 unpadded_row_size;
7097 uint32 padded_row_size;
7098 if (!GLES2Util::ComputeImageDataSizes(
7099 width, 2, format, type, state_.pack_alignment, &temp_size,
7100 &unpadded_row_size, &padded_row_size)) {
7101 return;
7102 }
7103 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
7104 // of this implementation.
7105 if (type != GL_UNSIGNED_BYTE) {
7106 return;
7107 }
7108 switch (format) {
7109 case GL_RGBA:
7110 case GL_BGRA_EXT:
7111 case GL_ALPHA: {
7112 int offset = (format == GL_ALPHA) ? 0 : 3;
7113 int step = (format == GL_ALPHA) ? 1 : 4;
7114 uint8* dst = static_cast<uint8*>(pixels) + offset;
7115 for (GLint yy = 0; yy < height; ++yy) {
7116 uint8* end = dst + unpadded_row_size;
7117 for (uint8* d = dst; d < end; d += step) {
7118 *d = 255;
7119 }
7120 dst += padded_row_size;
7121 }
7122 break;
7123 }
7124 default:
7125 break;
7126 }
7127 }
7128}
7129
7130
[email protected]f7a64ee2010-02-01 22:24:147131error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]ed9f9cd2013-02-27 21:12:357132 uint32 immediate_data_size, const cmds::ReadPixels& c) {
[email protected]09e17272012-11-30 10:30:447133 if (ShouldDeferReads())
7134 return error::kDeferCommandUntilLater;
[email protected]612d2f82009-12-08 20:49:317135 GLint x = c.x;
7136 GLint y = c.y;
7137 GLsizei width = c.width;
7138 GLsizei height = c.height;
7139 GLenum format = c.format;
7140 GLenum type = c.type;
[email protected]5a36dc132013-07-23 23:17:557141 GLboolean async = c.async;
[email protected]57f223832010-03-19 01:57:567142 if (width < 0 || height < 0) {
[email protected]ab09b612013-03-11 22:11:517143 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
[email protected]57f223832010-03-19 01:57:567144 return error::kNoError;
7145 }
[email protected]ed9f9cd2013-02-27 21:12:357146 typedef cmds::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:187147 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:347148 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247149 width, height, format, type, state_.pack_alignment, &pixels_size,
7150 NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:187151 return error::kOutOfBounds;
7152 }
[email protected]612d2f82009-12-08 20:49:317153 void* pixels = GetSharedMemoryAs<void*>(
7154 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]de43f082013-04-02 01:16:107155 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147156 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467157 }
[email protected]de43f082013-04-02 01:16:107158 Result* result = NULL;
7159 if (c.result_shm_id != 0) {
7160 result = GetSharedMemoryAs<Result*>(
7161 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7162 if (!result) {
7163 return error::kOutOfBounds;
7164 }
7165 }
[email protected]a51788e2010-02-24 21:54:257166
[email protected]9438b012010-06-15 22:55:057167 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:517168 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
[email protected]8eee29c2010-04-29 03:38:297169 return error::kNoError;
7170 }
[email protected]9438b012010-06-15 22:55:057171 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:517172 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
[email protected]d2cf0a2d2010-02-25 21:36:127173 return error::kNoError;
7174 }
[email protected]57f223832010-03-19 01:57:567175 if (width == 0 || height == 0) {
7176 return error::kNoError;
7177 }
7178
[email protected]57f223832010-03-19 01:57:567179 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:307180 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:567181
[email protected]3aad1a32012-09-07 20:54:477182 int32 max_x;
7183 int32 max_y;
7184 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
[email protected]ab09b612013-03-11 22:11:517185 LOCAL_SET_GL_ERROR(
7186 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:147187 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:317188 }
[email protected]57f223832010-03-19 01:57:567189
[email protected]0d6bfdc2011-11-02 01:32:207190 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7191 return error::kNoError;
7192 }
7193
[email protected]ab09b612013-03-11 22:11:517194 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
[email protected]a0b78dc2011-11-11 10:43:107195
7196 ScopedResolvedFrameBufferBinder binder(this, false, true);
7197
[email protected]d37231fa2010-04-09 21:16:027198 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:567199 // The user requested an out of range area. Get the results 1 line
7200 // at a time.
7201 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:347202 uint32 unpadded_row_size;
7203 uint32 padded_row_size;
7204 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247205 width, 2, format, type, state_.pack_alignment, &temp_size,
[email protected]3458a64a2012-04-10 17:39:347206 &unpadded_row_size, &padded_row_size)) {
[email protected]ab09b612013-03-11 22:11:517207 LOCAL_SET_GL_ERROR(
7208 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:567209 return error::kNoError;
7210 }
7211
7212 GLint dest_x_offset = std::max(-x, 0);
7213 uint32 dest_row_offset;
[email protected]3458a64a2012-04-10 17:39:347214 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247215 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7216 NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:517217 LOCAL_SET_GL_ERROR(
7218 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:567219 return error::kNoError;
7220 }
7221
7222 // Copy each row into the larger dest rect.
7223 int8* dst = static_cast<int8*>(pixels);
7224 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:027225 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:567226 GLint read_width = read_end_x - read_x;
7227 for (GLint yy = 0; yy < height; ++yy) {
7228 GLint ry = y + yy;
7229
7230 // Clear the row.
7231 memset(dst, 0, unpadded_row_size);
7232
7233 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:027234 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:567235 glReadPixels(
7236 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7237 }
7238 dst += padded_row_size;
7239 }
7240 } else {
[email protected]5a36dc132013-07-23 23:17:557241 if (async && features().use_async_readpixels) {
7242 GLuint buffer;
7243 glGenBuffersARB(1, &buffer);
7244 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7245 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7246 GLenum error = glGetError();
7247 if (error == GL_NO_ERROR) {
7248 glReadPixels(x, y, width, height, format, type, 0);
7249 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7250 new FenceCallback()));
7251 WaitForReadPixels(base::Bind(
7252 &GLES2DecoderImpl::FinishReadPixels,
7253 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7254 <GLES2DecoderImpl>(this),
7255 c, buffer));
7256 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7257 return error::kNoError;
7258 }
7259 }
[email protected]57f223832010-03-19 01:57:567260 glReadPixels(x, y, width, height, format, type, pixels);
7261 }
[email protected]ab09b612013-03-11 22:11:517262 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
[email protected]a51788e2010-02-24 21:54:257263 if (error == GL_NO_ERROR) {
[email protected]de43f082013-04-02 01:16:107264 if (result != NULL) {
7265 *result = true;
7266 }
[email protected]5a36dc132013-07-23 23:17:557267 FinishReadPixels(c, 0);
[email protected]a51788e2010-02-24 21:54:257268 }
[email protected]4848b9f82011-03-10 18:37:567269
[email protected]f7a64ee2010-02-01 22:24:147270 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327271}
7272
[email protected]f7a64ee2010-02-01 22:24:147273error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]ed9f9cd2013-02-27 21:12:357274 uint32 immediate_data_size, const cmds::PixelStorei& c) {
[email protected]b9849abf2009-11-25 19:13:197275 GLenum pname = c.pname;
7276 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:057277 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]ab09b612013-03-11 22:11:517278 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
[email protected]d2cf0a2d2010-02-25 21:36:127279 return error::kNoError;
7280 }
[email protected]222471d2011-11-30 18:06:397281 switch (pname) {
7282 case GL_PACK_ALIGNMENT:
7283 case GL_UNPACK_ALIGNMENT:
7284 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]ab09b612013-03-11 22:11:517285 LOCAL_SET_GL_ERROR(
7286 GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE");
[email protected]222471d2011-11-30 18:06:397287 return error::kNoError;
7288 }
[email protected]164d6d52012-05-05 00:55:037289 break;
[email protected]0a1e9ad2012-05-04 21:13:037290 case GL_UNPACK_FLIP_Y_CHROMIUM:
7291 unpack_flip_y_ = (param != 0);
7292 return error::kNoError;
7293 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7294 unpack_premultiply_alpha_ = (param != 0);
7295 return error::kNoError;
[email protected]6c75c712012-06-19 15:43:177296 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7297 unpack_unpremultiply_alpha_ = (param != 0);
7298 return error::kNoError;
[email protected]222471d2011-11-30 18:06:397299 default:
7300 break;
[email protected]b9849abf2009-11-25 19:13:197301 }
7302 glPixelStorei(pname, param);
7303 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:437304 case GL_PACK_ALIGNMENT:
[email protected]e259eb412012-10-13 05:47:247305 state_.pack_alignment = param;
[email protected]ad84a3a2012-06-08 21:42:437306 break;
7307 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
[email protected]88a61bf2012-10-27 13:00:427308 state_.pack_reverse_row_order = (param != 0);
[email protected]ad84a3a2012-06-08 21:42:437309 break;
7310 case GL_UNPACK_ALIGNMENT:
[email protected]e259eb412012-10-13 05:47:247311 state_.unpack_alignment = param;
[email protected]ad84a3a2012-06-08 21:42:437312 break;
7313 default:
7314 // Validation should have prevented us from getting here.
7315 NOTREACHED();
7316 break;
[email protected]b9849abf2009-11-25 19:13:197317 }
[email protected]f7a64ee2010-02-01 22:24:147318 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197319}
7320
[email protected]1c75a3702011-11-11 14:15:287321error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:357322 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
[email protected]43ed3a72012-05-30 22:55:387323 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]6f5fac9d12012-06-26 21:02:457324 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]ab09b612013-03-11 22:11:517325 LOCAL_SET_GL_ERROR(
7326 GL_INVALID_OPERATION,
7327 "glPostSubBufferCHROMIUM", "command not supported by surface");
[email protected]1c75a3702011-11-11 14:15:287328 return error::kNoError;
7329 }
[email protected]8f9b8dd2013-09-12 18:05:137330 bool is_tracing;
7331 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7332 &is_tracing);
7333 if (is_tracing) {
7334 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7335 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7336 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7337 is_offscreen ? offscreen_size_ : surface_->GetSize());
7338 }
[email protected]7794d512012-04-17 20:36:497339 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
[email protected]1c75a3702011-11-11 14:15:287340 return error::kNoError;
[email protected]7794d512012-04-17 20:36:497341 } else {
7342 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
[email protected]1c75a3702011-11-11 14:15:287343 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:497344 }
[email protected]1c75a3702011-11-11 14:15:287345}
7346
[email protected]558847a2010-03-24 07:02:547347error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7348 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7349 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:577350 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ab09b612013-03-11 22:11:517351 LOCAL_SET_GL_ERROR(
7352 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:577353 return error::kNoError;
7354 }
[email protected]df37b9932013-03-08 05:21:427355 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:587356 client_id, "glGetAttribLocation");
[email protected]df37b9932013-03-08 05:21:427357 if (!program) {
[email protected]f7a64ee2010-02-01 22:24:147358 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197359 }
[email protected]df37b9932013-03-08 05:21:427360 if (!program->IsValid()) {
[email protected]ab09b612013-03-11 22:11:517361 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437362 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:257363 return error::kNoError;
7364 }
[email protected]b9849abf2009-11-25 19:13:197365 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:547366 location_shm_id, location_shm_offset, sizeof(GLint));
7367 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:147368 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197369 }
[email protected]558847a2010-03-24 07:02:547370 // Require the client to init this incase the context is lost and we are no
7371 // longer executing commands.
7372 if (*location != -1) {
7373 return error::kGenericError;
7374 }
[email protected]df37b9932013-03-08 05:21:427375 *location = program->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:147376 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197377}
7378
[email protected]558847a2010-03-24 07:02:547379error::Error GLES2DecoderImpl::HandleGetAttribLocation(
[email protected]ed9f9cd2013-02-27 21:12:357380 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
[email protected]558847a2010-03-24 07:02:547381 uint32 name_size = c.data_size;
7382 const char* name = GetSharedMemoryAs<const char*>(
7383 c.name_shm_id, c.name_shm_offset, name_size);
7384 if (!name) {
7385 return error::kOutOfBounds;
7386 }
7387 String name_str(name, name_size);
7388 return GetAttribLocationHelper(
7389 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7390}
7391
[email protected]558847a2010-03-24 07:02:547392error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:357393 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
[email protected]558847a2010-03-24 07:02:547394 Bucket* bucket = GetBucket(c.name_bucket_id);
7395 if (!bucket) {
7396 return error::kInvalidArguments;
7397 }
7398 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:187399 if (!bucket->GetAsString(&name_str)) {
7400 return error::kInvalidArguments;
7401 }
[email protected]558847a2010-03-24 07:02:547402 return GetAttribLocationHelper(
7403 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7404}
7405
7406error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7407 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7408 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:577409 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ab09b612013-03-11 22:11:517410 LOCAL_SET_GL_ERROR(
7411 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:577412 return error::kNoError;
7413 }
[email protected]df37b9932013-03-08 05:21:427414 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:587415 client_id, "glUniformLocation");
[email protected]df37b9932013-03-08 05:21:427416 if (!program) {
[email protected]f7a64ee2010-02-01 22:24:147417 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197418 }
[email protected]df37b9932013-03-08 05:21:427419 if (!program->IsValid()) {
[email protected]ab09b612013-03-11 22:11:517420 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437421 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:257422 return error::kNoError;
7423 }
[email protected]b9849abf2009-11-25 19:13:197424 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:547425 location_shm_id, location_shm_offset, sizeof(GLint));
7426 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:147427 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197428 }
[email protected]558847a2010-03-24 07:02:547429 // Require the client to init this incase the context is lost an we are no
7430 // longer executing commands.
7431 if (*location != -1) {
7432 return error::kGenericError;
7433 }
[email protected]df37b9932013-03-08 05:21:427434 *location = program->GetUniformFakeLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:147435 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197436}
7437
[email protected]f7a64ee2010-02-01 22:24:147438error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]ed9f9cd2013-02-27 21:12:357439 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:197440 uint32 name_size = c.data_size;
7441 const char* name = GetSharedMemoryAs<const char*>(
7442 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:547443 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:147444 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197445 }
7446 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:547447 return GetUniformLocationHelper(
7448 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:197449}
7450
[email protected]558847a2010-03-24 07:02:547451error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:357452 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
[email protected]558847a2010-03-24 07:02:547453 Bucket* bucket = GetBucket(c.name_bucket_id);
7454 if (!bucket) {
7455 return error::kInvalidArguments;
7456 }
7457 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:187458 if (!bucket->GetAsString(&name_str)) {
7459 return error::kInvalidArguments;
7460 }
[email protected]558847a2010-03-24 07:02:547461 return GetUniformLocationHelper(
7462 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:197463}
7464
[email protected]ddd968b82010-03-02 00:44:297465error::Error GLES2DecoderImpl::HandleGetString(
[email protected]ed9f9cd2013-02-27 21:12:357466 uint32 immediate_data_size, const cmds::GetString& c) {
[email protected]ddd968b82010-03-02 00:44:297467 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:057468 if (!validators_->string_type.IsValid(name)) {
[email protected]ab09b612013-03-11 22:11:517469 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
[email protected]ddd968b82010-03-02 00:44:297470 return error::kNoError;
7471 }
[email protected]959e9072013-09-20 16:58:387472 const char* str = reinterpret_cast<const char*>(glGetString(name));
[email protected]f0d74742011-10-03 16:31:047473 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:157474 switch (name) {
7475 case GL_VERSION:
7476 str = "OpenGL ES 2.0 Chromium";
7477 break;
7478 case GL_SHADING_LANGUAGE_VERSION:
7479 str = "OpenGL ES GLSL ES 1.0 Chromium";
7480 break;
[email protected]32939602012-05-09 06:25:167481 case GL_RENDERER:
[email protected]32939602012-05-09 06:25:167482 case GL_VENDOR:
[email protected]959e9072013-09-20 16:58:387483 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7484 // They are used by WEBGL_debug_renderer_info.
7485 if (!force_webgl_glsl_validation_)
7486 str = "Chromium";
[email protected]32939602012-05-09 06:25:167487 break;
[email protected]1958e0e2010-04-22 05:17:157488 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:047489 {
[email protected]70dc60932013-06-04 03:33:497490 // For WebGL contexts, strip out the OES derivatives and
7491 // EXT frag depth extensions if they have not been enabled.
7492 if (force_webgl_glsl_validation_) {
[email protected]f0d74742011-10-03 16:31:047493 extensions = feature_info_->extensions();
[email protected]70dc60932013-06-04 03:33:497494 if (!derivatives_explicitly_enabled_) {
7495 size_t offset = extensions.find(kOESDerivativeExtension);
7496 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097497 extensions.replace(offset, arraysize(kOESDerivativeExtension),
[email protected]70dc60932013-06-04 03:33:497498 std::string());
7499 }
7500 }
7501 if (!frag_depth_explicitly_enabled_) {
7502 size_t offset = extensions.find(kEXTFragDepthExtension);
7503 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097504 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
[email protected]70dc60932013-06-04 03:33:497505 std::string());
7506 }
[email protected]f0d74742011-10-03 16:31:047507 }
[email protected]aff39ac82013-06-08 04:53:137508 if (!draw_buffers_explicitly_enabled_) {
7509 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7510 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097511 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
[email protected]aff39ac82013-06-08 04:53:137512 std::string());
7513 }
7514 }
[email protected]f0d74742011-10-03 16:31:047515 } else {
[email protected]6f5fac9d12012-06-26 21:02:457516 extensions = feature_info_->extensions().c_str();
[email protected]f0d74742011-10-03 16:31:047517 }
[email protected]6f5fac9d12012-06-26 21:02:457518 std::string surface_extensions = surface_->GetExtensions();
7519 if (!surface_extensions.empty())
7520 extensions += " " + surface_extensions;
7521 str = extensions.c_str();
[email protected]f0d74742011-10-03 16:31:047522 }
[email protected]1958e0e2010-04-22 05:17:157523 break;
7524 default:
[email protected]1958e0e2010-04-22 05:17:157525 break;
7526 }
[email protected]ddd968b82010-03-02 00:44:297527 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:157528 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:297529 return error::kNoError;
7530}
7531
[email protected]0c86dbf2010-03-05 08:14:117532error::Error GLES2DecoderImpl::HandleBufferData(
[email protected]ed9f9cd2013-02-27 21:12:357533 uint32 immediate_data_size, const cmds::BufferData& c) {
[email protected]0c86dbf2010-03-05 08:14:117534 GLenum target = static_cast<GLenum>(c.target);
7535 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7536 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7537 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7538 GLenum usage = static_cast<GLenum>(c.usage);
7539 const void* data = NULL;
7540 if (data_shm_id != 0 || data_shm_offset != 0) {
7541 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7542 if (!data) {
7543 return error::kOutOfBounds;
7544 }
7545 }
[email protected]0fbba3732013-07-17 15:40:137546 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:147547 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197548}
7549
[email protected]0c86dbf2010-03-05 08:14:117550void GLES2DecoderImpl::DoBufferSubData(
7551 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]0fbba3732013-07-17 15:40:137552 // Just delegate it. Some validation is actually done before this.
7553 buffer_manager()->ValidateAndDoBufferSubData(
7554 &state_, target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:197555}
7556
[email protected]0d6bfdc2011-11-02 01:32:207557bool GLES2DecoderImpl::ClearLevel(
7558 unsigned service_id,
7559 unsigned bind_target,
7560 unsigned target,
7561 int level,
7562 unsigned format,
7563 unsigned type,
7564 int width,
[email protected]4502e6492011-12-14 19:39:157565 int height,
7566 bool is_texture_immutable) {
[email protected]81375742012-06-08 00:04:007567 uint32 channels = GLES2Util::GetChannelsForFormat(format);
[email protected]345ba902013-11-14 21:39:007568 if (feature_info_->feature_flags().angle_depth_texture &&
7569 (channels & GLES2Util::kDepth) != 0) {
[email protected]81375742012-06-08 00:04:007570 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7571 // on depth formats.
7572 GLuint fb = 0;
7573 glGenFramebuffersEXT(1, &fb);
7574 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7575
7576 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7577 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7578 GL_DEPTH_ATTACHMENT;
7579
7580 glFramebufferTexture2DEXT(
7581 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7582 // ANGLE promises a depth only attachment ok.
7583 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7584 GL_FRAMEBUFFER_COMPLETE) {
7585 return false;
7586 }
7587 glClearStencil(0);
7588 glStencilMask(-1);
7589 glClearDepth(1.0f);
7590 glDepthMask(true);
7591 glDisable(GL_SCISSOR_TEST);
7592 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7593
7594 RestoreClearState();
7595
7596 glDeleteFramebuffersEXT(1, &fb);
[email protected]ed9f9cd2013-02-27 21:12:357597 Framebuffer* framebuffer =
[email protected]81375742012-06-08 00:04:007598 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7599 GLuint fb_service_id =
7600 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7601 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7602 return true;
7603 }
7604
[email protected]45d15a62012-04-18 14:33:177605 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7606
7607 uint32 size;
7608 uint32 padded_row_size;
[email protected]3458a64a2012-04-10 17:39:347609 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247610 width, height, format, type, state_.unpack_alignment, &size,
[email protected]45d15a62012-04-18 14:33:177611 NULL, &padded_row_size)) {
[email protected]0d6bfdc2011-11-02 01:32:207612 return false;
7613 }
[email protected]45d15a62012-04-18 14:33:177614
[email protected]a5d3dad2012-05-26 04:34:447615 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7616
[email protected]45d15a62012-04-18 14:33:177617 int tile_height;
7618
7619 if (size > kMaxZeroSize) {
7620 if (kMaxZeroSize < padded_row_size) {
7621 // That'd be an awfully large texture.
7622 return false;
7623 }
7624 // We should never have a large total size with a zero row size.
7625 DCHECK_GT(padded_row_size, 0U);
7626 tile_height = kMaxZeroSize / padded_row_size;
7627 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247628 width, tile_height, format, type, state_.unpack_alignment, &size,
7629 NULL, NULL)) {
[email protected]45d15a62012-04-18 14:33:177630 return false;
7631 }
[email protected]4502e6492011-12-14 19:39:157632 } else {
[email protected]45d15a62012-04-18 14:33:177633 tile_height = height;
7634 }
7635
7636 // Assumes the size has already been checked.
[email protected]40d90a22013-04-09 03:39:557637 scoped_ptr<char[]> zero(new char[size]);
[email protected]45d15a62012-04-18 14:33:177638 memset(zero.get(), 0, size);
7639 glBindTexture(bind_target, service_id);
7640
7641 GLint y = 0;
7642 while (y < height) {
7643 GLint h = y + tile_height > height ? height - y : tile_height;
7644 if (is_texture_immutable || h != height) {
7645 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7646 } else {
[email protected]8f1d2aa2013-05-10 23:45:387647 glTexImage2D(
[email protected]45d15a62012-04-18 14:33:177648 target, level, format, width, h, 0, format, type, zero.get());
7649 }
7650 y += tile_height;
[email protected]4502e6492011-12-14 19:39:157651 }
[email protected]c986af502013-08-14 01:04:447652 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7653 &state_, bind_target);
[email protected]02965c22013-03-09 02:40:077654 glBindTexture(bind_target, texture ? texture->service_id() : 0);
[email protected]0d6bfdc2011-11-02 01:32:207655 return true;
7656}
7657
[email protected]ad84a3a2012-06-08 21:42:437658namespace {
7659
7660const int kS3TCBlockWidth = 4;
7661const int kS3TCBlockHeight = 4;
7662const int kS3TCDXT1BlockSize = 8;
7663const int kS3TCDXT3AndDXT5BlockSize = 16;
[email protected]2d3765b2012-10-03 00:31:077664const int kETC1BlockWidth = 4;
7665const int kETC1BlockHeight = 4;
7666const int kETC1BlockSize = 8;
[email protected]ad84a3a2012-06-08 21:42:437667
7668bool IsValidDXTSize(GLint level, GLsizei size) {
[email protected]10b56de2012-07-14 02:09:517669 return (size == 1) ||
7670 (size == 2) || !(size % kS3TCBlockWidth);
[email protected]ad84a3a2012-06-08 21:42:437671}
7672
7673} // anonymous namespace.
7674
7675bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7676 const char* function_name,
7677 GLsizei width, GLsizei height, GLenum format, size_t size) {
7678 unsigned int bytes_required = 0;
7679
7680 switch (format) {
7681 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7682 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7683 int num_blocks_across =
7684 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7685 int num_blocks_down =
7686 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7687 int num_blocks = num_blocks_across * num_blocks_down;
7688 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7689 break;
7690 }
7691 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7692 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7693 int num_blocks_across =
7694 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7695 int num_blocks_down =
7696 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7697 int num_blocks = num_blocks_across * num_blocks_down;
7698 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7699 break;
7700 }
[email protected]2d3765b2012-10-03 00:31:077701 case GL_ETC1_RGB8_OES: {
7702 int num_blocks_across =
7703 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7704 int num_blocks_down =
7705 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7706 int num_blocks = num_blocks_across * num_blocks_down;
7707 bytes_required = num_blocks * kETC1BlockSize;
7708 break;
7709 }
[email protected]ad84a3a2012-06-08 21:42:437710 default:
[email protected]ab09b612013-03-11 22:11:517711 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
[email protected]ad84a3a2012-06-08 21:42:437712 return false;
7713 }
7714
7715 if (size != bytes_required) {
[email protected]ab09b612013-03-11 22:11:517716 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437717 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7718 return false;
7719 }
7720
7721 return true;
7722}
7723
7724bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7725 const char* function_name,
7726 GLint level, GLsizei width, GLsizei height, GLenum format) {
7727 switch (format) {
7728 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7729 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7730 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7731 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7732 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
[email protected]ab09b612013-03-11 22:11:517733 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437734 GL_INVALID_OPERATION, function_name,
7735 "width or height invalid for level");
7736 return false;
7737 }
7738 return true;
7739 }
[email protected]2d3765b2012-10-03 00:31:077740 case GL_ETC1_RGB8_OES:
7741 if (width <= 0 || height <= 0) {
[email protected]ab09b612013-03-11 22:11:517742 LOCAL_SET_GL_ERROR(
[email protected]2d3765b2012-10-03 00:31:077743 GL_INVALID_OPERATION, function_name,
7744 "width or height invalid for level");
7745 return false;
7746 }
7747 return true;
[email protected]ad84a3a2012-06-08 21:42:437748 default:
7749 return false;
7750 }
7751}
7752
7753bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7754 const char* function_name,
7755 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7756 GLsizei width, GLsizei height, GLenum format,
[email protected]ed9f9cd2013-02-27 21:12:357757 Texture* texture) {
[email protected]ad84a3a2012-06-08 21:42:437758 if (xoffset < 0 || yoffset < 0) {
[email protected]ab09b612013-03-11 22:11:517759 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437760 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7761 return false;
7762 }
7763
7764 switch (format) {
7765 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7766 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7767 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7768 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7769 const int kBlockWidth = 4;
7770 const int kBlockHeight = 4;
7771 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
[email protected]ab09b612013-03-11 22:11:517772 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437773 GL_INVALID_OPERATION, function_name,
7774 "xoffset or yoffset not multiple of 4");
7775 return false;
7776 }
7777 GLsizei tex_width = 0;
7778 GLsizei tex_height = 0;
7779 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7780 width - xoffset > tex_width ||
7781 height - yoffset > tex_height) {
[email protected]ab09b612013-03-11 22:11:517782 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437783 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7784 return false;
7785 }
7786 return ValidateCompressedTexDimensions(
7787 function_name, level, width, height, format);
7788 }
[email protected]2d3765b2012-10-03 00:31:077789 case GL_ETC1_RGB8_OES: {
[email protected]ab09b612013-03-11 22:11:517790 LOCAL_SET_GL_ERROR(
[email protected]2d3765b2012-10-03 00:31:077791 GL_INVALID_OPERATION, function_name,
7792 "TexsubImage2d not supported for ECT1_RGB8_OES textures");
7793 return false;
7794 }
[email protected]ad84a3a2012-06-08 21:42:437795 default:
7796 return false;
7797 }
7798}
7799
[email protected]a93bb842010-02-16 23:03:477800error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7801 GLenum target,
7802 GLint level,
7803 GLenum internal_format,
7804 GLsizei width,
7805 GLsizei height,
7806 GLint border,
7807 GLsizei image_size,
7808 const void* data) {
[email protected]a93bb842010-02-16 23:03:477809 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:057810 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:517811 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7812 "glCompressedTexImage2D", target, "target");
[email protected]8eee29c2010-04-29 03:38:297813 return error::kNoError;
7814 }
[email protected]9438b012010-06-15 22:55:057815 if (!validators_->compressed_texture_format.IsValid(
7816 internal_format)) {
[email protected]ab09b612013-03-11 22:11:517817 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:537818 "glCompressedTexImage2D", internal_format, "internal_format");
[email protected]a93bb842010-02-16 23:03:477819 return error::kNoError;
7820 }
[email protected]80eb6b52012-01-19 00:14:417821 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:477822 border != 0) {
[email protected]ab09b612013-03-11 22:11:517823 LOCAL_SET_GL_ERROR(
7824 GL_INVALID_VALUE,
7825 "glCompressedTexImage2D", "dimensions out of range");
[email protected]a93bb842010-02-16 23:03:477826 return error::kNoError;
7827 }
[email protected]c986af502013-08-14 01:04:447828 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7829 &state_, target);
[email protected]370eaf12013-05-18 09:19:497830 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517831 LOCAL_SET_GL_ERROR(
7832 GL_INVALID_VALUE,
7833 "glCompressedTexImage2D", "unknown texture target");
[email protected]a93bb842010-02-16 23:03:477834 return error::kNoError;
7835 }
[email protected]370eaf12013-05-18 09:19:497836 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:077837 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:517838 LOCAL_SET_GL_ERROR(
7839 GL_INVALID_OPERATION,
7840 "glCompressedTexImage2D", "texture is immutable");
[email protected]ad84a3a2012-06-08 21:42:437841 return error::kNoError;
7842 }
7843
7844 if (!ValidateCompressedTexDimensions(
7845 "glCompressedTexImage2D", level, width, height, internal_format) ||
7846 !ValidateCompressedTexFuncData(
7847 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
[email protected]97dc7cbe2011-12-06 17:26:177848 return error::kNoError;
7849 }
[email protected]968351b2011-12-20 08:26:517850
[email protected]7989c9e2013-01-23 06:39:267851 if (!EnsureGPUMemoryAvailable(image_size)) {
[email protected]ab09b612013-03-11 22:11:517852 LOCAL_SET_GL_ERROR(
7853 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
[email protected]7989c9e2013-01-23 06:39:267854 return error::kNoError;
7855 }
7856
[email protected]02965c22013-03-09 02:40:077857 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:447858 framebuffer_state_.clear_state_dirty = true;
[email protected]968351b2011-12-20 08:26:517859 }
7860
[email protected]40d90a22013-04-09 03:39:557861 scoped_ptr<int8[]> zero;
[email protected]a93bb842010-02-16 23:03:477862 if (!data) {
7863 zero.reset(new int8[image_size]);
7864 memset(zero.get(), 0, image_size);
7865 data = zero.get();
7866 }
[email protected]ab09b612013-03-11 22:11:517867 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
[email protected]a93bb842010-02-16 23:03:477868 glCompressedTexImage2D(
7869 target, level, internal_format, width, height, border, image_size, data);
[email protected]ab09b612013-03-11 22:11:517870 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
[email protected]cadde4a2010-07-31 17:10:437871 if (error == GL_NO_ERROR) {
7872 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:497873 texture_ref, target, level, internal_format,
7874 width, height, 1, border, 0, 0, true);
[email protected]cadde4a2010-07-31 17:10:437875 }
[email protected]a93bb842010-02-16 23:03:477876 return error::kNoError;
7877}
7878
[email protected]f7a64ee2010-02-01 22:24:147879error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]ed9f9cd2013-02-27 21:12:357880 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
[email protected]b9849abf2009-11-25 19:13:197881 GLenum target = static_cast<GLenum>(c.target);
7882 GLint level = static_cast<GLint>(c.level);
7883 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7884 GLsizei width = static_cast<GLsizei>(c.width);
7885 GLsizei height = static_cast<GLsizei>(c.height);
7886 GLint border = static_cast<GLint>(c.border);
7887 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7888 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7889 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7890 const void* data = NULL;
7891 if (data_shm_id != 0 || data_shm_offset != 0) {
7892 data = GetSharedMemoryAs<const void*>(
7893 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:467894 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147895 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197896 }
7897 }
[email protected]a93bb842010-02-16 23:03:477898 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197899 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:197900}
7901
[email protected]b6140d02010-05-17 14:47:167902error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
[email protected]ed9f9cd2013-02-27 21:12:357903 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
[email protected]b6140d02010-05-17 14:47:167904 GLenum target = static_cast<GLenum>(c.target);
7905 GLint level = static_cast<GLint>(c.level);
7906 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7907 GLsizei width = static_cast<GLsizei>(c.width);
7908 GLsizei height = static_cast<GLsizei>(c.height);
7909 GLint border = static_cast<GLint>(c.border);
7910 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287911 if (!bucket) {
7912 return error::kInvalidArguments;
7913 }
7914 uint32 data_size = bucket->size();
7915 GLsizei imageSize = data_size;
7916 const void* data = bucket->GetData(0, data_size);
7917 if (!data) {
7918 return error::kInvalidArguments;
7919 }
[email protected]b6140d02010-05-17 14:47:167920 return DoCompressedTexImage2D(
7921 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:287922 imageSize, data);
[email protected]b6140d02010-05-17 14:47:167923}
7924
7925error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7926 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:357927 const cmds::CompressedTexSubImage2DBucket& c) {
[email protected]b6140d02010-05-17 14:47:167928 GLenum target = static_cast<GLenum>(c.target);
7929 GLint level = static_cast<GLint>(c.level);
7930 GLint xoffset = static_cast<GLint>(c.xoffset);
7931 GLint yoffset = static_cast<GLint>(c.yoffset);
7932 GLsizei width = static_cast<GLsizei>(c.width);
7933 GLsizei height = static_cast<GLsizei>(c.height);
7934 GLenum format = static_cast<GLenum>(c.format);
7935 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287936 if (!bucket) {
7937 return error::kInvalidArguments;
7938 }
[email protected]b6140d02010-05-17 14:47:167939 uint32 data_size = bucket->size();
7940 GLsizei imageSize = data_size;
7941 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:287942 if (!data) {
7943 return error::kInvalidArguments;
7944 }
[email protected]9438b012010-06-15 22:55:057945 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:517946 LOCAL_SET_GL_ERROR(
[email protected]f80e6e12012-08-31 00:43:537947 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
[email protected]b6140d02010-05-17 14:47:167948 return error::kNoError;
7949 }
[email protected]9438b012010-06-15 22:55:057950 if (!validators_->compressed_texture_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:517951 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7952 "glCompressedTexSubImage2D", format, "format");
[email protected]9438b012010-06-15 22:55:057953 return error::kNoError;
7954 }
[email protected]b6140d02010-05-17 14:47:167955 if (width < 0) {
[email protected]ab09b612013-03-11 22:11:517956 LOCAL_SET_GL_ERROR(
7957 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
[email protected]b6140d02010-05-17 14:47:167958 return error::kNoError;
7959 }
7960 if (height < 0) {
[email protected]ab09b612013-03-11 22:11:517961 LOCAL_SET_GL_ERROR(
7962 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
[email protected]b6140d02010-05-17 14:47:167963 return error::kNoError;
7964 }
7965 if (imageSize < 0) {
[email protected]ab09b612013-03-11 22:11:517966 LOCAL_SET_GL_ERROR(
7967 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
[email protected]b6140d02010-05-17 14:47:167968 return error::kNoError;
7969 }
[email protected]cadde4a2010-07-31 17:10:437970 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:167971 target, level, xoffset, yoffset, width, height, format, imageSize, data);
7972 return error::kNoError;
7973}
7974
[email protected]f7a64ee2010-02-01 22:24:147975error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]ed9f9cd2013-02-27 21:12:357976 uint32 immediate_data_size, const cmds::TexImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:387977 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]c986af502013-08-14 01:04:447978 // Set as failed for now, but if it successed, this will be set to not failed.
7979 texture_state_.tex_image_2d_failed = true;
[email protected]b9849abf2009-11-25 19:13:197980 GLenum target = static_cast<GLenum>(c.target);
7981 GLint level = static_cast<GLint>(c.level);
[email protected]c986af502013-08-14 01:04:447982 // TODO(kloveless): Change TexImage2D command to use unsigned integer
7983 // for internalformat.
7984 GLenum internal_format = static_cast<GLenum>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:197985 GLsizei width = static_cast<GLsizei>(c.width);
7986 GLsizei height = static_cast<GLsizei>(c.height);
7987 GLint border = static_cast<GLint>(c.border);
7988 GLenum format = static_cast<GLenum>(c.format);
7989 GLenum type = static_cast<GLenum>(c.type);
7990 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
7991 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:187992 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:347993 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247994 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
[email protected]3458a64a2012-04-10 17:39:347995 NULL)) {
[email protected]a76b0052010-03-05 00:33:187996 return error::kOutOfBounds;
7997 }
[email protected]b9849abf2009-11-25 19:13:197998 const void* pixels = NULL;
7999 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8000 pixels = GetSharedMemoryAs<const void*>(
8001 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:468002 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:148003 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:198004 }
8005 }
[email protected]f598f422012-12-07 08:30:038006
[email protected]c986af502013-08-14 01:04:448007 TextureManager::DoTextImage2DArguments args = {
8008 target, level, internal_format, width, height, border, format, type,
8009 pixels, pixels_size};
8010 texture_manager()->ValidateAndDoTexImage2D(
8011 &texture_state_, &state_, &framebuffer_state_, args);
[email protected]f598f422012-12-07 08:30:038012 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:198013}
8014
[email protected]cadde4a2010-07-31 17:10:438015void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8016 GLenum target,
8017 GLint level,
8018 GLint xoffset,
8019 GLint yoffset,
8020 GLsizei width,
8021 GLsizei height,
8022 GLenum format,
8023 GLsizei image_size,
8024 const void * data) {
[email protected]c986af502013-08-14 01:04:448025 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8026 &state_, target);
[email protected]370eaf12013-05-18 09:19:498027 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:518028 LOCAL_SET_GL_ERROR(
8029 GL_INVALID_OPERATION,
8030 "glCompressedTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:438031 return;
8032 }
[email protected]370eaf12013-05-18 09:19:498033 Texture* texture = texture_ref->texture();
[email protected]cadde4a2010-07-31 17:10:438034 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:528035 GLenum internal_format = 0;
[email protected]02965c22013-03-09 02:40:078036 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
[email protected]ab09b612013-03-11 22:11:518037 LOCAL_SET_GL_ERROR(
[email protected]df6cf1ad2011-01-29 01:20:528038 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438039 "glCompressedTexSubImage2D", "level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:528040 return;
8041 }
8042 if (internal_format != format) {
[email protected]ab09b612013-03-11 22:11:518043 LOCAL_SET_GL_ERROR(
[email protected]df6cf1ad2011-01-29 01:20:528044 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438045 "glCompressedTexSubImage2D", "format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:528046 return;
8047 }
[email protected]02965c22013-03-09 02:40:078048 if (!texture->ValidForTexture(
[email protected]df6cf1ad2011-01-29 01:20:528049 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:518050 LOCAL_SET_GL_ERROR(
8051 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:438052 return;
8053 }
[email protected]ad84a3a2012-06-08 21:42:438054
8055 if (!ValidateCompressedTexFuncData(
8056 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8057 !ValidateCompressedTexSubDimensions(
8058 "glCompressedTexSubImage2D",
[email protected]02965c22013-03-09 02:40:078059 target, level, xoffset, yoffset, width, height, format, texture)) {
[email protected]ad84a3a2012-06-08 21:42:438060 return;
8061 }
8062
8063
[email protected]0d6bfdc2011-11-02 01:32:208064 // Note: There is no need to deal with texture cleared tracking here
8065 // because the validation above means you can only get here if the level
8066 // is already a matching compressed format and in that case
8067 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:438068 glCompressedTexSubImage2D(
8069 target, level, xoffset, yoffset, width, height, format, image_size, data);
8070}
8071
[email protected]6e288612010-12-21 20:45:038072static void Clip(
8073 GLint start, GLint range, GLint sourceRange,
8074 GLint* out_start, GLint* out_range) {
8075 DCHECK(out_start);
8076 DCHECK(out_range);
8077 if (start < 0) {
8078 range += start;
8079 start = 0;
8080 }
8081 GLint end = start + range;
8082 if (end > sourceRange) {
8083 range -= end - sourceRange;
8084 }
8085 *out_start = start;
8086 *out_range = range;
8087}
8088
[email protected]cadde4a2010-07-31 17:10:438089void GLES2DecoderImpl::DoCopyTexImage2D(
[email protected]a5d3dad2012-05-26 04:34:448090 GLenum target,
8091 GLint level,
8092 GLenum internal_format,
8093 GLint x,
8094 GLint y,
8095 GLsizei width,
8096 GLsizei height,
8097 GLint border) {
[email protected]09e17272012-11-30 10:30:448098 DCHECK(!ShouldDeferReads());
[email protected]c986af502013-08-14 01:04:448099 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8100 &state_, target);
[email protected]370eaf12013-05-18 09:19:498101 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:518102 LOCAL_SET_GL_ERROR(
8103 GL_INVALID_OPERATION,
8104 "glCopyTexImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:438105 return;
8106 }
[email protected]370eaf12013-05-18 09:19:498107 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:078108 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:518109 LOCAL_SET_GL_ERROR(
8110 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:178111 }
[email protected]80eb6b52012-01-19 00:14:418112 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:188113 border != 0) {
[email protected]ab09b612013-03-11 22:11:518114 LOCAL_SET_GL_ERROR(
8115 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
[email protected]f5719fb2010-08-04 18:27:188116 return;
8117 }
[email protected]c986af502013-08-14 01:04:448118 if (!texture_manager()->ValidateTextureParameters(
8119 state_.GetErrorState(), "glCopyTexImage2D", target, internal_format,
8120 GL_UNSIGNED_BYTE, level)) {
[email protected]81375742012-06-08 00:04:008121 return;
8122 }
[email protected]f5719fb2010-08-04 18:27:188123
[email protected]9edc6b22010-12-23 02:00:268124 // Check we have compatible formats.
8125 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8126 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8127 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8128
8129 if ((channels_needed & channels_exist) != channels_needed) {
[email protected]ab09b612013-03-11 22:11:518130 LOCAL_SET_GL_ERROR(
8131 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:268132 return;
8133 }
8134
[email protected]81375742012-06-08 00:04:008135 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:518136 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:008137 GL_INVALID_OPERATION,
[email protected]7989c9e2013-01-23 06:39:268138 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8139 return;
8140 }
8141
8142 uint32 estimated_size = 0;
8143 if (!GLES2Util::ComputeImageDataSizes(
8144 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8145 &estimated_size, NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:518146 LOCAL_SET_GL_ERROR(
8147 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:268148 return;
8149 }
8150
8151 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:518152 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
[email protected]81375742012-06-08 00:04:008153 return;
8154 }
8155
[email protected]a0b78dc2011-11-11 10:43:108156 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8157 return;
8158 }
8159
[email protected]ab09b612013-03-11 22:11:518160 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
[email protected]de26b3c2011-08-03 21:54:278161 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:038162 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:268163
[email protected]02965c22013-03-09 02:40:078164 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:448165 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:468166 }
8167
[email protected]9edc6b22010-12-23 02:00:268168 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:038169 GLint copyX = 0;
8170 GLint copyY = 0;
8171 GLint copyWidth = 0;
8172 GLint copyHeight = 0;
8173 Clip(x, width, size.width(), &copyX, &copyWidth);
8174 Clip(y, height, size.height(), &copyY, &copyHeight);
8175
8176 if (copyX != x ||
8177 copyY != y ||
8178 copyWidth != width ||
8179 copyHeight != height) {
8180 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:208181 if (!ClearLevel(
[email protected]02965c22013-03-09 02:40:078182 texture->service_id(), texture->target(),
[email protected]4502e6492011-12-14 19:39:158183 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
[email protected]02965c22013-03-09 02:40:078184 texture->IsImmutable())) {
[email protected]ab09b612013-03-11 22:11:518185 LOCAL_SET_GL_ERROR(
8186 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
[email protected]6e288612010-12-21 20:45:038187 return;
8188 }
[email protected]6e288612010-12-21 20:45:038189 if (copyHeight > 0 && copyWidth > 0) {
8190 GLint dx = copyX - x;
8191 GLint dy = copyY - y;
8192 GLint destX = dx;
8193 GLint destY = dy;
8194 glCopyTexSubImage2D(target, level,
8195 destX, destY, copyX, copyY,
8196 copyWidth, copyHeight);
8197 }
8198 } else {
8199 glCopyTexImage2D(target, level, internal_format,
8200 copyX, copyY, copyWidth, copyHeight, border);
8201 }
[email protected]ab09b612013-03-11 22:11:518202 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
[email protected]cadde4a2010-07-31 17:10:438203 if (error == GL_NO_ERROR) {
8204 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:498205 texture_ref, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:208206 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:438207 }
8208}
8209
8210void GLES2DecoderImpl::DoCopyTexSubImage2D(
[email protected]a5d3dad2012-05-26 04:34:448211 GLenum target,
8212 GLint level,
8213 GLint xoffset,
8214 GLint yoffset,
8215 GLint x,
8216 GLint y,
8217 GLsizei width,
8218 GLsizei height) {
[email protected]09e17272012-11-30 10:30:448219 DCHECK(!ShouldDeferReads());
[email protected]c986af502013-08-14 01:04:448220 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8221 &state_, target);
[email protected]370eaf12013-05-18 09:19:498222 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:518223 LOCAL_SET_GL_ERROR(
8224 GL_INVALID_OPERATION,
8225 "glCopyTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:438226 return;
8227 }
[email protected]370eaf12013-05-18 09:19:498228 Texture* texture = texture_ref->texture();
[email protected]cadde4a2010-07-31 17:10:438229 GLenum type = 0;
8230 GLenum format = 0;
[email protected]02965c22013-03-09 02:40:078231 if (!texture->GetLevelType(target, level, &type, &format) ||
8232 !texture->ValidForTexture(
[email protected]cadde4a2010-07-31 17:10:438233 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:518234 LOCAL_SET_GL_ERROR(
8235 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:438236 return;
8237 }
[email protected]85a4ac22013-05-31 01:58:478238 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:518239 LOCAL_SET_GL_ERROR(
8240 GL_INVALID_OPERATION,
8241 "glCopyTexSubImage2D", "async upload pending for texture");
[email protected]32145a92012-12-17 09:01:598242 return;
8243 }
[email protected]9edc6b22010-12-23 02:00:268244
8245 // Check we have compatible formats.
8246 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8247 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8248 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8249
[email protected]2d3765b2012-10-03 00:31:078250 if (!channels_needed ||
8251 (channels_needed & channels_exist) != channels_needed) {
[email protected]ab09b612013-03-11 22:11:518252 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:438253 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:268254 return;
8255 }
8256
[email protected]81375742012-06-08 00:04:008257 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:518258 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:008259 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438260 "glCopySubImage2D", "can not be used with depth or stencil textures");
[email protected]81375742012-06-08 00:04:008261 return;
8262 }
8263
[email protected]a0b78dc2011-11-11 10:43:108264 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8265 return;
8266 }
8267
[email protected]de26b3c2011-08-03 21:54:278268 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:038269 gfx::Size size = GetBoundReadFrameBufferSize();
8270 GLint copyX = 0;
8271 GLint copyY = 0;
8272 GLint copyWidth = 0;
8273 GLint copyHeight = 0;
8274 Clip(x, width, size.width(), &copyX, &copyWidth);
8275 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:208276
[email protected]370eaf12013-05-18 09:19:498277 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
[email protected]ab09b612013-03-11 22:11:518278 LOCAL_SET_GL_ERROR(
8279 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
[email protected]0d6bfdc2011-11-02 01:32:208280 return;
8281 }
8282
[email protected]6e288612010-12-21 20:45:038283 if (copyX != x ||
8284 copyY != y ||
8285 copyWidth != width ||
8286 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:208287 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:038288 uint32 pixels_size = 0;
[email protected]3458a64a2012-04-10 17:39:348289 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:248290 width, height, format, type, state_.unpack_alignment, &pixels_size,
8291 NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:518292 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:438293 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
[email protected]6e288612010-12-21 20:45:038294 return;
8295 }
[email protected]40d90a22013-04-09 03:39:558296 scoped_ptr<char[]> zero(new char[pixels_size]);
[email protected]6e288612010-12-21 20:45:038297 memset(zero.get(), 0, pixels_size);
8298 glTexSubImage2D(
8299 target, level, xoffset, yoffset, width, height,
8300 format, type, zero.get());
8301 }
[email protected]0d6bfdc2011-11-02 01:32:208302
[email protected]6e288612010-12-21 20:45:038303 if (copyHeight > 0 && copyWidth > 0) {
8304 GLint dx = copyX - x;
8305 GLint dy = copyY - y;
8306 GLint destX = xoffset + dx;
8307 GLint destY = yoffset + dy;
8308 glCopyTexSubImage2D(target, level,
8309 destX, destY, copyX, copyY,
8310 copyWidth, copyHeight);
8311 }
[email protected]cadde4a2010-07-31 17:10:438312}
8313
[email protected]f598f422012-12-07 08:30:038314bool GLES2DecoderImpl::ValidateTexSubImage2D(
8315 error::Error* error,
8316 const char* function_name,
8317 GLenum target,
8318 GLint level,
8319 GLint xoffset,
8320 GLint yoffset,
8321 GLsizei width,
8322 GLsizei height,
8323 GLenum format,
8324 GLenum type,
8325 const void * data) {
8326 (*error) = error::kNoError;
8327 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:518328 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
[email protected]f598f422012-12-07 08:30:038329 return false;
8330 }
8331 if (width < 0) {
[email protected]ab09b612013-03-11 22:11:518332 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
[email protected]f598f422012-12-07 08:30:038333 return false;
8334 }
8335 if (height < 0) {
[email protected]ab09b612013-03-11 22:11:518336 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
[email protected]f598f422012-12-07 08:30:038337 return false;
8338 }
8339 if (!validators_->texture_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:518340 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
[email protected]f598f422012-12-07 08:30:038341 return false;
8342 }
8343 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:518344 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
[email protected]f598f422012-12-07 08:30:038345 return false;
8346 }
[email protected]c986af502013-08-14 01:04:448347 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8348 &state_, target);
[email protected]370eaf12013-05-18 09:19:498349 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:518350 LOCAL_SET_GL_ERROR(
8351 GL_INVALID_OPERATION,
8352 function_name, "unknown texture for target");
[email protected]f598f422012-12-07 08:30:038353 return false;
[email protected]cadde4a2010-07-31 17:10:438354 }
[email protected]370eaf12013-05-18 09:19:498355 Texture* texture = texture_ref->texture();
[email protected]df6cf1ad2011-01-29 01:20:528356 GLenum current_type = 0;
8357 GLenum internal_format = 0;
[email protected]02965c22013-03-09 02:40:078358 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
[email protected]ab09b612013-03-11 22:11:518359 LOCAL_SET_GL_ERROR(
[email protected]f598f422012-12-07 08:30:038360 GL_INVALID_OPERATION, function_name, "level does not exist.");
8361 return false;
[email protected]df6cf1ad2011-01-29 01:20:528362 }
8363 if (format != internal_format) {
[email protected]ab09b612013-03-11 22:11:518364 LOCAL_SET_GL_ERROR(
8365 GL_INVALID_OPERATION,
8366 function_name, "format does not match internal format.");
[email protected]f598f422012-12-07 08:30:038367 return false;
[email protected]df6cf1ad2011-01-29 01:20:528368 }
8369 if (type != current_type) {
[email protected]ab09b612013-03-11 22:11:518370 LOCAL_SET_GL_ERROR(
8371 GL_INVALID_OPERATION,
8372 function_name, "type does not match type of texture.");
[email protected]f598f422012-12-07 08:30:038373 return false;
[email protected]df6cf1ad2011-01-29 01:20:528374 }
[email protected]85a4ac22013-05-31 01:58:478375 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:518376 LOCAL_SET_GL_ERROR(
8377 GL_INVALID_OPERATION,
8378 function_name, "async upload pending for texture");
[email protected]32145a92012-12-17 09:01:598379 return false;
8380 }
[email protected]02965c22013-03-09 02:40:078381 if (!texture->ValidForTexture(
[email protected]cadde4a2010-07-31 17:10:438382 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:518383 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
[email protected]f598f422012-12-07 08:30:038384 return false;
[email protected]cadde4a2010-07-31 17:10:438385 }
[email protected]81375742012-06-08 00:04:008386 if ((GLES2Util::GetChannelsForFormat(format) &
8387 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:518388 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:008389 GL_INVALID_OPERATION,
[email protected]f598f422012-12-07 08:30:038390 function_name, "can not supply data for depth or stencil textures");
8391 return false;
[email protected]81375742012-06-08 00:04:008392 }
[email protected]f598f422012-12-07 08:30:038393 if (data == NULL) {
8394 (*error) = error::kOutOfBounds;
8395 return false;
8396 }
8397 return true;
8398}
[email protected]81375742012-06-08 00:04:008399
[email protected]f598f422012-12-07 08:30:038400error::Error GLES2DecoderImpl::DoTexSubImage2D(
8401 GLenum target,
8402 GLint level,
8403 GLint xoffset,
8404 GLint yoffset,
8405 GLsizei width,
8406 GLsizei height,
8407 GLenum format,
8408 GLenum type,
8409 const void * data) {
8410 error::Error error = error::kNoError;
8411 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8412 xoffset, yoffset, width, height, format, type, data)) {
8413 return error;
8414 }
[email protected]c986af502013-08-14 01:04:448415 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8416 &state_, target);
[email protected]370eaf12013-05-18 09:19:498417 Texture* texture = texture_ref->texture();
[email protected]4502e6492011-12-14 19:39:158418 GLsizei tex_width = 0;
8419 GLsizei tex_height = 0;
[email protected]02965c22013-03-09 02:40:078420 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
[email protected]4502e6492011-12-14 19:39:158421 DCHECK(ok);
8422 if (xoffset != 0 || yoffset != 0 ||
8423 width != tex_width || height != tex_height) {
[email protected]370eaf12013-05-18 09:19:498424 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8425 target, level)) {
[email protected]ab09b612013-03-11 22:11:518426 LOCAL_SET_GL_ERROR(
8427 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
[email protected]f598f422012-12-07 08:30:038428 return error::kNoError;
[email protected]473c01ccb2011-06-07 01:33:308429 }
[email protected]c986af502013-08-14 01:04:448430 ScopedTextureUploadTimer timer(&texture_state_);
[email protected]4502e6492011-12-14 19:39:158431 glTexSubImage2D(
8432 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]f598f422012-12-07 08:30:038433 return error::kNoError;
[email protected]0d6bfdc2011-11-02 01:32:208434 }
[email protected]4502e6492011-12-14 19:39:158435
[email protected]345ba902013-11-14 21:39:008436 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
[email protected]c986af502013-08-14 01:04:448437 !texture->IsImmutable()) {
8438 ScopedTextureUploadTimer timer(&texture_state_);
[email protected]4502e6492011-12-14 19:39:158439 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
8440 // same as internal_foramt. If that changes we'll need to look them up.
[email protected]8f1d2aa2013-05-10 23:45:388441 glTexImage2D(
[email protected]4502e6492011-12-14 19:39:158442 target, level, format, width, height, 0, format, type, data);
8443 } else {
[email protected]c986af502013-08-14 01:04:448444 ScopedTextureUploadTimer timer(&texture_state_);
[email protected]4502e6492011-12-14 19:39:158445 glTexSubImage2D(
8446 target, level, xoffset, yoffset, width, height, format, type, data);
8447 }
[email protected]370eaf12013-05-18 09:19:498448 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
[email protected]f598f422012-12-07 08:30:038449 return error::kNoError;
[email protected]cadde4a2010-07-31 17:10:438450}
8451
[email protected]b493ee622011-04-13 23:52:008452error::Error GLES2DecoderImpl::HandleTexSubImage2D(
[email protected]ed9f9cd2013-02-27 21:12:358453 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:388454 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:008455 GLboolean internal = static_cast<GLboolean>(c.internal);
[email protected]c986af502013-08-14 01:04:448456 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
[email protected]b493ee622011-04-13 23:52:008457 return error::kNoError;
8458
8459 GLenum target = static_cast<GLenum>(c.target);
8460 GLint level = static_cast<GLint>(c.level);
8461 GLint xoffset = static_cast<GLint>(c.xoffset);
8462 GLint yoffset = static_cast<GLint>(c.yoffset);
8463 GLsizei width = static_cast<GLsizei>(c.width);
8464 GLsizei height = static_cast<GLsizei>(c.height);
8465 GLenum format = static_cast<GLenum>(c.format);
8466 GLenum type = static_cast<GLenum>(c.type);
8467 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:348468 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:248469 width, height, format, type, state_.unpack_alignment, &data_size,
8470 NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:008471 return error::kOutOfBounds;
8472 }
8473 const void* pixels = GetSharedMemoryAs<const void*>(
8474 c.pixels_shm_id, c.pixels_shm_offset, data_size);
[email protected]f598f422012-12-07 08:30:038475 return DoTexSubImage2D(
[email protected]b493ee622011-04-13 23:52:008476 target, level, xoffset, yoffset, width, height, format, type, pixels);
[email protected]b493ee622011-04-13 23:52:008477}
8478
[email protected]f7a64ee2010-02-01 22:24:148479error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]ed9f9cd2013-02-27 21:12:358480 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:368481 GLuint index = static_cast<GLuint>(c.index);
8482 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]ed9f9cd2013-02-27 21:12:358483 typedef cmds::GetVertexAttribPointerv::Result Result;
[email protected]0bfd9882010-02-05 23:02:258484 Result* result = GetSharedMemoryAs<Result*>(
8485 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:368486 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:148487 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:368488 }
[email protected]07d0cc82010-02-17 04:51:408489 // Check that the client initialized the result.
8490 if (result->size != 0) {
8491 return error::kInvalidArguments;
8492 }
[email protected]9438b012010-06-15 22:55:058493 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]ab09b612013-03-11 22:11:518494 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8495 "glGetVertexAttribPointerv", pname, "pname");
[email protected]f7a64ee2010-02-01 22:24:148496 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:368497 }
[email protected]3916c97e2010-02-25 03:20:508498 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:518499 LOCAL_SET_GL_ERROR(
8500 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
[email protected]f7a64ee2010-02-01 22:24:148501 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:368502 }
[email protected]0bfd9882010-02-05 23:02:258503 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:088504 *result->GetData() =
[email protected]ed9f9cd2013-02-27 21:12:358505 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:148506 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328507}
8508
[email protected]f7b85372010-02-03 01:11:378509bool GLES2DecoderImpl::GetUniformSetup(
[email protected]df37b9932013-03-08 05:21:428510 GLuint program_id, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:378511 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:128512 error::Error* error, GLint* real_location,
8513 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:108514 DCHECK(error);
8515 DCHECK(service_id);
8516 DCHECK(result_pointer);
8517 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:128518 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:378519 *error = error::kNoError;
8520 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:258521 SizedResult<GLint>* result;
8522 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8523 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8524 if (!result) {
[email protected]f7b85372010-02-03 01:11:378525 *error = error::kOutOfBounds;
8526 return false;
8527 }
[email protected]0bfd9882010-02-05 23:02:258528 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:378529 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:258530 result->SetNumResults(0);
[email protected]df37b9932013-03-08 05:21:428531 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8532 if (!program) {
[email protected]ae51d192010-04-27 00:48:038533 return false;
8534 }
[email protected]df37b9932013-03-08 05:21:428535 if (!program->IsValid()) {
[email protected]f7b85372010-02-03 01:11:378536 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ab09b612013-03-11 22:11:518537 LOCAL_SET_GL_ERROR(
8538 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
[email protected]f7b85372010-02-03 01:11:378539 return false;
8540 }
[email protected]df37b9932013-03-08 05:21:428541 *service_id = program->service_id();
[email protected]43c2f1f2011-03-25 18:35:368542 GLint array_index = -1;
[email protected]ed9f9cd2013-02-27 21:12:358543 const Program::UniformInfo* uniform_info =
[email protected]df37b9932013-03-08 05:21:428544 program->GetUniformInfoByFakeLocation(
[email protected]1b0a6752012-02-22 03:44:128545 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:368546 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:378547 // No such location.
[email protected]ab09b612013-03-11 22:11:518548 LOCAL_SET_GL_ERROR(
8549 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
[email protected]f7b85372010-02-03 01:11:378550 return false;
8551 }
[email protected]43c2f1f2011-03-25 18:35:368552 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:508553 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:378554 if (size == 0) {
[email protected]ab09b612013-03-11 22:11:518555 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
[email protected]f7b85372010-02-03 01:11:378556 return false;
8557 }
[email protected]0bfd9882010-02-05 23:02:258558 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8559 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8560 if (!result) {
[email protected]f7b85372010-02-03 01:11:378561 *error = error::kOutOfBounds;
8562 return false;
8563 }
[email protected]0bfd9882010-02-05 23:02:258564 result->size = size;
[email protected]939e7362010-05-13 20:49:108565 *result_type = type;
[email protected]f7b85372010-02-03 01:11:378566 return true;
8567}
8568
[email protected]f7a64ee2010-02-01 22:24:148569error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]ed9f9cd2013-02-27 21:12:358570 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:378571 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:338572 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:378573 GLuint service_id;
[email protected]939e7362010-05-13 20:49:108574 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:128575 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:378576 Error error;
[email protected]0bfd9882010-02-05 23:02:258577 void* result;
[email protected]f7b85372010-02-03 01:11:378578 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:128579 program, fake_location, c.params_shm_id, c.params_shm_offset,
8580 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:258581 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:128582 service_id, real_location,
[email protected]ed9f9cd2013-02-27 21:12:358583 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
[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::HandleGetUniformfv(
[email protected]ed9f9cd2013-02-27 21:12:358589 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:378590 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:338591 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:378592 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:128593 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:378594 Error error;
[email protected]ed9f9cd2013-02-27 21:12:358595 typedef cmds::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:108596 Result* result;
8597 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:378598 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:128599 program, fake_location, c.params_shm_id, c.params_shm_offset,
8600 &error, &real_location, &service_id,
8601 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:108602 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8603 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8604 GLsizei num_values = result->GetNumResults();
[email protected]40d90a22013-04-09 03:39:558605 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:128606 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:108607 GLfloat* dst = result->GetData();
8608 for (GLsizei ii = 0; ii < num_values; ++ii) {
8609 dst[ii] = (temp[ii] != 0);
8610 }
8611 } else {
[email protected]1b0a6752012-02-22 03:44:128612 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:108613 }
[email protected]f7b85372010-02-03 01:11:378614 }
8615 return error;
[email protected]96449d2c2009-11-25 00:01:328616}
8617
[email protected]f7a64ee2010-02-01 22:24:148618error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]ed9f9cd2013-02-27 21:12:358619 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:258620 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8621 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
[email protected]ed9f9cd2013-02-27 21:12:358622 typedef cmds::GetShaderPrecisionFormat::Result Result;
[email protected]0bfd9882010-02-05 23:02:258623 Result* result = GetSharedMemoryAs<Result*>(
8624 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8625 if (!result) {
8626 return error::kOutOfBounds;
8627 }
[email protected]07d0cc82010-02-17 04:51:408628 // Check that the client initialized the result.
8629 if (result->success != 0) {
8630 return error::kInvalidArguments;
8631 }
[email protected]9438b012010-06-15 22:55:058632 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]ab09b612013-03-11 22:11:518633 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:538634 "glGetShaderPrecisionFormat", shader_type, "shader_type");
[email protected]8eee29c2010-04-29 03:38:298635 return error::kNoError;
8636 }
[email protected]9438b012010-06-15 22:55:058637 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]ab09b612013-03-11 22:11:518638 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:538639 "glGetShaderPrecisionFormat", precision_type, "precision_type");
[email protected]8eee29c2010-04-29 03:38:298640 return error::kNoError;
8641 }
8642
8643 result->success = 1; // true
[email protected]d8bc3ec2013-03-07 06:28:408644
[email protected]46c86752013-05-21 05:08:398645 GLint range[2] = { 0, 0 };
[email protected]d8bc3ec2013-03-07 06:28:408646 GLint precision = 0;
[email protected]8dc1bf92013-03-12 03:58:218647 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
[email protected]d8bc3ec2013-03-07 06:28:408648
8649 result->min_range = range[0];
8650 result->max_range = range[1];
8651 result->precision = precision;
8652
[email protected]f7a64ee2010-02-01 22:24:148653 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328654}
8655
[email protected]f7a64ee2010-02-01 22:24:148656error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]ed9f9cd2013-02-27 21:12:358657 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:258658 uint32 result_size = c.result_size;
[email protected]df37b9932013-03-08 05:21:428659 GLuint program_id = static_cast<GLuint>(c.program);
8660 Program* program = GetProgramInfoNotShader(
8661 program_id, "glGetAttachedShaders");
8662 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258663 return error::kNoError;
8664 }
[email protected]ed9f9cd2013-02-27 21:12:358665 typedef cmds::GetAttachedShaders::Result Result;
[email protected]0bfd9882010-02-05 23:02:258666 uint32 max_count = Result::ComputeMaxResults(result_size);
8667 Result* result = GetSharedMemoryAs<Result*>(
8668 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8669 if (!result) {
8670 return error::kOutOfBounds;
8671 }
[email protected]07d0cc82010-02-17 04:51:408672 // Check that the client initialized the result.
8673 if (result->size != 0) {
8674 return error::kInvalidArguments;
8675 }
[email protected]0bfd9882010-02-05 23:02:258676 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:038677 glGetAttachedShaders(
[email protected]df37b9932013-03-08 05:21:428678 program->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:258679 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:038680 if (!shader_manager()->GetClientId(result->GetData()[ii],
8681 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:258682 NOTREACHED();
8683 return error::kGenericError;
8684 }
8685 }
8686 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:148687 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328688}
8689
[email protected]f7a64ee2010-02-01 22:24:148690error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]ed9f9cd2013-02-27 21:12:358691 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
[email protected]df37b9932013-03-08 05:21:428692 GLuint program_id = c.program;
[email protected]0bfd9882010-02-05 23:02:258693 GLuint index = c.index;
8694 uint32 name_bucket_id = c.name_bucket_id;
[email protected]ed9f9cd2013-02-27 21:12:358695 typedef cmds::GetActiveUniform::Result Result;
[email protected]0bfd9882010-02-05 23:02:258696 Result* result = GetSharedMemoryAs<Result*>(
8697 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8698 if (!result) {
8699 return error::kOutOfBounds;
8700 }
[email protected]07d0cc82010-02-17 04:51:408701 // Check that the client initialized the result.
8702 if (result->success != 0) {
8703 return error::kInvalidArguments;
8704 }
[email protected]df37b9932013-03-08 05:21:428705 Program* program = GetProgramInfoNotShader(
8706 program_id, "glGetActiveUniform");
8707 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258708 return error::kNoError;
8709 }
[email protected]ed9f9cd2013-02-27 21:12:358710 const Program::UniformInfo* uniform_info =
[email protected]df37b9932013-03-08 05:21:428711 program->GetUniformInfo(index);
[email protected]0bfd9882010-02-05 23:02:258712 if (!uniform_info) {
[email protected]ab09b612013-03-11 22:11:518713 LOCAL_SET_GL_ERROR(
8714 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258715 return error::kNoError;
8716 }
8717 result->success = 1; // true.
8718 result->size = uniform_info->size;
8719 result->type = uniform_info->type;
8720 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298721 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148722 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328723}
8724
[email protected]f7a64ee2010-02-01 22:24:148725error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]ed9f9cd2013-02-27 21:12:358726 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
[email protected]df37b9932013-03-08 05:21:428727 GLuint program_id = c.program;
[email protected]0bfd9882010-02-05 23:02:258728 GLuint index = c.index;
8729 uint32 name_bucket_id = c.name_bucket_id;
[email protected]ed9f9cd2013-02-27 21:12:358730 typedef cmds::GetActiveAttrib::Result Result;
[email protected]0bfd9882010-02-05 23:02:258731 Result* result = GetSharedMemoryAs<Result*>(
8732 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8733 if (!result) {
8734 return error::kOutOfBounds;
8735 }
[email protected]07d0cc82010-02-17 04:51:408736 // Check that the client initialized the result.
8737 if (result->success != 0) {
8738 return error::kInvalidArguments;
8739 }
[email protected]df37b9932013-03-08 05:21:428740 Program* program = GetProgramInfoNotShader(
8741 program_id, "glGetActiveAttrib");
8742 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258743 return error::kNoError;
8744 }
[email protected]ed9f9cd2013-02-27 21:12:358745 const Program::VertexAttrib* attrib_info =
[email protected]df37b9932013-03-08 05:21:428746 program->GetAttribInfo(index);
[email protected]0bfd9882010-02-05 23:02:258747 if (!attrib_info) {
[email protected]ab09b612013-03-11 22:11:518748 LOCAL_SET_GL_ERROR(
8749 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258750 return error::kNoError;
8751 }
8752 result->success = 1; // true.
8753 result->size = attrib_info->size;
8754 result->type = attrib_info->type;
8755 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298756 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148757 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328758}
8759
[email protected]b273e432010-04-12 17:23:588760error::Error GLES2DecoderImpl::HandleShaderBinary(
[email protected]ed9f9cd2013-02-27 21:12:358761 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
[email protected]b273e432010-04-12 17:23:588762#if 1 // No binary shader support.
[email protected]ab09b612013-03-11 22:11:518763 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
[email protected]b273e432010-04-12 17:23:588764 return error::kNoError;
8765#else
8766 GLsizei n = static_cast<GLsizei>(c.n);
8767 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:518768 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
[email protected]b273e432010-04-12 17:23:588769 return error::kNoError;
8770 }
8771 GLsizei length = static_cast<GLsizei>(c.length);
8772 if (length < 0) {
[email protected]ab09b612013-03-11 22:11:518773 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
[email protected]b273e432010-04-12 17:23:588774 return error::kNoError;
8775 }
8776 uint32 data_size;
8777 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8778 return error::kOutOfBounds;
8779 }
8780 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8781 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8782 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8783 const void* binary = GetSharedMemoryAs<const void*>(
8784 c.binary_shm_id, c.binary_shm_offset, length);
8785 if (shaders == NULL || binary == NULL) {
8786 return error::kOutOfBounds;
8787 }
8788 scoped_array<GLuint> service_ids(new GLuint[n]);
8789 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]df37b9932013-03-08 05:21:428790 Shader* shader = GetShader(shaders[ii]);
8791 if (!shader) {
[email protected]ab09b612013-03-11 22:11:518792 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
[email protected]b273e432010-04-12 17:23:588793 return error::kNoError;
8794 }
[email protected]df37b9932013-03-08 05:21:428795 service_ids[ii] = shader->service_id();
[email protected]b273e432010-04-12 17:23:588796 }
8797 // TODO(gman): call glShaderBinary
8798 return error::kNoError;
8799#endif
8800}
8801
[email protected]6d792ee12013-05-15 00:40:568802void GLES2DecoderImpl::DoSwapBuffers() {
[email protected]64ace852011-05-19 21:49:498803 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
[email protected]a7266a92012-06-28 02:11:088804
[email protected]64ace852011-05-19 21:49:498805 int this_frame_number = frame_number_++;
[email protected]2ac620e52012-07-23 20:31:428806 // TRACE_EVENT for gpu tests:
8807 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
[email protected]c76faea2013-03-26 07:42:428808 TRACE_EVENT_SCOPE_THREAD,
[email protected]2ac620e52012-07-23 20:31:428809 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8810 "width", (is_offscreen ? offscreen_size_.width() :
8811 surface_->GetSize().width()));
[email protected]6d792ee12013-05-15 00:40:568812 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
[email protected]64ace852011-05-19 21:49:498813 "offscreen", is_offscreen,
8814 "frame", this_frame_number);
[email protected]8f9b8dd2013-09-12 18:05:138815 bool is_tracing;
8816 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8817 &is_tracing);
8818 if (is_tracing) {
8819 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8820 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8821 is_offscreen ? offscreen_size_ : surface_->GetSize());
8822 }
8823
[email protected]6217d392010-03-25 22:08:358824 // If offscreen then don't actually SwapBuffers to the display. Just copy
8825 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:498826 if (is_offscreen) {
[email protected]111975c62012-09-06 01:37:318827 TRACE_EVENT2("gpu", "Offscreen",
8828 "width", offscreen_size_.width(), "height", offscreen_size_.height());
[email protected]1fb8c482011-08-31 01:01:538829 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8830 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8831 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8832 // fix this.
[email protected]62e155e2012-10-23 22:43:158833 if (workarounds().needs_offscreen_buffer_workaround) {
[email protected]1fb8c482011-08-31 01:01:538834 offscreen_saved_frame_buffer_->Create();
8835 glFinish();
8836 }
8837
8838 // Allocate the offscreen saved color texture.
8839 DCHECK(offscreen_saved_color_format_);
8840 offscreen_saved_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:098841 offscreen_size_, offscreen_saved_color_format_, false);
[email protected]1fb8c482011-08-31 01:01:538842
8843 offscreen_saved_frame_buffer_->AttachRenderTexture(
8844 offscreen_saved_color_texture_.get());
[email protected]f0cfe752013-01-14 01:09:058845 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
8846 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8847 GL_FRAMEBUFFER_COMPLETE) {
8848 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8849 << "because offscreen saved FBO was incomplete.";
[email protected]6d792ee12013-05-15 00:40:568850 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8851 return;
[email protected]f0cfe752013-01-14 01:09:058852 }
[email protected]1fb8c482011-08-31 01:01:538853
[email protected]f0cfe752013-01-14 01:09:058854 // Clear the offscreen color texture.
8855 // TODO(piman): Is this still necessary?
8856 {
8857 ScopedFrameBufferBinder binder(this,
8858 offscreen_saved_frame_buffer_->id());
8859 glClearColor(0, 0, 0, 0);
8860 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8861 glDisable(GL_SCISSOR_TEST);
8862 glClear(GL_COLOR_BUFFER_BIT);
8863 RestoreClearState();
8864 }
[email protected]1fb8c482011-08-31 01:01:538865 }
8866
8867 UpdateParentTextureInfo();
8868 }
8869
[email protected]f0cfe752013-01-14 01:09:058870 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
[email protected]6d792ee12013-05-15 00:40:568871 return;
[email protected]ab09b612013-03-11 22:11:518872 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:308873 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
[email protected]6217d392010-03-25 22:08:358874
[email protected]34ff8b0c2010-10-01 20:06:028875 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:138876 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:278877 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]b86b14982010-10-11 18:45:488878 } else {
[email protected]069944672012-04-25 20:52:238879 ScopedFrameBufferBinder binder(this,
8880 offscreen_target_frame_buffer_->id());
[email protected]51411e32012-01-19 20:21:138881
[email protected]069944672012-04-25 20:52:238882 if (offscreen_target_buffer_preserved_) {
8883 // Copy the target frame buffer to the saved offscreen texture.
8884 offscreen_saved_color_texture_->Copy(
8885 offscreen_saved_color_texture_->size(),
8886 offscreen_saved_color_format_);
8887 } else {
8888 // Flip the textures in the parent context via the texture manager.
8889 if (!!offscreen_saved_color_texture_info_.get())
[email protected]370eaf12013-05-18 09:19:498890 offscreen_saved_color_texture_info_->texture()->
[email protected]069944672012-04-25 20:52:238891 SetServiceId(offscreen_target_color_texture_->id());
[email protected]8a61d872012-01-20 12:43:568892
[email protected]069944672012-04-25 20:52:238893 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8894 offscreen_target_frame_buffer_->AttachRenderTexture(
8895 offscreen_target_color_texture_.get());
[email protected]b86b14982010-10-11 18:45:488896 }
[email protected]069944672012-04-25 20:52:238897
8898 // Ensure the side effects of the copy are visible to the parent
8899 // context. There is no need to do this for ANGLE because it uses a
8900 // single D3D device for all contexts.
[email protected]f42f05b2013-11-15 21:46:188901 if (!feature_info_->feature_flags().is_angle)
[email protected]069944672012-04-25 20:52:238902 glFlush();
[email protected]0c8c9d22010-06-25 17:36:398903 }
[email protected]6217d392010-03-25 22:08:358904 } else {
[email protected]111975c62012-09-06 01:37:318905 TRACE_EVENT2("gpu", "Onscreen",
8906 "width", surface_->GetSize().width(),
8907 "height", surface_->GetSize().height());
[email protected]f62a5ab2011-05-23 20:34:158908 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:018909 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]6d792ee12013-05-15 00:40:568910 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
[email protected]d0498742010-09-20 20:27:018911 }
[email protected]6217d392010-03-25 22:08:358912 }
[email protected]6217d392010-03-25 22:08:358913}
8914
[email protected]d4239852011-08-12 04:51:228915error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358916 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:188917 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288918 if (!bucket || bucket->size() == 0) {
8919 return error::kInvalidArguments;
8920 }
[email protected]ed9f9cd2013-02-27 21:12:358921 typedef cmds::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:188922 Result* result = GetSharedMemoryAs<Result*>(
8923 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8924 if (!result) {
8925 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:108926 }
[email protected]b1d2dcb2010-05-17 19:24:188927 // Check that the client initialized the result.
8928 if (*result != 0) {
8929 return error::kInvalidArguments;
8930 }
8931 std::string feature_str;
8932 if (!bucket->GetAsString(&feature_str)) {
8933 return error::kInvalidArguments;
8934 }
8935
8936 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:228937 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:188938 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:228939 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:408940 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8941 // TODO(gman): decide how to remove the need for this const_cast.
8942 // I could make validators_ non const but that seems bad as this is the only
8943 // place it is needed. I could make some special friend class of validators
8944 // just to allow this to set them. That seems silly. I could refactor this
8945 // code to use the extension mechanism or the initialization attributes to
8946 // turn this feature on. Given that the only real point of this is to make
8947 // the conformance tests pass and given that there is lots of real work that
8948 // needs to be done it seems like refactoring for one to one of those
8949 // methods is a very low priority.
8950 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:048951 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
8952 force_webgl_glsl_validation_ = true;
8953 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:188954 } else {
8955 return error::kNoError;
8956 }
8957
8958 *result = 1; // true.
8959 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:108960}
8961
[email protected]c2f8c8402010-12-06 18:07:248962error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8963 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:358964 const cmds::GetRequestableExtensionsCHROMIUM& c) {
[email protected]c2f8c8402010-12-06 18:07:248965 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]ed9f9cd2013-02-27 21:12:358966 scoped_refptr<FeatureInfo> info(new FeatureInfo());
[email protected]956aec52013-09-05 15:41:198967 info->Initialize(disallowed_features_);
[email protected]c2f8c8402010-12-06 18:07:248968 bucket->SetFromString(info->extensions().c_str());
8969 return error::kNoError;
8970}
8971
8972error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358973 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
[email protected]c2f8c8402010-12-06 18:07:248974 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288975 if (!bucket || bucket->size() == 0) {
8976 return error::kInvalidArguments;
8977 }
[email protected]c2f8c8402010-12-06 18:07:248978 std::string feature_str;
8979 if (!bucket->GetAsString(&feature_str)) {
8980 return error::kInvalidArguments;
8981 }
8982
[email protected]4b7eba92013-01-08 02:23:568983 bool desire_webgl_glsl_validation =
8984 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
8985 bool desire_standard_derivatives = false;
[email protected]70dc60932013-06-04 03:33:498986 bool desire_frag_depth = false;
[email protected]aff39ac82013-06-08 04:53:138987 bool desire_draw_buffers = false;
[email protected]4b7eba92013-01-08 02:23:568988 if (force_webgl_glsl_validation_) {
8989 desire_standard_derivatives =
8990 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
[email protected]70dc60932013-06-04 03:33:498991 desire_frag_depth =
8992 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
[email protected]aff39ac82013-06-08 04:53:138993 desire_draw_buffers =
8994 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
[email protected]f0d74742011-10-03 16:31:048995 }
8996
[email protected]4b7eba92013-01-08 02:23:568997 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
[email protected]70dc60932013-06-04 03:33:498998 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
[email protected]aff39ac82013-06-08 04:53:138999 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9000 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
[email protected]70dc60932013-06-04 03:33:499001 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9002 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9003 frag_depth_explicitly_enabled_ |= desire_frag_depth;
[email protected]aff39ac82013-06-08 04:53:139004 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
[email protected]c2f8c8402010-12-06 18:07:249005 InitializeShaderTranslator();
9006 }
9007
[email protected]302ce6d2011-07-07 23:28:119008 UpdateCapabilities();
9009
[email protected]c2f8c8402010-12-06 18:07:249010 return error::kNoError;
9011}
9012
[email protected]372e0412011-06-28 16:08:569013error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359014 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
[email protected]372e0412011-06-28 16:08:569015 GLuint count = c.count;
9016 uint32 pnames_size;
9017 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9018 return error::kOutOfBounds;
9019 }
9020 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9021 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9022 if (pnames == NULL) {
9023 return error::kOutOfBounds;
9024 }
9025
9026 // We have to copy them since we use them twice so the client
9027 // can't change them between the time we validate them and the time we use
9028 // them.
[email protected]40d90a22013-04-09 03:39:559029 scoped_ptr<GLenum[]> enums(new GLenum[count]);
[email protected]372e0412011-06-28 16:08:569030 memcpy(enums.get(), pnames, pnames_size);
9031
9032 // Count up the space needed for the result.
9033 uint32 num_results = 0;
9034 for (GLuint ii = 0; ii < count; ++ii) {
9035 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9036 if (num == 0) {
[email protected]ab09b612013-03-11 22:11:519037 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9038 "glGetMulitpleCHROMIUM", enums[ii], "pname");
[email protected]372e0412011-06-28 16:08:569039 return error::kNoError;
9040 }
9041 // Num will never be more than 4.
9042 DCHECK_LE(num, 4u);
[email protected]3aad1a32012-09-07 20:54:479043 if (!SafeAddUint32(num_results, num, &num_results)) {
[email protected]372e0412011-06-28 16:08:569044 return error::kOutOfBounds;
9045 }
9046 }
9047
9048 uint32 result_size = 0;
9049 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9050 return error::kOutOfBounds;
9051 }
9052
9053 if (result_size != static_cast<uint32>(c.size)) {
[email protected]ab09b612013-03-11 22:11:519054 LOCAL_SET_GL_ERROR(
9055 GL_INVALID_VALUE,
9056 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
[email protected]372e0412011-06-28 16:08:569057 return error::kNoError;
9058 }
9059
9060 GLint* results = GetSharedMemoryAs<GLint*>(
9061 c.results_shm_id, c.results_shm_offset, result_size);
9062 if (results == NULL) {
9063 return error::kOutOfBounds;
9064 }
9065
9066 // Check the results have been cleared in case the context was lost.
9067 for (uint32 ii = 0; ii < num_results; ++ii) {
9068 if (results[ii]) {
9069 return error::kInvalidArguments;
9070 }
9071 }
9072
9073 // Get each result.
9074 GLint* start = results;
9075 for (GLuint ii = 0; ii < count; ++ii) {
9076 GLsizei num_written = 0;
[email protected]d058bca2012-11-26 10:27:269077 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
[email protected]f63b1232012-10-31 07:03:539078 !GetHelper(enums[ii], results, &num_written)) {
[email protected]b0ce0982013-05-13 18:51:489079 DoGetIntegerv(enums[ii], results);
[email protected]372e0412011-06-28 16:08:569080 }
9081 results += num_written;
9082 }
9083
9084 // Just to verify. Should this be a DCHECK?
9085 if (static_cast<uint32>(results - start) != num_results) {
9086 return error::kOutOfBounds;
9087 }
9088
9089 return error::kNoError;
9090}
9091
[email protected]2318d342011-07-11 22:27:429092error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359093 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
[email protected]df37b9932013-03-08 05:21:429094 GLuint program_id = static_cast<GLuint>(c.program);
[email protected]2318d342011-07-11 22:27:429095 uint32 bucket_id = c.bucket_id;
9096 Bucket* bucket = CreateBucket(bucket_id);
9097 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
[email protected]df37b9932013-03-08 05:21:429098 Program* program = NULL;
9099 program = GetProgram(program_id);
9100 if (!program || !program->IsValid()) {
[email protected]9a14ae612011-08-08 17:51:469101 return error::kNoError;
[email protected]2318d342011-07-11 22:27:429102 }
[email protected]df37b9932013-03-08 05:21:429103 program->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:429104 return error::kNoError;
9105}
9106
[email protected]38d139d2011-07-14 00:38:439107error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9108 switch (reset_status_) {
[email protected]ad84a3a2012-06-08 21:42:439109 case GL_NO_ERROR:
9110 // TODO(kbr): improve the precision of the error code in this case.
9111 // Consider delegating to context for error code if MakeCurrent fails.
9112 return error::kUnknown;
9113 case GL_GUILTY_CONTEXT_RESET_ARB:
9114 return error::kGuilty;
9115 case GL_INNOCENT_CONTEXT_RESET_ARB:
9116 return error::kInnocent;
9117 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9118 return error::kUnknown;
[email protected]38d139d2011-07-14 00:38:439119 }
9120
9121 NOTREACHED();
9122 return error::kUnknown;
9123}
9124
9125bool GLES2DecoderImpl::WasContextLost() {
[email protected]c4485aad62012-12-17 10:19:099126 if (reset_status_ != GL_NO_ERROR) {
9127 return true;
9128 }
[email protected]706b69f2012-07-27 04:59:309129 if (context_->WasAllocatedUsingRobustnessExtension()) {
9130 GLenum status = GL_NO_ERROR;
9131 if (has_robustness_extension_)
9132 status = glGetGraphicsResetStatusARB();
[email protected]38d139d2011-07-14 00:38:439133 if (status != GL_NO_ERROR) {
9134 // The graphics card was reset. Signal a lost context to the application.
9135 reset_status_ = status;
[email protected]93a7d98f2013-07-11 00:04:229136 reset_by_robustness_extension_ = true;
[email protected]38d139d2011-07-14 00:38:439137 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
[email protected]c4485aad62012-12-17 10:19:099138 << " context lost via ARB/EXT_robustness. Reset status = "
9139 << GLES2Util::GetStringEnum(status);
[email protected]38d139d2011-07-14 00:38:439140 return true;
9141 }
9142 }
9143 return false;
9144}
9145
[email protected]93a7d98f2013-07-11 00:04:229146bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9147 return WasContextLost() && reset_by_robustness_extension_;
9148}
9149
[email protected]c4485aad62012-12-17 10:19:099150void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9151 // Only loses the context once.
9152 if (reset_status_ != GL_NO_ERROR) {
9153 return;
9154 }
9155
9156 // Marks this context as lost.
9157 reset_status_ = reset_status;
9158 current_decoder_error_ = error::kLostContext;
[email protected]c4485aad62012-12-17 10:19:099159}
9160
9161error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359162 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
[email protected]c4485aad62012-12-17 10:19:099163 GLenum current = static_cast<GLenum>(c.current);
9164 GLenum other = static_cast<GLenum>(c.other);
9165 if (!validators_->reset_status.IsValid(current)) {
[email protected]ab09b612013-03-11 22:11:519166 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9167 "glLoseContextCHROMIUM", current, "current");
[email protected]c4485aad62012-12-17 10:19:099168 }
9169 if (!validators_->reset_status.IsValid(other)) {
[email protected]ab09b612013-03-11 22:11:519170 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
[email protected]c4485aad62012-12-17 10:19:099171 }
9172 group_->LoseContexts(other);
9173 reset_status_ = current;
9174 current_decoder_error_ = error::kLostContext;
9175 return error::kLostContext;
9176}
9177
[email protected]b096d032013-03-08 03:08:019178error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9179 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9180 return error::kUnknownCommand;
9181}
9182
[email protected]840a7e462013-02-27 01:29:519183error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359184 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
[email protected]840a7e462013-02-27 01:29:519185 if (wait_sync_point_callback_.is_null())
9186 return error::kNoError;
9187
9188 return wait_sync_point_callback_.Run(c.sync_point) ?
9189 error::kNoError : error::kDeferCommandUntilLater;
9190}
9191
[email protected]882ba1e22012-03-08 19:02:539192bool GLES2DecoderImpl::GenQueriesEXTHelper(
9193 GLsizei n, const GLuint* client_ids) {
9194 for (GLsizei ii = 0; ii < n; ++ii) {
9195 if (query_manager_->GetQuery(client_ids[ii])) {
9196 return false;
9197 }
9198 }
[email protected]c45f1972012-03-14 07:27:369199 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:539200 return true;
9201}
9202
9203void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9204 GLsizei n, const GLuint* client_ids) {
9205 for (GLsizei ii = 0; ii < n; ++ii) {
9206 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9207 if (query && !query->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:119208 if (query == state_.current_query.get()) {
[email protected]e259eb412012-10-13 05:47:249209 state_.current_query = NULL;
[email protected]882ba1e22012-03-08 19:02:539210 }
[email protected]c45f1972012-03-14 07:27:369211 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:539212 query_manager_->RemoveQuery(client_ids[ii]);
9213 }
9214 }
9215}
9216
[email protected]22e3f552012-03-13 01:54:199217bool GLES2DecoderImpl::ProcessPendingQueries() {
9218 if (query_manager_.get() == NULL) {
9219 return false;
9220 }
[email protected]c45f1972012-03-14 07:27:369221 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:199222 current_decoder_error_ = error::kOutOfBounds;
9223 }
9224 return query_manager_->HavePendingQueries();
9225}
9226
[email protected]5a36dc132013-07-23 23:17:559227// Note that if there are no pending readpixels right now,
9228// this function will call the callback immediately.
9229void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9230 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9231 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9232 } else {
9233 callback.Run();
9234 }
9235}
9236
9237void GLES2DecoderImpl::ProcessPendingReadPixels() {
9238 while (!pending_readpixel_fences_.empty() &&
9239 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9240 std::vector<base::Closure> callbacks =
9241 pending_readpixel_fences_.front()->callbacks;
9242 pending_readpixel_fences_.pop();
9243 for (size_t i = 0; i < callbacks.size(); i++) {
9244 callbacks[i].Run();
9245 }
9246 }
9247}
9248
[email protected]2b1767cf2013-03-16 09:25:059249bool GLES2DecoderImpl::HasMoreIdleWork() {
[email protected]5a36dc132013-07-23 23:17:559250 return !pending_readpixel_fences_.empty() ||
9251 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
[email protected]2b1767cf2013-03-16 09:25:059252}
9253
9254void GLES2DecoderImpl::PerformIdleWork() {
[email protected]5a36dc132013-07-23 23:17:559255 ProcessPendingReadPixels();
[email protected]b68b100752013-06-05 08:34:489256 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
[email protected]2b1767cf2013-03-16 09:25:059257 return;
[email protected]b68b100752013-06-05 08:34:489258 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
[email protected]2b1767cf2013-03-16 09:25:059259 ProcessFinishedAsyncTransfers();
9260}
9261
[email protected]882ba1e22012-03-08 19:02:539262error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
[email protected]ed9f9cd2013-02-27 21:12:359263 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
[email protected]882ba1e22012-03-08 19:02:539264 GLenum target = static_cast<GLenum>(c.target);
9265 GLuint client_id = static_cast<GLuint>(c.id);
9266 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9267 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9268
[email protected]c45f1972012-03-14 07:27:369269 switch (target) {
9270 case GL_COMMANDS_ISSUED_CHROMIUM:
[email protected]fb4bf5822012-10-23 21:25:559271 case GL_LATENCY_QUERY_CHROMIUM:
[email protected]5537605d2013-08-27 05:22:319272 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9273 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
[email protected]620b0db02013-03-20 15:47:009274 case GL_GET_ERROR_QUERY_CHROMIUM:
[email protected]c45f1972012-03-14 07:27:369275 break;
9276 default:
[email protected]62e155e2012-10-23 22:43:159277 if (!features().occlusion_query_boolean) {
[email protected]ab09b612013-03-11 22:11:519278 LOCAL_SET_GL_ERROR(
[email protected]620b0db02013-03-20 15:47:009279 GL_INVALID_OPERATION, "glBeginQueryEXT",
9280 "not enabled for occlusion queries");
[email protected]c45f1972012-03-14 07:27:369281 return error::kNoError;
9282 }
9283 break;
[email protected]882ba1e22012-03-08 19:02:539284 }
9285
[email protected]5a36dc132013-07-23 23:17:559286 // TODO(hubbe): Make it possible to have one query per type running at the
9287 // same time.
[email protected]7cd76fd2013-06-02 21:11:119288 if (state_.current_query.get()) {
[email protected]ab09b612013-03-11 22:11:519289 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439290 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
[email protected]882ba1e22012-03-08 19:02:539291 return error::kNoError;
9292 }
9293
9294 if (client_id == 0) {
[email protected]ab09b612013-03-11 22:11:519295 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
[email protected]882ba1e22012-03-08 19:02:539296 return error::kNoError;
9297 }
9298
9299 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9300 if (!query) {
[email protected]c45f1972012-03-14 07:27:369301 // TODO(gman): Decide if we need this check.
9302 //
[email protected]882ba1e22012-03-08 19:02:539303 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:369304 //
9305 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9306 // for all Query ids but from the POV of the command buffer service maybe
9307 // you don't.
9308 //
9309 // The client can enforce this. I don't think the service cares.
9310 //
9311 // IdAllocatorInterface* id_allocator =
9312 // group_->GetIdAllocator(id_namespaces::kQueries);
9313 // if (!id_allocator->InUse(client_id)) {
[email protected]ab09b612013-03-11 22:11:519314 // LOCAL_SET_GL_ERROR(
9315 // GL_INVALID_OPERATION,
9316 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
[email protected]c45f1972012-03-14 07:27:369317 // return error::kNoError;
9318 // }
9319 query = query_manager_->CreateQuery(
9320 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:539321 }
9322
[email protected]c45f1972012-03-14 07:27:369323 if (query->target() != target) {
[email protected]ab09b612013-03-11 22:11:519324 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439325 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
[email protected]882ba1e22012-03-08 19:02:539326 return error::kNoError;
9327 } else if (query->shm_id() != sync_shm_id ||
9328 query->shm_offset() != sync_shm_offset) {
9329 DLOG(ERROR) << "Shared memory used by query not the same as before";
9330 return error::kInvalidArguments;
9331 }
9332
[email protected]c45f1972012-03-14 07:27:369333 if (!query_manager_->BeginQuery(query)) {
9334 return error::kOutOfBounds;
9335 }
[email protected]882ba1e22012-03-08 19:02:539336
[email protected]e259eb412012-10-13 05:47:249337 state_.current_query = query;
[email protected]882ba1e22012-03-08 19:02:539338 return error::kNoError;
9339}
9340
9341error::Error GLES2DecoderImpl::HandleEndQueryEXT(
[email protected]ed9f9cd2013-02-27 21:12:359342 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
[email protected]882ba1e22012-03-08 19:02:539343 GLenum target = static_cast<GLenum>(c.target);
9344 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9345
[email protected]7cd76fd2013-06-02 21:11:119346 if (!state_.current_query.get()) {
[email protected]ab09b612013-03-11 22:11:519347 LOCAL_SET_GL_ERROR(
9348 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
[email protected]882ba1e22012-03-08 19:02:539349 return error::kNoError;
9350 }
[email protected]e259eb412012-10-13 05:47:249351 if (state_.current_query->target() != target) {
[email protected]ab09b612013-03-11 22:11:519352 LOCAL_SET_GL_ERROR(
9353 GL_INVALID_OPERATION,
9354 "glEndQueryEXT", "target does not match active query");
[email protected]882ba1e22012-03-08 19:02:539355 return error::kNoError;
9356 }
[email protected]882ba1e22012-03-08 19:02:539357
[email protected]7cd76fd2013-06-02 21:11:119358 if (!query_manager_->EndQuery(state_.current_query.get(), submit_count)) {
[email protected]c45f1972012-03-14 07:27:369359 return error::kOutOfBounds;
9360 }
9361
[email protected]fe8d73c2013-02-16 22:37:329362 query_manager_->ProcessPendingTransferQueries();
9363
[email protected]e259eb412012-10-13 05:47:249364 state_.current_query = NULL;
[email protected]882ba1e22012-03-08 19:02:539365 return error::kNoError;
9366}
9367
[email protected]944b62f32012-09-27 02:20:469368bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9369 GLsizei n, const GLuint* client_ids) {
[email protected]944b62f32012-09-27 02:20:469370 for (GLsizei ii = 0; ii < n; ++ii) {
9371 if (GetVertexAttribManager(client_ids[ii])) {
9372 return false;
9373 }
9374 }
[email protected]ab4fd7282012-10-12 16:25:579375
[email protected]62e155e2012-10-23 22:43:159376 if (!features().native_vertex_array_object) {
[email protected]ab4fd7282012-10-12 16:25:579377 // Emulated VAO
9378 for (GLsizei ii = 0; ii < n; ++ii) {
9379 CreateVertexAttribManager(client_ids[ii], 0);
9380 }
9381 } else {
[email protected]40d90a22013-04-09 03:39:559382 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ab4fd7282012-10-12 16:25:579383
9384 glGenVertexArraysOES(n, service_ids.get());
9385 for (GLsizei ii = 0; ii < n; ++ii) {
9386 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9387 }
[email protected]944b62f32012-09-27 02:20:469388 }
[email protected]ab4fd7282012-10-12 16:25:579389
[email protected]944b62f32012-09-27 02:20:469390 return true;
9391}
9392
9393void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9394 GLsizei n, const GLuint* client_ids) {
[email protected]944b62f32012-09-27 02:20:469395 for (GLsizei ii = 0; ii < n; ++ii) {
9396 VertexAttribManager* vao =
9397 GetVertexAttribManager(client_ids[ii]);
9398 if (vao && !vao->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:119399 if (state_.vertex_attrib_manager.get() == vao) {
[email protected]e259eb412012-10-13 05:47:249400 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
[email protected]944b62f32012-09-27 02:20:469401 }
9402 RemoveVertexAttribManager(client_ids[ii]);
9403 }
9404 }
9405}
9406
9407void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
[email protected]944b62f32012-09-27 02:20:469408 VertexAttribManager* vao = NULL;
9409 GLuint service_id = 0;
9410 if (client_id != 0) {
9411 vao = GetVertexAttribManager(client_id);
9412 if (!vao) {
9413 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9414 // only allows names that have been previously generated. As such, we do
9415 // not generate new names here.
[email protected]ab09b612013-03-11 22:11:519416 LOCAL_SET_GL_ERROR(
9417 GL_INVALID_OPERATION,
9418 "glBindVertexArrayOES", "bad vertex array id.");
[email protected]944b62f32012-09-27 02:20:469419 current_decoder_error_ = error::kNoError;
9420 return;
9421 } else {
9422 service_id = vao->service_id();
9423 }
[email protected]944b62f32012-09-27 02:20:469424 } else {
[email protected]7cd76fd2013-06-02 21:11:119425 vao = default_vertex_attrib_manager_.get();
[email protected]944b62f32012-09-27 02:20:469426 }
9427
[email protected]ab4fd7282012-10-12 16:25:579428 // Only set the VAO state if it's changed
[email protected]7cd76fd2013-06-02 21:11:119429 if (state_.vertex_attrib_manager.get() != vao) {
[email protected]e259eb412012-10-13 05:47:249430 state_.vertex_attrib_manager = vao;
[email protected]62e155e2012-10-23 22:43:159431 if (!features().native_vertex_array_object) {
[email protected]ab4fd7282012-10-12 16:25:579432 EmulateVertexArrayState();
9433 } else {
9434 glBindVertexArrayOES(service_id);
9435 }
9436 }
9437}
9438
9439// Used when OES_vertex_array_object isn't natively supported
9440void GLES2DecoderImpl::EmulateVertexArrayState() {
9441 // Setup the Vertex attribute state
9442 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9443 RestoreStateForAttrib(vv);
9444 }
9445
9446 // Setup the element buffer
[email protected]16ccec12013-02-28 03:40:219447 Buffer* element_array_buffer =
[email protected]e259eb412012-10-13 05:47:249448 state_.vertex_attrib_manager->element_array_buffer();
[email protected]ab4fd7282012-10-12 16:25:579449 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9450 element_array_buffer ? element_array_buffer->service_id() : 0);
[email protected]944b62f32012-09-27 02:20:469451}
9452
9453bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
[email protected]944b62f32012-09-27 02:20:469454 const VertexAttribManager* vao =
9455 GetVertexAttribManager(client_id);
9456 return vao && vao->IsValid() && !vao->IsDeleted();
9457}
9458
[email protected]b0af4f52011-09-28 22:04:429459error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
9460 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:359461 const cmds::CreateStreamTextureCHROMIUM& c) {
[email protected]62e155e2012-10-23 22:43:159462 if (!features().chromium_stream_texture) {
[email protected]ab09b612013-03-11 22:11:519463 LOCAL_SET_GL_ERROR(
9464 GL_INVALID_OPERATION,
9465 "glOpenStreamTextureCHROMIUM", "not supported.");
[email protected]b0af4f52011-09-28 22:04:429466 return error::kNoError;
9467 }
9468
9469 uint32 client_id = c.client_id;
[email protected]ed9f9cd2013-02-27 21:12:359470 typedef cmds::CreateStreamTextureCHROMIUM::Result Result;
[email protected]b0af4f52011-09-28 22:04:429471 Result* result = GetSharedMemoryAs<Result*>(
9472 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9473
[email protected]e5081262012-01-05 23:09:039474 if (!result)
9475 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:429476 *result = GL_ZERO;
[email protected]370eaf12013-05-18 09:19:499477 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
9478 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519479 LOCAL_SET_GL_ERROR(
9480 GL_INVALID_VALUE,
9481 "glCreateStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:429482 return error::kNoError;
9483 }
9484
[email protected]370eaf12013-05-18 09:19:499485 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079486 if (texture->IsStreamTexture()) {
[email protected]ab09b612013-03-11 22:11:519487 LOCAL_SET_GL_ERROR(
9488 GL_INVALID_OPERATION,
9489 "glCreateStreamTextureCHROMIUM", "is already a stream texture.");
[email protected]b0af4f52011-09-28 22:04:429490 return error::kNoError;
9491 }
9492
[email protected]02965c22013-03-09 02:40:079493 if (texture->target() && texture->target() != GL_TEXTURE_EXTERNAL_OES) {
[email protected]ab09b612013-03-11 22:11:519494 LOCAL_SET_GL_ERROR(
9495 GL_INVALID_OPERATION,
9496 "glCreateStreamTextureCHROMIUM",
9497 "is already bound to incompatible target.");
[email protected]b0af4f52011-09-28 22:04:429498 return error::kNoError;
9499 }
9500
[email protected]4f9958142013-07-02 03:58:079501 if (!stream_texture_manager())
[email protected]b0af4f52011-09-28 22:04:429502 return error::kInvalidArguments;
9503
[email protected]4f9958142013-07-02 03:58:079504 GLuint object_id = stream_texture_manager()->CreateStreamTexture(
[email protected]02965c22013-03-09 02:40:079505 texture->service_id(), client_id);
[email protected]b0af4f52011-09-28 22:04:429506
9507 if (object_id) {
[email protected]370eaf12013-05-18 09:19:499508 texture_manager()->SetStreamTexture(texture_ref, true);
[email protected]b0af4f52011-09-28 22:04:429509 } else {
[email protected]ab09b612013-03-11 22:11:519510 LOCAL_SET_GL_ERROR(
9511 GL_OUT_OF_MEMORY,
9512 "glCreateStreamTextureCHROMIUM", "failed to create platform texture.");
[email protected]b0af4f52011-09-28 22:04:429513 }
9514
9515 *result = object_id;
9516 return error::kNoError;
9517}
9518
9519error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
9520 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:359521 const cmds::DestroyStreamTextureCHROMIUM& c) {
[email protected]b0af4f52011-09-28 22:04:429522 GLuint client_id = c.texture;
[email protected]370eaf12013-05-18 09:19:499523 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
[email protected]4f9958142013-07-02 03:58:079524 if (texture_ref && texture_manager()->IsStreamTextureOwner(texture_ref)) {
9525 if (!stream_texture_manager())
[email protected]b0af4f52011-09-28 22:04:429526 return error::kInvalidArguments;
9527
[email protected]4f9958142013-07-02 03:58:079528 stream_texture_manager()->DestroyStreamTexture(texture_ref->service_id());
[email protected]370eaf12013-05-18 09:19:499529 texture_manager()->SetStreamTexture(texture_ref, false);
[email protected]b0af4f52011-09-28 22:04:429530 } else {
[email protected]ab09b612013-03-11 22:11:519531 LOCAL_SET_GL_ERROR(
9532 GL_INVALID_VALUE,
9533 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:429534 }
9535
9536 return error::kNoError;
9537}
9538
[email protected]e51bdf32011-11-23 22:21:469539#if defined(OS_MACOSX)
9540void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9541 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9542 texture_id);
9543 if (it != texture_to_io_surface_map_.end()) {
9544 // Found a previous IOSurface bound to this texture; release it.
9545 CFTypeRef surface = it->second;
9546 CFRelease(surface);
9547 texture_to_io_surface_map_.erase(it);
9548 }
9549}
9550#endif
9551
9552void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9553 GLenum target, GLsizei width, GLsizei height,
9554 GLuint io_surface_id, GLuint plane) {
9555#if defined(OS_MACOSX)
9556 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
[email protected]ab09b612013-03-11 22:11:519557 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439558 GL_INVALID_OPERATION,
9559 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
[email protected]e51bdf32011-11-23 22:21:469560 return;
9561 }
9562
9563 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9564 if (!surface_support) {
[email protected]ab09b612013-03-11 22:11:519565 LOCAL_SET_GL_ERROR(
9566 GL_INVALID_OPERATION,
9567 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
[email protected]e51bdf32011-11-23 22:21:469568 return;
9569 }
9570
9571 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9572 // This might be supported in the future, and if we could require
9573 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9574 // could delete a lot of code. For now, perform strict validation so we
9575 // know what's going on.
[email protected]ab09b612013-03-11 22:11:519576 LOCAL_SET_GL_ERROR(
[email protected]e51bdf32011-11-23 22:21:469577 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439578 "glTexImageIOSurface2DCHROMIUM",
9579 "requires TEXTURE_RECTANGLE_ARB target");
[email protected]e51bdf32011-11-23 22:21:469580 return;
9581 }
9582
[email protected]09d50362012-10-18 20:54:379583 // Default target might be conceptually valid, but disallow it to avoid
9584 // accidents.
[email protected]c986af502013-08-14 01:04:449585 TextureRef* texture_ref =
9586 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]370eaf12013-05-18 09:19:499587 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519588 LOCAL_SET_GL_ERROR(
9589 GL_INVALID_OPERATION,
9590 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
[email protected]e51bdf32011-11-23 22:21:469591 return;
9592 }
[email protected]e51bdf32011-11-23 22:21:469593
9594 // Look up the new IOSurface. Note that because of asynchrony
9595 // between processes this might fail; during live resizing the
9596 // plugin process might allocate and release an IOSurface before
9597 // this process gets a chance to look it up. Hold on to any old
9598 // IOSurface in this case.
9599 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9600 if (!surface) {
[email protected]ab09b612013-03-11 22:11:519601 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439602 GL_INVALID_OPERATION,
9603 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
[email protected]e51bdf32011-11-23 22:21:469604 return;
9605 }
9606
9607 // Release any IOSurface previously bound to this texture.
[email protected]370eaf12013-05-18 09:19:499608 ReleaseIOSurfaceForTexture(texture_ref->service_id());
[email protected]e51bdf32011-11-23 22:21:469609
9610 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9611 texture_to_io_surface_map_.insert(
[email protected]370eaf12013-05-18 09:19:499612 std::make_pair(texture_ref->service_id(), surface));
[email protected]e51bdf32011-11-23 22:21:469613
9614 CGLContextObj context =
9615 static_cast<CGLContextObj>(context_->GetHandle());
9616
9617 CGLError err = surface_support->CGLTexImageIOSurface2D(
9618 context,
9619 target,
9620 GL_RGBA,
9621 width,
9622 height,
9623 GL_BGRA,
9624 GL_UNSIGNED_INT_8_8_8_8_REV,
9625 surface,
9626 plane);
9627
9628 if (err != kCGLNoError) {
[email protected]ab09b612013-03-11 22:11:519629 LOCAL_SET_GL_ERROR(
[email protected]e51bdf32011-11-23 22:21:469630 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439631 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
[email protected]e51bdf32011-11-23 22:21:469632 return;
9633 }
9634
9635 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499636 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:469637 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9638
9639#else
[email protected]ab09b612013-03-11 22:11:519640 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439641 "glTexImageIOSurface2DCHROMIUM", "not supported.");
[email protected]e51bdf32011-11-23 22:21:469642#endif
9643}
9644
[email protected]97dc7cbe2011-12-06 17:26:179645static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9646 switch (internalformat) {
9647 case GL_RGB565:
9648 return GL_RGB;
9649 case GL_RGBA4:
9650 return GL_RGBA;
9651 case GL_RGB5_A1:
9652 return GL_RGBA;
9653 case GL_RGB8_OES:
9654 return GL_RGB;
9655 case GL_RGBA8_OES:
9656 return GL_RGBA;
9657 case GL_LUMINANCE8_ALPHA8_EXT:
9658 return GL_LUMINANCE_ALPHA;
9659 case GL_LUMINANCE8_EXT:
9660 return GL_LUMINANCE;
9661 case GL_ALPHA8_EXT:
9662 return GL_ALPHA;
9663 case GL_RGBA32F_EXT:
9664 return GL_RGBA;
9665 case GL_RGB32F_EXT:
9666 return GL_RGB;
9667 case GL_ALPHA32F_EXT:
9668 return GL_ALPHA;
9669 case GL_LUMINANCE32F_EXT:
9670 return GL_LUMINANCE;
9671 case GL_LUMINANCE_ALPHA32F_EXT:
9672 return GL_LUMINANCE_ALPHA;
9673 case GL_RGBA16F_EXT:
9674 return GL_RGBA;
9675 case GL_RGB16F_EXT:
9676 return GL_RGB;
9677 case GL_ALPHA16F_EXT:
9678 return GL_ALPHA;
9679 case GL_LUMINANCE16F_EXT:
9680 return GL_LUMINANCE;
9681 case GL_LUMINANCE_ALPHA16F_EXT:
9682 return GL_LUMINANCE_ALPHA;
9683 case GL_BGRA8_EXT:
9684 return GL_BGRA_EXT;
9685 default:
9686 return GL_NONE;
9687 }
9688}
9689
[email protected]43410e92012-04-20 17:06:289690void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
[email protected]0a1e9ad2012-05-04 21:13:039691 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
[email protected]a4a6bdd12013-04-19 20:46:549692 GLenum internal_format, GLenum dest_type) {
[email protected]370eaf12013-05-18 09:19:499693 TextureRef* dest_texture_ref = GetTexture(dest_id);
9694 TextureRef* source_texture_ref = GetTexture(source_id);
[email protected]43410e92012-04-20 17:06:289695
[email protected]370eaf12013-05-18 09:19:499696 if (!source_texture_ref || !dest_texture_ref) {
[email protected]ab09b612013-03-11 22:11:519697 LOCAL_SET_GL_ERROR(
9698 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
[email protected]43410e92012-04-20 17:06:289699 return;
9700 }
9701
9702 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:519703 LOCAL_SET_GL_ERROR(
9704 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
[email protected]43410e92012-04-20 17:06:289705 return;
9706 }
9707
[email protected]370eaf12013-05-18 09:19:499708 Texture* source_texture = source_texture_ref->texture();
9709 Texture* dest_texture = dest_texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079710 if (dest_texture->target() != GL_TEXTURE_2D ||
[email protected]9bc9a2e82013-04-03 03:56:259711 (source_texture->target() != GL_TEXTURE_2D &&
9712 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
[email protected]3ecc1052013-09-26 08:59:009713 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9714 "glCopyTextureCHROMIUM",
9715 "invalid texture target binding");
[email protected]0a1e9ad2012-05-04 21:13:039716 return;
9717 }
9718
[email protected]43410e92012-04-20 17:06:289719 int source_width, source_height, dest_width, dest_height;
[email protected]43410e92012-04-20 17:06:289720
[email protected]3ecc1052013-09-26 08:59:009721 if (source_texture->IsStreamTexture()) {
9722 DCHECK_EQ(source_texture->target(),
9723 static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES));
[email protected]4f9958142013-07-02 03:58:079724 DCHECK(stream_texture_manager());
[email protected]377976552013-05-14 23:32:569725 StreamTexture* stream_tex =
[email protected]4f9958142013-07-02 03:58:079726 stream_texture_manager()->LookupStreamTexture(
[email protected]377976552013-05-14 23:32:569727 source_texture->service_id());
9728 if (!stream_tex) {
9729 LOCAL_SET_GL_ERROR(
9730 GL_INVALID_VALUE,
9731 "glCopyTextureChromium", "Stream texture lookup failed");
9732 return;
9733 }
9734 gfx::Size size = stream_tex->GetSize();
9735 source_width = size.width();
9736 source_height = size.height();
9737 if (source_width <= 0 || source_height <= 0) {
9738 LOCAL_SET_GL_ERROR(
9739 GL_INVALID_VALUE,
9740 "glCopyTextureChromium", "invalid streamtexture size");
9741 return;
9742 }
[email protected]3ecc1052013-09-26 08:59:009743 } else {
9744 if (!source_texture->GetLevelSize(
9745 source_texture->target(), 0, &source_width, &source_height)) {
9746 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9747 "glCopyTextureChromium",
9748 "source texture has no level 0");
9749 return;
9750 }
9751
9752 // Check that this type of texture is allowed.
9753 if (!texture_manager()->ValidForTarget(
9754 source_texture->target(), level, source_width, source_height, 1)) {
9755 LOCAL_SET_GL_ERROR(
9756 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9757 return;
9758 }
[email protected]377976552013-05-14 23:32:569759 }
9760
[email protected]cf6b8f62012-05-25 21:43:379761 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9762 // needed because it takes 10s of milliseconds to initialize.
9763 if (!copy_texture_CHROMIUM_.get()) {
[email protected]ab09b612013-03-11 22:11:519764 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
[email protected]cf6b8f62012-05-25 21:43:379765 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
[email protected]07a0cc32013-02-28 00:36:279766 copy_texture_CHROMIUM_->Initialize(this);
[email protected]cf6b8f62012-05-25 21:43:379767 RestoreCurrentFramebufferBindings();
[email protected]ab09b612013-03-11 22:11:519768 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
[email protected]cf6b8f62012-05-25 21:43:379769 return;
9770 }
9771
[email protected]a4a6bdd12013-04-19 20:46:549772 GLenum dest_type_previous;
[email protected]0a1e9ad2012-05-04 21:13:039773 GLenum dest_internal_format;
[email protected]02965c22013-03-09 02:40:079774 bool dest_level_defined = dest_texture->GetLevelSize(
9775 GL_TEXTURE_2D, level, &dest_width, &dest_height);
[email protected]43410e92012-04-20 17:06:289776
[email protected]0a1e9ad2012-05-04 21:13:039777 if (dest_level_defined) {
[email protected]a4a6bdd12013-04-19 20:46:549778 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
[email protected]02965c22013-03-09 02:40:079779 &dest_internal_format);
[email protected]0a1e9ad2012-05-04 21:13:039780 }
9781
9782 // Resize the destination texture to the dimensions of the source texture.
9783 if (!dest_level_defined || dest_width != source_width ||
9784 dest_height != source_height ||
[email protected]a4a6bdd12013-04-19 20:46:549785 dest_internal_format != internal_format ||
9786 dest_type_previous != dest_type) {
[email protected]43410e92012-04-20 17:06:289787 // Ensure that the glTexImage2D succeeds.
[email protected]ab09b612013-03-11 22:11:519788 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
[email protected]02965c22013-03-09 02:40:079789 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
[email protected]8f1d2aa2013-05-10 23:45:389790 glTexImage2D(
[email protected]43410e92012-04-20 17:06:289791 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
[email protected]0a1e9ad2012-05-04 21:13:039792 0, internal_format, dest_type, NULL);
[email protected]ab09b612013-03-11 22:11:519793 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
[email protected]0a1e9ad2012-05-04 21:13:039794 if (error != GL_NO_ERROR) {
[email protected]ce296892013-10-24 22:04:369795 RestoreCurrentTexture2DBindings(&state_);
[email protected]43410e92012-04-20 17:06:289796 return;
[email protected]0a1e9ad2012-05-04 21:13:039797 }
[email protected]43410e92012-04-20 17:06:289798
9799 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499800 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
[email protected]0a1e9ad2012-05-04 21:13:039801 source_height, 1, 0, internal_format, dest_type, true);
[email protected]f7024712012-05-15 21:30:259802 } else {
[email protected]02965c22013-03-09 02:40:079803 texture_manager()->SetLevelCleared(
[email protected]370eaf12013-05-18 09:19:499804 dest_texture_ref, GL_TEXTURE_2D, level, true);
[email protected]43410e92012-04-20 17:06:289805 }
9806
[email protected]91c94eb2013-10-22 10:32:549807 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
9808
[email protected]5394a4102013-04-18 05:41:379809 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9810 // before presenting.
9811 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9812 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9813 // instead of using default matrix crbug.com/226218.
9814 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9815 0.0f, 1.0f, 0.0f, 0.0f,
9816 0.0f, 0.0f, 1.0f, 0.0f,
9817 0.0f, 0.0f, 0.0f, 1.0f};
9818 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9819 this,
9820 source_texture->target(),
9821 dest_texture->target(),
9822 source_texture->service_id(),
9823 dest_texture->service_id(), level,
9824 source_width, source_height,
9825 unpack_flip_y_,
9826 unpack_premultiply_alpha_,
9827 unpack_unpremultiply_alpha_,
9828 default_matrix);
9829 } else {
9830 copy_texture_CHROMIUM_->DoCopyTexture(
9831 this,
9832 source_texture->target(),
9833 dest_texture->target(),
9834 source_texture->service_id(),
9835 dest_texture->service_id(), level,
9836 source_width, source_height,
9837 unpack_flip_y_,
9838 unpack_premultiply_alpha_,
9839 unpack_unpremultiply_alpha_);
9840 }
[email protected]91c94eb2013-10-22 10:32:549841
9842 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
[email protected]43410e92012-04-20 17:06:289843}
9844
[email protected]97dc7cbe2011-12-06 17:26:179845static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9846 switch (internalformat) {
9847 case GL_RGB565:
9848 return GL_UNSIGNED_SHORT_5_6_5;
9849 case GL_RGBA4:
9850 return GL_UNSIGNED_SHORT_4_4_4_4;
9851 case GL_RGB5_A1:
9852 return GL_UNSIGNED_SHORT_5_5_5_1;
9853 case GL_RGB8_OES:
9854 return GL_UNSIGNED_BYTE;
9855 case GL_RGBA8_OES:
9856 return GL_UNSIGNED_BYTE;
9857 case GL_LUMINANCE8_ALPHA8_EXT:
9858 return GL_UNSIGNED_BYTE;
9859 case GL_LUMINANCE8_EXT:
9860 return GL_UNSIGNED_BYTE;
9861 case GL_ALPHA8_EXT:
9862 return GL_UNSIGNED_BYTE;
9863 case GL_RGBA32F_EXT:
9864 return GL_FLOAT;
9865 case GL_RGB32F_EXT:
9866 return GL_FLOAT;
9867 case GL_ALPHA32F_EXT:
9868 return GL_FLOAT;
9869 case GL_LUMINANCE32F_EXT:
9870 return GL_FLOAT;
9871 case GL_LUMINANCE_ALPHA32F_EXT:
9872 return GL_FLOAT;
9873 case GL_RGBA16F_EXT:
9874 return GL_HALF_FLOAT_OES;
9875 case GL_RGB16F_EXT:
9876 return GL_HALF_FLOAT_OES;
9877 case GL_ALPHA16F_EXT:
9878 return GL_HALF_FLOAT_OES;
9879 case GL_LUMINANCE16F_EXT:
9880 return GL_HALF_FLOAT_OES;
9881 case GL_LUMINANCE_ALPHA16F_EXT:
9882 return GL_HALF_FLOAT_OES;
9883 case GL_BGRA8_EXT:
9884 return GL_UNSIGNED_BYTE;
9885 default:
9886 return GL_NONE;
9887 }
9888}
9889
9890void GLES2DecoderImpl::DoTexStorage2DEXT(
[email protected]a5d3dad2012-05-26 04:34:449891 GLenum target,
9892 GLint levels,
9893 GLenum internal_format,
9894 GLsizei width,
9895 GLsizei height) {
[email protected]43ed3a72012-05-30 22:55:389896 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
[email protected]80eb6b52012-01-19 00:14:419897 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]3ecc1052013-09-26 08:59:009898 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
[email protected]ab09b612013-03-11 22:11:519899 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439900 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
[email protected]97dc7cbe2011-12-06 17:26:179901 return;
9902 }
[email protected]c986af502013-08-14 01:04:449903 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9904 &state_, target);
[email protected]370eaf12013-05-18 09:19:499905 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519906 LOCAL_SET_GL_ERROR(
9907 GL_INVALID_OPERATION,
9908 "glTexStorage2DEXT", "unknown texture for target");
[email protected]97dc7cbe2011-12-06 17:26:179909 return;
9910 }
[email protected]370eaf12013-05-18 09:19:499911 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079912 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:449913 framebuffer_state_.clear_state_dirty = true;
[email protected]97dc7cbe2011-12-06 17:26:179914 }
[email protected]02965c22013-03-09 02:40:079915 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:519916 LOCAL_SET_GL_ERROR(
9917 GL_INVALID_OPERATION,
9918 "glTexStorage2DEXT", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:179919 return;
9920 }
[email protected]7989c9e2013-01-23 06:39:269921
9922 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9923 GLenum type = ExtractTypeFromStorageFormat(internal_format);
9924
9925 {
9926 GLsizei level_width = width;
9927 GLsizei level_height = height;
9928 uint32 estimated_size = 0;
9929 for (int ii = 0; ii < levels; ++ii) {
9930 uint32 level_size = 0;
9931 if (!GLES2Util::ComputeImageDataSizes(
9932 level_width, level_height, format, type, state_.unpack_alignment,
9933 &estimated_size, NULL, NULL) ||
9934 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:519935 LOCAL_SET_GL_ERROR(
9936 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:269937 return;
9938 }
9939 level_width = std::max(1, level_width >> 1);
9940 level_height = std::max(1, level_height >> 1);
9941 }
9942 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:519943 LOCAL_SET_GL_ERROR(
9944 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
[email protected]7989c9e2013-01-23 06:39:269945 return;
9946 }
9947 }
9948
[email protected]ab09b612013-03-11 22:11:519949 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
[email protected]8f1d2aa2013-05-10 23:45:389950 glTexStorage2DEXT(target, levels, internal_format, width, height);
[email protected]ab09b612013-03-11 22:11:519951 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
[email protected]97dc7cbe2011-12-06 17:26:179952 if (error == GL_NO_ERROR) {
[email protected]4502e6492011-12-14 19:39:159953 GLsizei level_width = width;
9954 GLsizei level_height = height;
9955 for (int ii = 0; ii < levels; ++ii) {
9956 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499957 texture_ref, target, ii, format,
9958 level_width, level_height, 1, 0, format, type, false);
[email protected]4502e6492011-12-14 19:39:159959 level_width = std::max(1, level_width >> 1);
9960 level_height = std::max(1, level_height >> 1);
9961 }
[email protected]02965c22013-03-09 02:40:079962 texture->SetImmutable(true);
[email protected]97dc7cbe2011-12-06 17:26:179963 }
[email protected]97dc7cbe2011-12-06 17:26:179964}
[email protected]e51bdf32011-11-23 22:21:469965
[email protected]78b514b2012-05-01 21:50:599966error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359967 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
[email protected]baed42c2013-10-01 05:06:359968 return error::kUnknownCommand;
[email protected]78b514b2012-05-01 21:50:599969}
9970
9971void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
9972 const GLbyte* mailbox) {
[email protected]987b9c02013-03-23 00:58:029973 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
[email protected]1d82e822013-04-10 21:32:329974 "context", logger_.GetLogPrefix(),
[email protected]987b9c02013-03-23 00:58:029975 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9976
[email protected]c986af502013-08-14 01:04:449977 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9978 &state_, target);
[email protected]370eaf12013-05-18 09:19:499979 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519980 LOCAL_SET_GL_ERROR(
9981 GL_INVALID_OPERATION,
9982 "glProduceTextureCHROMIUM", "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599983 return;
9984 }
9985
[email protected]62e65f02013-05-29 22:28:109986 Texture* produced = texture_manager()->Produce(texture_ref);
9987 if (!produced) {
[email protected]ab09b612013-03-11 22:11:519988 LOCAL_SET_GL_ERROR(
9989 GL_INVALID_OPERATION,
9990 "glProduceTextureCHROMIUM", "invalid texture");
[email protected]78b514b2012-05-01 21:50:599991 return;
9992 }
9993
9994 if (!group_->mailbox_manager()->ProduceTexture(
9995 target,
9996 *reinterpret_cast<const MailboxName*>(mailbox),
[email protected]62e65f02013-05-29 22:28:109997 produced)) {
[email protected]ab09b612013-03-11 22:11:519998 LOCAL_SET_GL_ERROR(
9999 GL_INVALID_OPERATION,
10000 "glProduceTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:5910001 return;
10002 }
[email protected]78b514b2012-05-01 21:50:5910003}
10004
10005void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10006 const GLbyte* mailbox) {
[email protected]987b9c02013-03-23 00:58:0210007 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
[email protected]1d82e822013-04-10 21:32:3210008 "context", logger_.GetLogPrefix(),
[email protected]987b9c02013-03-23 00:58:0210009 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
10010
[email protected]62e65f02013-05-29 22:28:1010011 scoped_refptr<TextureRef> texture_ref =
[email protected]c986af502013-08-14 01:04:4410012 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]7cd76fd2013-06-02 21:11:1110013 if (!texture_ref.get()) {
10014 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10015 "glConsumeTextureCHROMIUM",
10016 "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:5910017 return;
10018 }
[email protected]62e65f02013-05-29 22:28:1010019 GLuint client_id = texture_ref->client_id();
10020 if (!client_id) {
10021 LOCAL_SET_GL_ERROR(
10022 GL_INVALID_OPERATION,
10023 "glConsumeTextureCHROMIUM", "unknown texture for target");
10024 return;
10025 }
10026 Texture* texture =
[email protected]78b514b2012-05-01 21:50:5910027 group_->mailbox_manager()->ConsumeTexture(
10028 target,
[email protected]62e65f02013-05-29 22:28:1010029 *reinterpret_cast<const MailboxName*>(mailbox));
10030 if (!texture) {
[email protected]ab09b612013-03-11 22:11:5110031 LOCAL_SET_GL_ERROR(
10032 GL_INVALID_OPERATION,
10033 "glConsumeTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:5910034 return;
10035 }
[email protected]62e65f02013-05-29 22:28:1010036 if (texture->target() != target) {
[email protected]ab09b612013-03-11 22:11:5110037 LOCAL_SET_GL_ERROR(
10038 GL_INVALID_OPERATION,
[email protected]62e65f02013-05-29 22:28:1010039 "glConsumeTextureCHROMIUM", "invalid target");
[email protected]78b514b2012-05-01 21:50:5910040 return;
10041 }
[email protected]62e65f02013-05-29 22:28:1010042
10043 DeleteTexturesHelper(1, &client_id);
10044 texture_ref = texture_manager()->Consume(client_id, texture);
10045 glBindTexture(target, texture_ref->service_id());
10046
10047 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10048 unit.bind_target = target;
10049 switch (target) {
10050 case GL_TEXTURE_2D:
10051 unit.bound_texture_2d = texture_ref;
10052 break;
10053 case GL_TEXTURE_CUBE_MAP:
10054 unit.bound_texture_cube_map = texture_ref;
10055 break;
10056 case GL_TEXTURE_EXTERNAL_OES:
10057 unit.bound_texture_external_oes = texture_ref;
10058 break;
10059 case GL_TEXTURE_RECTANGLE_ARB:
10060 unit.bound_texture_rectangle_arb = texture_ref;
10061 break;
10062 default:
10063 NOTREACHED(); // Validation should prevent us getting here.
10064 break;
10065 }
[email protected]78b514b2012-05-01 21:50:5910066}
10067
[email protected]d2a0e1a2012-08-12 02:25:0110068void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10069 GLsizei length, const GLchar* marker) {
10070 if (!marker) {
10071 marker = "";
10072 }
10073 debug_marker_manager_.SetMarker(
10074 length ? std::string(marker, length) : std::string(marker));
10075}
10076
10077void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10078 GLsizei length, const GLchar* marker) {
10079 if (!marker) {
10080 marker = "";
10081 }
10082 debug_marker_manager_.PushGroup(
10083 length ? std::string(marker, length) : std::string(marker));
10084}
10085
10086void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10087 debug_marker_manager_.PopGroup();
10088}
10089
[email protected]09d50362012-10-18 20:54:3710090void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10091 GLenum target, GLint image_id) {
10092 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
[email protected]09d50362012-10-18 20:54:3710093
10094 // Default target might be conceptually valid, but disallow it to avoid
10095 // accidents.
[email protected]c986af502013-08-14 01:04:4410096 TextureRef* texture_ref =
10097 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]370eaf12013-05-18 09:19:4910098 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:5110099 LOCAL_SET_GL_ERROR(
10100 GL_INVALID_OPERATION,
10101 "glBindTexImage2DCHROMIUM", "no texture bound");
[email protected]09d50362012-10-18 20:54:3710102 return;
10103 }
10104
10105 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10106 if (!gl_image) {
[email protected]ab09b612013-03-11 22:11:5110107 LOCAL_SET_GL_ERROR(
10108 GL_INVALID_OPERATION,
10109 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
[email protected]09d50362012-10-18 20:54:3710110 return;
10111 }
10112
[email protected]b8160812013-04-09 00:41:0410113 {
10114 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:3010115 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
[email protected]3c580122013-11-22 07:52:2610116 if (!gl_image->BindTexImage(target)) {
[email protected]b8160812013-04-09 00:41:0410117 LOCAL_SET_GL_ERROR(
10118 GL_INVALID_OPERATION,
10119 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10120 return;
10121 }
[email protected]09d50362012-10-18 20:54:3710122 }
10123
10124 gfx::Size size = gl_image->GetSize();
10125 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:4910126 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
[email protected]09d50362012-10-18 20:54:3710127 GL_RGBA, GL_UNSIGNED_BYTE, true);
[email protected]370eaf12013-05-18 09:19:4910128 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
[email protected]09d50362012-10-18 20:54:3710129}
10130
10131void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10132 GLenum target, GLint image_id) {
10133 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
[email protected]09d50362012-10-18 20:54:3710134
10135 // Default target might be conceptually valid, but disallow it to avoid
10136 // accidents.
[email protected]c986af502013-08-14 01:04:4410137 TextureRef* texture_ref =
10138 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]370eaf12013-05-18 09:19:4910139 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:5110140 LOCAL_SET_GL_ERROR(
10141 GL_INVALID_OPERATION,
10142 "glReleaseTexImage2DCHROMIUM", "no texture bound");
[email protected]09d50362012-10-18 20:54:3710143 return;
10144 }
10145
10146 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10147 if (!gl_image) {
[email protected]ab09b612013-03-11 22:11:5110148 LOCAL_SET_GL_ERROR(
10149 GL_INVALID_OPERATION,
10150 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
[email protected]09d50362012-10-18 20:54:3710151 return;
10152 }
10153
10154 // Do nothing when image is not currently bound.
[email protected]370eaf12013-05-18 09:19:4910155 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
[email protected]09d50362012-10-18 20:54:3710156 return;
10157
[email protected]b8160812013-04-09 00:41:0410158 {
10159 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:3010160 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
[email protected]3c580122013-11-22 07:52:2610161 gl_image->ReleaseTexImage(target);
[email protected]b8160812013-04-09 00:41:0410162 }
[email protected]09d50362012-10-18 20:54:3710163
10164 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:4910165 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
[email protected]09d50362012-10-18 20:54:3710166 GL_RGBA, GL_UNSIGNED_BYTE, false);
10167}
[email protected]d2a0e1a2012-08-12 02:25:0110168
[email protected]94307712012-11-16 23:26:1110169error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510170 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
[email protected]94307712012-11-16 23:26:1110171 Bucket* bucket = GetBucket(c.bucket_id);
10172 if (!bucket || bucket->size() == 0) {
10173 return error::kInvalidArguments;
10174 }
10175 std::string command_name;
10176 if (!bucket->GetAsString(&command_name)) {
10177 return error::kInvalidArguments;
10178 }
[email protected]fb97b662013-02-20 23:02:1410179 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10180 if (!gpu_tracer_->Begin(command_name)) {
[email protected]ab09b612013-03-11 22:11:5110181 LOCAL_SET_GL_ERROR(
10182 GL_INVALID_OPERATION,
10183 "glTraceBeginCHROMIUM", "unable to create begin trace");
[email protected]fb97b662013-02-20 23:02:1410184 return error::kNoError;
10185 }
[email protected]94307712012-11-16 23:26:1110186 return error::kNoError;
10187}
10188
10189void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
[email protected]fb97b662013-02-20 23:02:1410190 if (gpu_tracer_->CurrentName().empty()) {
[email protected]ab09b612013-03-11 22:11:5110191 LOCAL_SET_GL_ERROR(
10192 GL_INVALID_OPERATION,
10193 "glTraceEndCHROMIUM", "no trace begin found");
[email protected]94307712012-11-16 23:26:1110194 return;
10195 }
[email protected]fb97b662013-02-20 23:02:1410196 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10197 gpu_tracer_->End();
[email protected]94307712012-11-16 23:26:1110198}
10199
[email protected]2f143d482013-03-14 18:04:4910200void GLES2DecoderImpl::DoDrawBuffersEXT(
10201 GLsizei count, const GLenum* bufs) {
10202 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10203 LOCAL_SET_GL_ERROR(
10204 GL_INVALID_VALUE,
10205 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10206 return;
10207 }
10208
10209 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10210 if (framebuffer) {
10211 for (GLsizei i = 0; i < count; ++i) {
10212 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10213 bufs[i] != GL_NONE) {
10214 LOCAL_SET_GL_ERROR(
10215 GL_INVALID_OPERATION,
10216 "glDrawBuffersEXT",
10217 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10218 return;
10219 }
10220 }
10221 glDrawBuffersARB(count, bufs);
10222 framebuffer->SetDrawBuffers(count, bufs);
10223 } else { // backbuffer
10224 if (count > 1 ||
10225 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10226 LOCAL_SET_GL_ERROR(
10227 GL_INVALID_OPERATION,
10228 "glDrawBuffersEXT",
10229 "more than one buffer or bufs not GL_NONE or GL_BACK");
10230 return;
10231 }
10232 GLenum mapped_buf = bufs[0];
10233 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10234 bufs[0] == GL_BACK) {
10235 mapped_buf = GL_COLOR_ATTACHMENT0;
10236 }
10237 glDrawBuffersARB(count, &mapped_buf);
10238 group_->set_draw_buffer(bufs[0]);
10239 }
10240}
10241
[email protected]32145a92012-12-17 09:01:5910242bool GLES2DecoderImpl::ValidateAsyncTransfer(
10243 const char* function_name,
[email protected]85a4ac22013-05-31 01:58:4710244 TextureRef* texture_ref,
[email protected]32145a92012-12-17 09:01:5910245 GLenum target,
10246 GLint level,
10247 const void * data) {
10248 // We only support async uploads to 2D textures for now.
10249 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:5110250 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
[email protected]32145a92012-12-17 09:01:5910251 return false;
10252 }
10253 // We only support uploads to level zero for now.
10254 if (level != 0) {
[email protected]ab09b612013-03-11 22:11:5110255 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
[email protected]32145a92012-12-17 09:01:5910256 return false;
10257 }
10258 // A transfer buffer must be bound, even for asyncTexImage2D.
10259 if (data == NULL) {
[email protected]ab09b612013-03-11 22:11:5110260 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
[email protected]32145a92012-12-17 09:01:5910261 return false;
10262 }
10263 // We only support one async transfer in progress.
[email protected]85a4ac22013-05-31 01:58:4710264 if (!texture_ref ||
10265 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:5110266 LOCAL_SET_GL_ERROR(
10267 GL_INVALID_OPERATION,
[email protected]32145a92012-12-17 09:01:5910268 function_name, "transfer already in progress");
10269 return false;
10270 }
10271 return true;
10272}
10273
[email protected]69023942012-11-30 19:57:1610274error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510275 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
[email protected]69023942012-11-30 19:57:1610276 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
[email protected]69023942012-11-30 19:57:1610277 GLenum target = static_cast<GLenum>(c.target);
10278 GLint level = static_cast<GLint>(c.level);
[email protected]c986af502013-08-14 01:04:4410279 // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
10280 // unsigned integer for internalformat.
10281 GLenum internal_format = static_cast<GLenum>(c.internalformat);
[email protected]69023942012-11-30 19:57:1610282 GLsizei width = static_cast<GLsizei>(c.width);
10283 GLsizei height = static_cast<GLsizei>(c.height);
10284 GLint border = static_cast<GLint>(c.border);
10285 GLenum format = static_cast<GLenum>(c.format);
10286 GLenum type = static_cast<GLenum>(c.type);
10287 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10288 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10289 uint32 pixels_size;
[email protected]32145a92012-12-17 09:01:5910290
10291 // TODO(epenner): Move this and copies of this memory validation
10292 // into ValidateTexImage2D step.
[email protected]69023942012-11-30 19:57:1610293 if (!GLES2Util::ComputeImageDataSizes(
10294 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10295 NULL)) {
10296 return error::kOutOfBounds;
10297 }
10298 const void* pixels = NULL;
10299 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10300 pixels = GetSharedMemoryAs<const void*>(
10301 pixels_shm_id, pixels_shm_offset, pixels_size);
10302 if (!pixels) {
10303 return error::kOutOfBounds;
10304 }
10305 }
10306
[email protected]c986af502013-08-14 01:04:4410307 TextureManager::DoTextImage2DArguments args = {
10308 target, level, internal_format, width, height, border, format, type,
10309 pixels, pixels_size};
10310 TextureRef* texture_ref;
[email protected]32145a92012-12-17 09:01:5910311 // All the normal glTexSubImage2D validation.
[email protected]c986af502013-08-14 01:04:4410312 if (!texture_manager()->ValidateTexImage2D(
10313 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
[email protected]32145a92012-12-17 09:01:5910314 return error::kNoError;
10315 }
10316
10317 // Extra async validation.
[email protected]370eaf12013-05-18 09:19:4910318 Texture* texture = texture_ref->texture();
[email protected]32145a92012-12-17 09:01:5910319 if (!ValidateAsyncTransfer(
[email protected]85a4ac22013-05-31 01:58:4710320 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
[email protected]32145a92012-12-17 09:01:5910321 return error::kNoError;
10322
10323 // Don't allow async redefinition of a textures.
[email protected]02965c22013-03-09 02:40:0710324 if (texture->IsDefined()) {
[email protected]ab09b612013-03-11 22:11:5110325 LOCAL_SET_GL_ERROR(
10326 GL_INVALID_OPERATION,
[email protected]32145a92012-12-17 09:01:5910327 "glAsyncTexImage2DCHROMIUM", "already defined");
10328 return error::kNoError;
10329 }
10330
[email protected]7989c9e2013-01-23 06:39:2610331 if (!EnsureGPUMemoryAvailable(pixels_size)) {
[email protected]ab09b612013-03-11 22:11:5110332 LOCAL_SET_GL_ERROR(
10333 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
[email protected]7989c9e2013-01-23 06:39:2610334 return error::kNoError;
10335 }
10336
[email protected]32145a92012-12-17 09:01:5910337 // We know the memory/size is safe, so get the real shared memory since
10338 // it might need to be duped to prevent use-after-free of the memory.
[email protected]16ccec12013-02-28 03:40:2110339 gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id);
[email protected]32145a92012-12-17 09:01:5910340 base::SharedMemory* shared_memory = buffer.shared_memory;
10341 uint32 shm_size = buffer.size;
10342 uint32 shm_data_offset = c.pixels_shm_offset;
10343 uint32 shm_data_size = pixels_size;
10344
[email protected]5b3a8e02013-03-13 05:36:4410345 // Setup the parameters.
[email protected]8f1d2aa2013-05-10 23:45:3810346 AsyncTexImage2DParams tex_params = {
10347 target, level, static_cast<GLenum>(internal_format),
10348 width, height, border, format, type};
10349 AsyncMemoryParams mem_params = {
10350 shared_memory, shm_size, shm_data_offset, shm_data_size};
[email protected]32145a92012-12-17 09:01:5910351
[email protected]5b3a8e02013-03-13 05:36:4410352 // Set up the async state if needed, and make the texture
10353 // immutable so the async state stays valid. The level info
10354 // is set up lazily when the transfer completes.
[email protected]896425e2013-06-12 17:27:1810355 AsyncPixelTransferDelegate* delegate =
10356 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10357 tex_params);
[email protected]5b3a8e02013-03-13 05:36:4410358 texture->SetImmutable(true);
[email protected]32145a92012-12-17 09:01:5910359
[email protected]896425e2013-06-12 17:27:1810360 delegate->AsyncTexImage2D(
[email protected]5b3a8e02013-03-13 05:36:4410361 tex_params,
10362 mem_params,
10363 base::Bind(&TextureManager::SetLevelInfoFromParams,
[email protected]370eaf12013-05-18 09:19:4910364 // The callback is only invoked if the transfer delegate still
10365 // exists, which implies through manager->texture_ref->state
[email protected]5b3a8e02013-03-13 05:36:4410366 // ownership that both of these pointers are valid.
10367 base::Unretained(texture_manager()),
[email protected]370eaf12013-05-18 09:19:4910368 base::Unretained(texture_ref),
[email protected]5b3a8e02013-03-13 05:36:4410369 tex_params));
[email protected]f598f422012-12-07 08:30:0310370 return error::kNoError;
[email protected]69023942012-11-30 19:57:1610371}
10372
10373error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510374 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
[email protected]69023942012-11-30 19:57:1610375 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
[email protected]69023942012-11-30 19:57:1610376 GLenum target = static_cast<GLenum>(c.target);
10377 GLint level = static_cast<GLint>(c.level);
10378 GLint xoffset = static_cast<GLint>(c.xoffset);
10379 GLint yoffset = static_cast<GLint>(c.yoffset);
10380 GLsizei width = static_cast<GLsizei>(c.width);
10381 GLsizei height = static_cast<GLsizei>(c.height);
10382 GLenum format = static_cast<GLenum>(c.format);
10383 GLenum type = static_cast<GLenum>(c.type);
[email protected]32145a92012-12-17 09:01:5910384
10385 // TODO(epenner): Move this and copies of this memory validation
10386 // into ValidateTexSubImage2D step.
[email protected]69023942012-11-30 19:57:1610387 uint32 data_size;
10388 if (!GLES2Util::ComputeImageDataSizes(
10389 width, height, format, type, state_.unpack_alignment, &data_size,
10390 NULL, NULL)) {
10391 return error::kOutOfBounds;
10392 }
10393 const void* pixels = GetSharedMemoryAs<const void*>(
10394 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]32145a92012-12-17 09:01:5910395
10396 // All the normal glTexSubImage2D validation.
10397 error::Error error = error::kNoError;
10398 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10399 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10400 return error;
[email protected]69023942012-11-30 19:57:1610401 }
10402
[email protected]32145a92012-12-17 09:01:5910403 // Extra async validation.
[email protected]c986af502013-08-14 01:04:4410404 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10405 &state_, target);
[email protected]370eaf12013-05-18 09:19:4910406 Texture* texture = texture_ref->texture();
[email protected]32145a92012-12-17 09:01:5910407 if (!ValidateAsyncTransfer(
[email protected]85a4ac22013-05-31 01:58:4710408 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
[email protected]32145a92012-12-17 09:01:5910409 return error::kNoError;
10410
10411 // Guarantee async textures are always 'cleared' as follows:
10412 // - AsyncTexImage2D can not redefine an existing texture
10413 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10414 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10415 // - Textures become immutable after an async call.
10416 // This way we know in all cases that an async texture is always clear.
[email protected]02965c22013-03-09 02:40:0710417 if (!texture->SafeToRenderFrom()) {
[email protected]370eaf12013-05-18 09:19:4910418 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10419 target, level)) {
[email protected]ab09b612013-03-11 22:11:5110420 LOCAL_SET_GL_ERROR(
10421 GL_OUT_OF_MEMORY,
[email protected]b04e24c2013-01-08 18:35:2510422 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
[email protected]32145a92012-12-17 09:01:5910423 return error::kNoError;
10424 }
10425 }
10426
10427 // We know the memory/size is safe, so get the real shared memory since
10428 // it might need to be duped to prevent use-after-free of the memory.
[email protected]16ccec12013-02-28 03:40:2110429 gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id);
[email protected]32145a92012-12-17 09:01:5910430 base::SharedMemory* shared_memory = buffer.shared_memory;
10431 uint32 shm_size = buffer.size;
10432 uint32 shm_data_offset = c.data_shm_offset;
10433 uint32 shm_data_size = data_size;
10434
[email protected]5b3a8e02013-03-13 05:36:4410435 // Setup the parameters.
[email protected]2a7568a2013-05-09 23:12:0310436 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
[email protected]32145a92012-12-17 09:01:5910437 width, height, format, type};
[email protected]2a7568a2013-05-09 23:12:0310438 AsyncMemoryParams mem_params = {shared_memory, shm_size,
[email protected]32145a92012-12-17 09:01:5910439 shm_data_offset, shm_data_size};
[email protected]896425e2013-06-12 17:27:1810440 AsyncPixelTransferDelegate* delegate =
10441 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10442 if (!delegate) {
[email protected]5b3a8e02013-03-13 05:36:4410443 // TODO(epenner): We may want to enforce exclusive use
10444 // of async APIs in which case this should become an error,
10445 // (the texture should have been async defined).
[email protected]2a7568a2013-05-09 23:12:0310446 AsyncTexImage2DParams define_params = {target, level,
[email protected]5b3a8e02013-03-13 05:36:4410447 0, 0, 0, 0, 0, 0};
10448 texture->GetLevelSize(target, level, &define_params.width,
10449 &define_params.height);
10450 texture->GetLevelType(target, level, &define_params.type,
10451 &define_params.internal_format);
10452 // Set up the async state if needed, and make the texture
10453 // immutable so the async state stays valid.
[email protected]896425e2013-06-12 17:27:1810454 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
[email protected]85a4ac22013-05-31 01:58:4710455 texture_ref, define_params);
[email protected]5b3a8e02013-03-13 05:36:4410456 texture->SetImmutable(true);
10457 }
10458
[email protected]896425e2013-06-12 17:27:1810459 delegate->AsyncTexSubImage2D(tex_params, mem_params);
[email protected]32145a92012-12-17 09:01:5910460 return error::kNoError;
[email protected]69023942012-11-30 19:57:1610461}
10462
[email protected]a00c1f742013-03-05 17:02:1610463error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10464 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10465 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10466 GLenum target = static_cast<GLenum>(c.target);
10467
10468 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:5110469 LOCAL_SET_GL_ERROR(
10470 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
[email protected]a00c1f742013-03-05 17:02:1610471 return error::kNoError;
10472 }
[email protected]c986af502013-08-14 01:04:4410473 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10474 &state_, target);
[email protected]370eaf12013-05-18 09:19:4910475 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:5110476 LOCAL_SET_GL_ERROR(
10477 GL_INVALID_OPERATION,
10478 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
[email protected]a00c1f742013-03-05 17:02:1610479 return error::kNoError;
10480 }
[email protected]896425e2013-06-12 17:27:1810481 AsyncPixelTransferDelegate* delegate =
10482 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10483 if (!delegate) {
[email protected]370eaf12013-05-18 09:19:4910484 LOCAL_SET_GL_ERROR(
10485 GL_INVALID_OPERATION,
10486 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10487 return error::kNoError;
10488 }
[email protected]896425e2013-06-12 17:27:1810489 delegate->WaitForTransferCompletion();
[email protected]69a8701e2013-03-07 21:31:0910490 ProcessFinishedAsyncTransfers();
[email protected]a00c1f742013-03-05 17:02:1610491 return error::kNoError;
10492}
10493
[email protected]91c94eb2013-10-22 10:32:5410494void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10495 TextureRef* texture_ref) {
10496 Texture* texture = texture_ref->texture();
10497 DoDidUseTexImageIfNeeded(texture, texture->target());
10498}
10499
[email protected]96449d2c2009-11-25 00:01:3210500// Include the auto-generated part of this file. We split this because it means
10501// we can easily edit the non-auto generated parts right here in this file
10502// instead of having to edit some template or the code generator.
10503#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10504
10505} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:2510506} // namespace gpu