Roll src/third_party/skia d32087a:1052f51
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob410f1cc09454b3a3ccb13b86d5adc6f76efde3e8
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
7 #include <stdio.h>
9 #include <algorithm>
10 #include <cmath>
11 #include <list>
12 #include <map>
13 #include <queue>
15 #include "base/callback.h"
16 #include "base/callback_helpers.h"
17 #include "base/command_line.h"
18 #include "base/logging.h"
19 #include "base/memory/linked_ptr.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/numerics/safe_math.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/trace_event/trace_event.h"
25 #include "base/trace_event/trace_event_synthetic_delay.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/mailbox.h"
32 #include "gpu/command_buffer/service/buffer_manager.h"
33 #include "gpu/command_buffer/service/context_group.h"
34 #include "gpu/command_buffer/service/context_state.h"
35 #include "gpu/command_buffer/service/error_state.h"
36 #include "gpu/command_buffer/service/feature_info.h"
37 #include "gpu/command_buffer/service/framebuffer_manager.h"
38 #include "gpu/command_buffer/service/gl_utils.h"
39 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
40 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
41 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
42 #include "gpu/command_buffer/service/gpu_state_tracer.h"
43 #include "gpu/command_buffer/service/gpu_switches.h"
44 #include "gpu/command_buffer/service/gpu_tracer.h"
45 #include "gpu/command_buffer/service/image_manager.h"
46 #include "gpu/command_buffer/service/logger.h"
47 #include "gpu/command_buffer/service/mailbox_manager.h"
48 #include "gpu/command_buffer/service/memory_tracking.h"
49 #include "gpu/command_buffer/service/path_manager.h"
50 #include "gpu/command_buffer/service/program_manager.h"
51 #include "gpu/command_buffer/service/query_manager.h"
52 #include "gpu/command_buffer/service/renderbuffer_manager.h"
53 #include "gpu/command_buffer/service/shader_manager.h"
54 #include "gpu/command_buffer/service/shader_translator.h"
55 #include "gpu/command_buffer/service/texture_manager.h"
56 #include "gpu/command_buffer/service/valuebuffer_manager.h"
57 #include "gpu/command_buffer/service/vertex_array_manager.h"
58 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
59 #include "third_party/smhasher/src/City.h"
60 #include "ui/gfx/geometry/point.h"
61 #include "ui/gfx/geometry/rect.h"
62 #include "ui/gfx/geometry/size.h"
63 #include "ui/gfx/overlay_transform.h"
64 #include "ui/gl/gl_bindings.h"
65 #include "ui/gl/gl_context.h"
66 #include "ui/gl/gl_fence.h"
67 #include "ui/gl/gl_image.h"
68 #include "ui/gl/gl_implementation.h"
69 #include "ui/gl/gl_surface.h"
70 #include "ui/gl/gl_version_info.h"
71 #include "ui/gl/gpu_timing.h"
73 #if defined(OS_MACOSX)
74 #include <IOSurface/IOSurface.h>
75 // Note that this must be included after gl_bindings.h to avoid conflicts.
76 #include <OpenGL/CGLIOSurface.h>
77 #endif
79 namespace gpu {
80 namespace gles2 {
82 namespace {
84 const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
85 const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
86 const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
87 const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
89 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
90 0.0f, 1.0f, 0.0f, 0.0f,
91 0.0f, 0.0f, 1.0f, 0.0f,
92 0.0f, 0.0f, 0.0f, 1.0f};
94 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
95 GLint rangeMax,
96 GLint precision) {
97 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
100 void GetShaderPrecisionFormatImpl(GLenum shader_type,
101 GLenum precision_type,
102 GLint* range, GLint* precision) {
103 switch (precision_type) {
104 case GL_LOW_INT:
105 case GL_MEDIUM_INT:
106 case GL_HIGH_INT:
107 // These values are for a 32-bit twos-complement integer format.
108 range[0] = 31;
109 range[1] = 30;
110 *precision = 0;
111 break;
112 case GL_LOW_FLOAT:
113 case GL_MEDIUM_FLOAT:
114 case GL_HIGH_FLOAT:
115 // These values are for an IEEE single-precision floating-point format.
116 range[0] = 127;
117 range[1] = 127;
118 *precision = 23;
119 break;
120 default:
121 NOTREACHED();
122 break;
125 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
126 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
127 // This function is sometimes defined even though it's really just
128 // a stub, so we need to set range and precision as if it weren't
129 // defined before calling it.
130 // On Mac OS with some GPUs, calling this generates a
131 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
132 // platforms.
133 glGetShaderPrecisionFormat(shader_type, precision_type,
134 range, precision);
136 // TODO(brianderson): Make the following official workarounds.
138 // Some drivers have bugs where they report the ranges as a negative number.
139 // Taking the absolute value here shouldn't hurt because negative numbers
140 // aren't expected anyway.
141 range[0] = abs(range[0]);
142 range[1] = abs(range[1]);
144 // If the driver reports a precision for highp float that isn't actually
145 // highp, don't pretend like it's supported because shader compilation will
146 // fail anyway.
147 if (precision_type == GL_HIGH_FLOAT &&
148 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
149 range[0] = 0;
150 range[1] = 0;
151 *precision = 0;
156 gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
157 switch (plane_transform) {
158 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
159 return gfx::OVERLAY_TRANSFORM_NONE;
160 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
161 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
162 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
163 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
164 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
165 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
166 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
168 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
170 default:
171 return gfx::OVERLAY_TRANSFORM_INVALID;
175 template <typename MANAGER_TYPE, typename OBJECT_TYPE>
176 GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) {
177 DCHECK(manager);
178 GLuint client_id = 0;
179 if (object) {
180 manager->GetClientId(object->service_id(), &client_id);
182 return client_id;
185 struct Vec4f {
186 explicit Vec4f(const Vec4& data) {
187 data.GetValues(v);
190 GLfloat v[4];
193 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
194 // contains the other rectangle or shares an edge with the other rectangle.
195 bool CombineAdjacentRects(const gfx::Rect& rect1,
196 const gfx::Rect& rect2,
197 gfx::Rect* result) {
198 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
199 if (rect1.IsEmpty() || rect2.Contains(rect1)) {
200 *result = rect2;
201 return true;
204 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
205 if (rect2.IsEmpty() || rect1.Contains(rect2)) {
206 *result = rect1;
207 return true;
210 // Return the union of |rect1| and |rect2| if they share an edge.
211 if (rect1.SharesEdgeWith(rect2)) {
212 *result = gfx::UnionRects(rect1, rect2);
213 return true;
216 // Return false if it's not possible to combine |rect1| and |rect2|.
217 return false;
220 } // namespace
222 class GLES2DecoderImpl;
224 // Local versions of the SET_GL_ERROR macros
225 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
226 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
227 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
228 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
229 function_name, value, label)
230 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
231 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
232 function_name, pname)
233 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
234 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
235 function_name)
236 #define LOCAL_PEEK_GL_ERROR(function_name) \
237 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
238 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
239 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
240 #define LOCAL_PERFORMANCE_WARNING(msg) \
241 PerformanceWarning(__FILE__, __LINE__, msg)
242 #define LOCAL_RENDER_WARNING(msg) \
243 RenderWarning(__FILE__, __LINE__, msg)
245 // Check that certain assumptions the code makes are true. There are places in
246 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
247 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
248 // a few others) are 32bits. If they are not 32bits the code will have to change
249 // to call those GL functions with service side memory and then copy the results
250 // to shared memory, converting the sizes.
251 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
252 "GLint should be the same size as uint32");
253 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
254 "GLsizei should be the same size as uint32");
255 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
256 "GLfloat should be the same size as float");
258 // TODO(kbr): the use of this anonymous namespace core dumps the
259 // linker on Mac OS X 10.6 when the symbol ordering file is used
260 // namespace {
262 // Returns the address of the first byte after a struct.
263 template <typename T>
264 const void* AddressAfterStruct(const T& pod) {
265 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
268 // Returns the address of the frst byte after the struct or NULL if size >
269 // immediate_data_size.
270 template <typename RETURN_TYPE, typename COMMAND_TYPE>
271 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
272 uint32 size,
273 uint32 immediate_data_size) {
274 return (size <= immediate_data_size) ?
275 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
276 NULL;
279 // Computes the data size for certain gl commands like glUniform.
280 bool ComputeDataSize(
281 GLuint count,
282 size_t size,
283 unsigned int elements_per_unit,
284 uint32* dst) {
285 uint32 value;
286 if (!SafeMultiplyUint32(count, size, &value)) {
287 return false;
289 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
290 return false;
292 *dst = value;
293 return true;
296 // Return true if a character belongs to the ASCII subset as defined in
297 // GLSL ES 1.0 spec section 3.1.
298 static bool CharacterIsValidForGLES(unsigned char c) {
299 // Printing characters are valid except " $ ` @ \ ' DEL.
300 if (c >= 32 && c <= 126 &&
301 c != '"' &&
302 c != '$' &&
303 c != '`' &&
304 c != '@' &&
305 c != '\\' &&
306 c != '\'') {
307 return true;
309 // Horizontal tab, line feed, vertical tab, form feed, carriage return
310 // are also valid.
311 if (c >= 9 && c <= 13) {
312 return true;
315 return false;
318 static bool StringIsValidForGLES(const char* str) {
319 for (; *str; ++str) {
320 if (!CharacterIsValidForGLES(*str)) {
321 return false;
324 return true;
327 // This class prevents any GL errors that occur when it is in scope from
328 // being reported to the client.
329 class ScopedGLErrorSuppressor {
330 public:
331 explicit ScopedGLErrorSuppressor(
332 const char* function_name, ErrorState* error_state);
333 ~ScopedGLErrorSuppressor();
334 private:
335 const char* function_name_;
336 ErrorState* error_state_;
337 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
340 // Temporarily changes a decoder's bound texture and restore it when this
341 // object goes out of scope. Also temporarily switches to using active texture
342 // unit zero in case the client has changed that to something invalid.
343 class ScopedTextureBinder {
344 public:
345 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
346 ~ScopedTextureBinder();
348 private:
349 ContextState* state_;
350 GLenum target_;
351 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
354 // Temporarily changes a decoder's bound render buffer and restore it when this
355 // object goes out of scope.
356 class ScopedRenderBufferBinder {
357 public:
358 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
359 ~ScopedRenderBufferBinder();
361 private:
362 ContextState* state_;
363 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
366 // Temporarily changes a decoder's bound frame buffer and restore it when this
367 // object goes out of scope.
368 class ScopedFrameBufferBinder {
369 public:
370 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
371 ~ScopedFrameBufferBinder();
373 private:
374 GLES2DecoderImpl* decoder_;
375 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
378 // Temporarily changes a decoder's bound frame buffer to a resolved version of
379 // the multisampled offscreen render buffer if that buffer is multisampled, and,
380 // if it is bound or enforce_internal_framebuffer is true. If internal is
381 // true, the resolved framebuffer is not visible to the parent.
382 class ScopedResolvedFrameBufferBinder {
383 public:
384 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
385 bool enforce_internal_framebuffer,
386 bool internal);
387 ~ScopedResolvedFrameBufferBinder();
389 private:
390 GLES2DecoderImpl* decoder_;
391 bool resolve_and_bind_;
392 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
395 class ScopedModifyPixels {
396 public:
397 explicit ScopedModifyPixels(TextureRef* ref);
398 ~ScopedModifyPixels();
400 private:
401 TextureRef* ref_;
404 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
405 if (ref_)
406 ref_->texture()->OnWillModifyPixels();
409 ScopedModifyPixels::~ScopedModifyPixels() {
410 if (ref_)
411 ref_->texture()->OnDidModifyPixels();
414 class ScopedRenderTo {
415 public:
416 explicit ScopedRenderTo(Framebuffer* framebuffer)
417 : ScopedRenderTo(framebuffer, 0) {}
418 ScopedRenderTo(Framebuffer* framebuffer, GLenum attachment);
419 ~ScopedRenderTo();
421 private:
422 const Framebuffer* framebuffer_;
423 GLenum attachment_;
426 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer, GLenum attachment)
427 : framebuffer_(framebuffer),
428 attachment_(attachment) {
429 if (framebuffer_)
430 framebuffer_->OnWillRenderTo(attachment_);
433 ScopedRenderTo::~ScopedRenderTo() {
434 if (framebuffer_)
435 framebuffer_->OnDidRenderTo(attachment_);
438 // Encapsulates an OpenGL texture.
439 class BackTexture {
440 public:
441 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
442 ~BackTexture();
444 // Create a new render texture.
445 void Create();
447 // Set the initial size and format of a render texture or resize it.
448 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
450 // Copy the contents of the currently bound frame buffer.
451 void Copy(const gfx::Size& size, GLenum format);
453 // Destroy the render texture. This must be explicitly called before
454 // destroying this object.
455 void Destroy();
457 // Invalidate the texture. This can be used when a context is lost and it is
458 // not possible to make it current in order to free the resource.
459 void Invalidate();
461 GLuint id() const {
462 return id_;
465 gfx::Size size() const {
466 return size_;
469 private:
470 MemoryTypeTracker memory_tracker_;
471 ContextState* state_;
472 size_t bytes_allocated_;
473 GLuint id_;
474 gfx::Size size_;
475 DISALLOW_COPY_AND_ASSIGN(BackTexture);
478 // Encapsulates an OpenGL render buffer of any format.
479 class BackRenderbuffer {
480 public:
481 explicit BackRenderbuffer(
482 RenderbufferManager* renderbuffer_manager,
483 MemoryTracker* memory_tracker,
484 ContextState* state);
485 ~BackRenderbuffer();
487 // Create a new render buffer.
488 void Create();
490 // Set the initial size and format of a render buffer or resize it.
491 bool AllocateStorage(const FeatureInfo* feature_info,
492 const gfx::Size& size,
493 GLenum format,
494 GLsizei samples);
496 // Destroy the render buffer. This must be explicitly called before destroying
497 // this object.
498 void Destroy();
500 // Invalidate the render buffer. This can be used when a context is lost and
501 // it is not possible to make it current in order to free the resource.
502 void Invalidate();
504 GLuint id() const {
505 return id_;
508 private:
509 RenderbufferManager* renderbuffer_manager_;
510 MemoryTypeTracker memory_tracker_;
511 ContextState* state_;
512 size_t bytes_allocated_;
513 GLuint id_;
514 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
517 // Encapsulates an OpenGL frame buffer.
518 class BackFramebuffer {
519 public:
520 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
521 ~BackFramebuffer();
523 // Create a new frame buffer.
524 void Create();
526 // Attach a color render buffer to a frame buffer.
527 void AttachRenderTexture(BackTexture* texture);
529 // Attach a render buffer to a frame buffer. Note that this unbinds any
530 // currently bound frame buffer.
531 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
533 // Destroy the frame buffer. This must be explicitly called before destroying
534 // this object.
535 void Destroy();
537 // Invalidate the frame buffer. This can be used when a context is lost and it
538 // is not possible to make it current in order to free the resource.
539 void Invalidate();
541 // See glCheckFramebufferStatusEXT.
542 GLenum CheckStatus();
544 GLuint id() const {
545 return id_;
548 private:
549 GLES2DecoderImpl* decoder_;
550 GLuint id_;
551 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
554 struct FenceCallback {
555 FenceCallback()
556 : fence(gfx::GLFence::Create()) {
557 DCHECK(fence);
559 std::vector<base::Closure> callbacks;
560 scoped_ptr<gfx::GLFence> fence;
563 // } // anonymous namespace.
565 // static
566 const unsigned int GLES2Decoder::kDefaultStencilMask =
567 static_cast<unsigned int>(-1);
569 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
570 uint32* service_texture_id) {
571 return false;
574 GLES2Decoder::GLES2Decoder()
575 : initialized_(false),
576 debug_(false),
577 log_commands_(false),
578 unsafe_es3_apis_enabled_(false) {
581 GLES2Decoder::~GLES2Decoder() {
584 void GLES2Decoder::BeginDecoding() {}
586 void GLES2Decoder::EndDecoding() {}
588 // This class implements GLES2Decoder so we don't have to expose all the GLES2
589 // cmd stuff to outside this class.
590 class GLES2DecoderImpl : public GLES2Decoder,
591 public FramebufferManager::TextureDetachObserver,
592 public ErrorStateClient {
593 public:
594 explicit GLES2DecoderImpl(ContextGroup* group);
595 ~GLES2DecoderImpl() override;
597 // Overridden from AsyncAPIInterface.
598 Error DoCommand(unsigned int command,
599 unsigned int arg_count,
600 const void* args) override;
602 error::Error DoCommands(unsigned int num_commands,
603 const void* buffer,
604 int num_entries,
605 int* entries_processed) override;
607 template <bool DebugImpl>
608 error::Error DoCommandsImpl(unsigned int num_commands,
609 const void* buffer,
610 int num_entries,
611 int* entries_processed);
613 // Overridden from AsyncAPIInterface.
614 const char* GetCommandName(unsigned int command_id) const override;
616 // Overridden from GLES2Decoder.
617 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
618 const scoped_refptr<gfx::GLContext>& context,
619 bool offscreen,
620 const gfx::Size& offscreen_size,
621 const DisallowedFeatures& disallowed_features,
622 const std::vector<int32>& attribs) override;
623 void Destroy(bool have_context) override;
624 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
625 void ProduceFrontBuffer(const Mailbox& mailbox) override;
626 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
627 void UpdateParentTextureInfo();
628 bool MakeCurrent() override;
629 GLES2Util* GetGLES2Util() override { return &util_; }
630 gfx::GLContext* GetGLContext() override { return context_.get(); }
631 ContextGroup* GetContextGroup() override { return group_.get(); }
632 Capabilities GetCapabilities() override;
633 void RestoreState(const ContextState* prev_state) override;
635 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
636 void RestoreAllTextureUnitBindings(
637 const ContextState* prev_state) const override {
638 state_.RestoreAllTextureUnitBindings(prev_state);
640 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
641 state_.RestoreActiveTextureUnitBinding(target);
643 void RestoreBufferBindings() const override {
644 state_.RestoreBufferBindings();
646 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
647 void RestoreProgramBindings() const override {
648 state_.RestoreProgramBindings();
650 void RestoreTextureUnitBindings(unsigned unit) const override {
651 state_.RestoreTextureUnitBindings(unit, NULL);
653 void RestoreFramebufferBindings() const override;
654 void RestoreRenderbufferBindings() override;
655 void RestoreTextureState(unsigned service_id) const override;
657 void ClearAllAttributes() const override;
658 void RestoreAllAttributes() const override;
660 QueryManager* GetQueryManager() override { return query_manager_.get(); }
661 VertexArrayManager* GetVertexArrayManager() override {
662 return vertex_array_manager_.get();
664 ImageManager* GetImageManager() override { return image_manager_.get(); }
666 ValuebufferManager* GetValuebufferManager() override {
667 return valuebuffer_manager();
670 bool HasPendingQueries() const override;
671 void ProcessPendingQueries(bool did_finish) override;
673 bool HasMoreIdleWork() const override;
674 void PerformIdleWork() override;
676 void WaitForReadPixels(base::Closure callback) override;
678 void SetResizeCallback(
679 const base::Callback<void(gfx::Size, float)>& callback) override;
681 Logger* GetLogger() override;
683 void BeginDecoding() override;
684 void EndDecoding() override;
686 ErrorState* GetErrorState() override;
687 const ContextState* GetContextState() override { return &state_; }
689 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
690 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
692 void SetIgnoreCachedStateForTest(bool ignore) override;
693 void ProcessFinishedAsyncTransfers();
695 bool GetServiceTextureId(uint32 client_texture_id,
696 uint32* service_texture_id) override;
698 uint32 GetTextureUploadCount() override;
699 base::TimeDelta GetTotalTextureUploadTime() override;
700 base::TimeDelta GetTotalProcessingCommandsTime() override;
701 void AddProcessingCommandsTime(base::TimeDelta) override;
703 // Restores the current state to the user's settings.
704 void RestoreCurrentFramebufferBindings();
706 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
707 void ApplyDirtyState();
709 // These check the state of the currently bound framebuffer or the
710 // backbuffer if no framebuffer is bound.
711 // Check with all attached and enabled color attachments.
712 bool BoundFramebufferHasColorAttachmentWithAlpha();
713 bool BoundFramebufferHasDepthAttachment();
714 bool BoundFramebufferHasStencilAttachment();
716 error::ContextLostReason GetContextLostReason() override;
718 // Overridden from FramebufferManager::TextureDetachObserver:
719 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
721 // Overriden from ErrorStateClient.
722 void OnContextLostError() override;
723 void OnOutOfMemoryError() override;
725 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
726 void EnsureRenderbufferBound();
728 // Helpers to facilitate calling into compatible extensions.
729 static void RenderbufferStorageMultisampleHelper(
730 const FeatureInfo* feature_info,
731 GLenum target,
732 GLsizei samples,
733 GLenum internal_format,
734 GLsizei width,
735 GLsizei height);
737 void BlitFramebufferHelper(GLint srcX0,
738 GLint srcY0,
739 GLint srcX1,
740 GLint srcY1,
741 GLint dstX0,
742 GLint dstY0,
743 GLint dstX1,
744 GLint dstY1,
745 GLbitfield mask,
746 GLenum filter);
748 private:
749 friend class ScopedFrameBufferBinder;
750 friend class ScopedResolvedFrameBufferBinder;
751 friend class BackFramebuffer;
753 // Initialize or re-initialize the shader translator.
754 bool InitializeShaderTranslator();
756 void UpdateCapabilities();
758 // Helpers for the glGen and glDelete functions.
759 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
760 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
761 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
762 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
763 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
764 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
765 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
766 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
767 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
768 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
769 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
770 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
771 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
772 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
773 bool GenPathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
774 bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
776 // Workarounds
777 void OnFboChanged() const;
778 void OnUseFramebuffer() const;
780 error::ContextLostReason GetContextLostReasonFromResetStatus(
781 GLenum reset_status) const;
783 // TODO(gman): Cache these pointers?
784 BufferManager* buffer_manager() {
785 return group_->buffer_manager();
788 RenderbufferManager* renderbuffer_manager() {
789 return group_->renderbuffer_manager();
792 FramebufferManager* framebuffer_manager() {
793 return group_->framebuffer_manager();
796 ValuebufferManager* valuebuffer_manager() {
797 return group_->valuebuffer_manager();
800 PathManager* path_manager() { return group_->path_manager(); }
802 ProgramManager* program_manager() {
803 return group_->program_manager();
806 ShaderManager* shader_manager() {
807 return group_->shader_manager();
810 ShaderTranslatorCache* shader_translator_cache() {
811 return group_->shader_translator_cache();
814 const TextureManager* texture_manager() const {
815 return group_->texture_manager();
818 TextureManager* texture_manager() {
819 return group_->texture_manager();
822 MailboxManager* mailbox_manager() {
823 return group_->mailbox_manager();
826 ImageManager* image_manager() { return image_manager_.get(); }
828 VertexArrayManager* vertex_array_manager() {
829 return vertex_array_manager_.get();
832 MemoryTracker* memory_tracker() {
833 return group_->memory_tracker();
836 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
837 MemoryTracker* tracker = memory_tracker();
838 if (tracker) {
839 return tracker->EnsureGPUMemoryAvailable(estimated_size);
841 return true;
844 bool IsWebGLContext() const {
845 return webgl_version_ == 1 || webgl_version_ == 2;
848 bool IsOffscreenBufferMultisampled() const {
849 return offscreen_target_samples_ > 1;
852 // Creates a Texture for the given texture.
853 TextureRef* CreateTexture(
854 GLuint client_id, GLuint service_id) {
855 return texture_manager()->CreateTexture(client_id, service_id);
858 // Gets the texture info for the given texture. Returns NULL if none exists.
859 TextureRef* GetTexture(GLuint client_id) const {
860 return texture_manager()->GetTexture(client_id);
863 // Deletes the texture info for the given texture.
864 void RemoveTexture(GLuint client_id) {
865 texture_manager()->RemoveTexture(client_id);
868 // Get the size (in pixels) of the currently bound frame buffer (either FBO
869 // or regular back buffer).
870 gfx::Size GetBoundReadFrameBufferSize();
872 // Get the format/type of the currently bound frame buffer (either FBO or
873 // regular back buffer).
874 // If the color image is a renderbuffer, returns 0 for type.
875 GLenum GetBoundReadFrameBufferTextureType();
876 GLenum GetBoundReadFrameBufferInternalFormat();
878 // Get the i-th draw buffer's internal format from the bound framebuffer.
879 // If no framebuffer is bound, or no image is attached, or the DrawBuffers
880 // setting for that image is GL_NONE, return 0.
881 GLenum GetBoundColorDrawBufferInternalFormat(GLint drawbuffer_i);
883 void MarkDrawBufferAsCleared(GLenum buffer, GLint drawbuffer_i);
885 // Wrapper for CompressedTexImage2D commands.
886 error::Error DoCompressedTexImage2D(
887 GLenum target,
888 GLint level,
889 GLenum internal_format,
890 GLsizei width,
891 GLsizei height,
892 GLint border,
893 GLsizei image_size,
894 const void* data);
896 // Wrapper for CompressedTexImage3D commands.
897 error::Error DoCompressedTexImage3D(
898 GLenum target,
899 GLint level,
900 GLenum internal_format,
901 GLsizei width,
902 GLsizei height,
903 GLsizei depth,
904 GLint border,
905 GLsizei image_size,
906 const void* data);
908 // Wrapper for CompressedTexSubImage2D.
909 void DoCompressedTexSubImage2D(
910 GLenum target,
911 GLint level,
912 GLint xoffset,
913 GLint yoffset,
914 GLsizei width,
915 GLsizei height,
916 GLenum format,
917 GLsizei imageSize,
918 const void * data);
920 // Wrapper for CompressedTexSubImage3D.
921 void DoCompressedTexSubImage3D(
922 GLenum target,
923 GLint level,
924 GLint xoffset,
925 GLint yoffset,
926 GLint zoffset,
927 GLsizei width,
928 GLsizei height,
929 GLsizei depth,
930 GLenum format,
931 GLsizei image_size,
932 const void* data);
934 // Wrapper for CopyTexImage2D.
935 void DoCopyTexImage2D(
936 GLenum target,
937 GLint level,
938 GLenum internal_format,
939 GLint x,
940 GLint y,
941 GLsizei width,
942 GLsizei height,
943 GLint border);
945 // Wrapper for SwapBuffers.
946 void DoSwapBuffers();
948 // Wrapper for SwapInterval.
949 void DoSwapInterval(int interval);
951 // Wrapper for CopyTexSubImage2D.
952 void DoCopyTexSubImage2D(
953 GLenum target,
954 GLint level,
955 GLint xoffset,
956 GLint yoffset,
957 GLint x,
958 GLint y,
959 GLsizei width,
960 GLsizei height);
962 // Validation for TexSubImage2D.
963 bool ValidateTexSubImage2D(
964 error::Error* error,
965 const char* function_name,
966 GLenum target,
967 GLint level,
968 GLint xoffset,
969 GLint yoffset,
970 GLsizei width,
971 GLsizei height,
972 GLenum format,
973 GLenum type,
974 const void * data);
976 // Wrapper for TexSubImage2D.
977 error::Error DoTexSubImage2D(
978 GLenum target,
979 GLint level,
980 GLint xoffset,
981 GLint yoffset,
982 GLsizei width,
983 GLsizei height,
984 GLenum format,
985 GLenum type,
986 const void * data);
988 // Wrapper for TexSubImage3D.
989 error::Error DoTexSubImage3D(
990 GLenum target,
991 GLint level,
992 GLint xoffset,
993 GLint yoffset,
994 GLint zoffset,
995 GLsizei width,
996 GLsizei height,
997 GLsizei depth,
998 GLenum format,
999 GLenum type,
1000 const void * data);
1002 // Wrapper for TexImageIOSurface2DCHROMIUM.
1003 void DoTexImageIOSurface2DCHROMIUM(
1004 GLenum target,
1005 GLsizei width,
1006 GLsizei height,
1007 GLuint io_surface_id,
1008 GLuint plane);
1010 void DoCopyTextureCHROMIUM(GLenum target,
1011 GLuint source_id,
1012 GLuint dest_id,
1013 GLenum internal_format,
1014 GLenum dest_type,
1015 GLboolean unpack_flip_y,
1016 GLboolean unpack_premultiply_alpha,
1017 GLboolean unpack_unmultiply_alpha);
1019 void DoCopySubTextureCHROMIUM(GLenum target,
1020 GLuint source_id,
1021 GLuint dest_id,
1022 GLint xoffset,
1023 GLint yoffset,
1024 GLint x,
1025 GLint y,
1026 GLsizei width,
1027 GLsizei height,
1028 GLboolean unpack_flip_y,
1029 GLboolean unpack_premultiply_alpha,
1030 GLboolean unpack_unmultiply_alpha);
1032 void DoCompressedCopyTextureCHROMIUM(GLenum target,
1033 GLuint source_id,
1034 GLuint dest_id);
1036 void DoCompressedCopySubTextureCHROMIUM(GLenum target,
1037 GLuint source_id,
1038 GLuint dest_id,
1039 GLint xoffset,
1040 GLint yoffset,
1041 GLint x,
1042 GLint y,
1043 GLsizei width,
1044 GLsizei height);
1046 // Wrapper for TexStorage2DEXT.
1047 void DoTexStorage2DEXT(
1048 GLenum target,
1049 GLint levels,
1050 GLenum internal_format,
1051 GLsizei width,
1052 GLsizei height);
1054 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
1055 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
1056 const GLbyte* key);
1057 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
1058 GLenum target, const GLbyte* data);
1060 void EnsureTextureForClientId(GLenum target, GLuint client_id);
1061 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
1062 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
1063 GLuint client_id);
1064 void DoApplyScreenSpaceAntialiasingCHROMIUM();
1066 bool DoIsValuebufferCHROMIUM(GLuint client_id);
1067 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
1068 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
1069 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
1070 void DoUniformValueBufferCHROMIUM(GLint location,
1071 GLenum target,
1072 GLenum subscription);
1074 void DoBindTexImage2DCHROMIUM(
1075 GLenum target,
1076 GLint image_id);
1077 void DoReleaseTexImage2DCHROMIUM(
1078 GLenum target,
1079 GLint image_id);
1081 void DoTraceEndCHROMIUM(void);
1083 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1085 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1087 void DoFlushDriverCachesCHROMIUM(void);
1089 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1090 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1092 // Creates a Program for the given program.
1093 Program* CreateProgram(
1094 GLuint client_id, GLuint service_id) {
1095 return program_manager()->CreateProgram(client_id, service_id);
1098 // Gets the program info for the given program. Returns NULL if none exists.
1099 Program* GetProgram(GLuint client_id) {
1100 return program_manager()->GetProgram(client_id);
1103 #if defined(NDEBUG)
1104 void LogClientServiceMapping(
1105 const char* /* function_name */,
1106 GLuint /* client_id */,
1107 GLuint /* service_id */) {
1109 template<typename T>
1110 void LogClientServiceForInfo(
1111 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1113 #else
1114 void LogClientServiceMapping(
1115 const char* function_name, GLuint client_id, GLuint service_id) {
1116 if (service_logging_) {
1117 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1118 << ": client_id = " << client_id
1119 << ", service_id = " << service_id;
1122 template<typename T>
1123 void LogClientServiceForInfo(
1124 T* info, GLuint client_id, const char* function_name) {
1125 if (info) {
1126 LogClientServiceMapping(function_name, client_id, info->service_id());
1129 #endif
1131 // Gets the program info for the given program. If it's not a program
1132 // generates a GL error. Returns NULL if not program.
1133 Program* GetProgramInfoNotShader(
1134 GLuint client_id, const char* function_name) {
1135 Program* program = GetProgram(client_id);
1136 if (!program) {
1137 if (GetShader(client_id)) {
1138 LOCAL_SET_GL_ERROR(
1139 GL_INVALID_OPERATION, function_name, "shader passed for program");
1140 } else {
1141 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1144 LogClientServiceForInfo(program, client_id, function_name);
1145 return program;
1149 // Creates a Shader for the given shader.
1150 Shader* CreateShader(
1151 GLuint client_id,
1152 GLuint service_id,
1153 GLenum shader_type) {
1154 return shader_manager()->CreateShader(
1155 client_id, service_id, shader_type);
1158 // Gets the shader info for the given shader. Returns NULL if none exists.
1159 Shader* GetShader(GLuint client_id) {
1160 return shader_manager()->GetShader(client_id);
1163 // Gets the shader info for the given shader. If it's not a shader generates a
1164 // GL error. Returns NULL if not shader.
1165 Shader* GetShaderInfoNotProgram(
1166 GLuint client_id, const char* function_name) {
1167 Shader* shader = GetShader(client_id);
1168 if (!shader) {
1169 if (GetProgram(client_id)) {
1170 LOCAL_SET_GL_ERROR(
1171 GL_INVALID_OPERATION, function_name, "program passed for shader");
1172 } else {
1173 LOCAL_SET_GL_ERROR(
1174 GL_INVALID_VALUE, function_name, "unknown shader");
1177 LogClientServiceForInfo(shader, client_id, function_name);
1178 return shader;
1181 // Creates a buffer info for the given buffer.
1182 void CreateBuffer(GLuint client_id, GLuint service_id) {
1183 return buffer_manager()->CreateBuffer(client_id, service_id);
1186 // Gets the buffer info for the given buffer.
1187 Buffer* GetBuffer(GLuint client_id) {
1188 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1189 return buffer;
1192 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1193 // on glDeleteBuffers so we can make sure the user does not try to render
1194 // with deleted buffers.
1195 void RemoveBuffer(GLuint client_id);
1197 // Creates a framebuffer info for the given framebuffer.
1198 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1199 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1202 // Gets the framebuffer info for the given framebuffer.
1203 Framebuffer* GetFramebuffer(GLuint client_id) {
1204 return framebuffer_manager()->GetFramebuffer(client_id);
1207 // Removes the framebuffer info for the given framebuffer.
1208 void RemoveFramebuffer(GLuint client_id) {
1209 framebuffer_manager()->RemoveFramebuffer(client_id);
1212 // Creates a renderbuffer info for the given renderbuffer.
1213 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1214 return renderbuffer_manager()->CreateRenderbuffer(
1215 client_id, service_id);
1218 // Gets the renderbuffer info for the given renderbuffer.
1219 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1220 return renderbuffer_manager()->GetRenderbuffer(client_id);
1223 // Removes the renderbuffer info for the given renderbuffer.
1224 void RemoveRenderbuffer(GLuint client_id) {
1225 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1228 // Creates a valuebuffer info for the given valuebuffer.
1229 void CreateValuebuffer(GLuint client_id) {
1230 return valuebuffer_manager()->CreateValuebuffer(client_id);
1233 // Gets the valuebuffer info for a given valuebuffer.
1234 Valuebuffer* GetValuebuffer(GLuint client_id) {
1235 return valuebuffer_manager()->GetValuebuffer(client_id);
1238 // Removes the valuebuffer info for the given valuebuffer.
1239 void RemoveValuebuffer(GLuint client_id) {
1240 valuebuffer_manager()->RemoveValuebuffer(client_id);
1243 // Gets the vertex attrib manager for the given vertex array.
1244 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1245 VertexAttribManager* info =
1246 vertex_array_manager()->GetVertexAttribManager(client_id);
1247 return info;
1250 // Removes the vertex attrib manager for the given vertex array.
1251 void RemoveVertexAttribManager(GLuint client_id) {
1252 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1255 // Creates a vertex attrib manager for the given vertex array.
1256 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1257 GLuint client_id,
1258 GLuint service_id,
1259 bool client_visible) {
1260 return vertex_array_manager()->CreateVertexAttribManager(
1261 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1264 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1265 void DoBindUniformLocationCHROMIUM(
1266 GLuint client_id, GLint location, const char* name);
1268 error::Error GetAttribLocationHelper(
1269 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1270 const std::string& name_str);
1272 error::Error GetUniformLocationHelper(
1273 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1274 const std::string& name_str);
1276 error::Error GetFragDataLocationHelper(
1277 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1278 const std::string& name_str);
1280 // Wrapper for glShaderSource.
1281 void DoShaderSource(
1282 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1284 // Wrapper for glTransformFeedbackVaryings.
1285 void DoTransformFeedbackVaryings(
1286 GLuint client_program_id, GLsizei count, const char* const* varyings,
1287 GLenum buffer_mode);
1289 // Clear any textures used by the current program.
1290 bool ClearUnclearedTextures();
1292 // Clears any uncleared attachments attached to the given frame buffer.
1293 // Returns false if there was a generated GL error.
1294 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1296 // overridden from GLES2Decoder
1297 bool ClearLevel(Texture* texture,
1298 unsigned target,
1299 int level,
1300 unsigned format,
1301 unsigned type,
1302 int xoffset,
1303 int yoffset,
1304 int width,
1305 int height) override;
1307 // Restore all GL state that affects clearing.
1308 void RestoreClearState();
1310 // Remembers the state of some capabilities.
1311 // Returns: true if glEnable/glDisable should actually be called.
1312 bool SetCapabilityState(GLenum cap, bool enabled);
1314 // Check that the currently bound framebuffers are valid.
1315 // Generates GL error if not.
1316 bool CheckBoundFramebuffersValid(const char* func_name);
1318 // Check that the currently bound read framebuffer has a color image
1319 // attached. Generates GL error if not.
1320 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1322 // Check that the currently bound read framebuffer's color image
1323 // isn't the target texture of the glCopyTex{Sub}Image2D.
1324 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1326 // Check if a framebuffer meets our requirements.
1327 bool CheckFramebufferValid(
1328 Framebuffer* framebuffer,
1329 GLenum target,
1330 const char* func_name);
1332 bool CheckBoundDrawFramebufferValid(const char* func_name);
1334 // Check if the current valuebuffer exists and is valid. If not generates
1335 // the appropriate GL error. Returns true if the current valuebuffer is in
1336 // a usable state.
1337 bool CheckCurrentValuebuffer(const char* function_name);
1339 // Check if the current valuebuffer exists and is valiud and that the
1340 // value buffer is actually subscribed to the given subscription
1341 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1342 const char* function_name);
1344 // Check if the location can be used for the given subscription target. If not
1345 // generates the appropriate GL error. Returns true if the location is usable
1346 bool CheckSubscriptionTarget(GLint location,
1347 GLenum subscription,
1348 const char* function_name);
1350 // Checks if the current program exists and is valid. If not generates the
1351 // appropriate GL error. Returns true if the current program is in a usable
1352 // state.
1353 bool CheckCurrentProgram(const char* function_name);
1355 // Checks if the current program exists and is valid and that location is not
1356 // -1. If the current program is not valid generates the appropriate GL
1357 // error. Returns true if the current program is in a usable state and
1358 // location is not -1.
1359 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1361 // Checks if the current program samples a texture that is also the color
1362 // image of the current bound framebuffer, i.e., the source and destination
1363 // of the draw operation are the same.
1364 bool CheckDrawingFeedbackLoops();
1366 // Checks if |api_type| is valid for the given uniform
1367 // If the api type is not valid generates the appropriate GL
1368 // error. Returns true if |api_type| is valid for the uniform
1369 bool CheckUniformForApiType(const Program::UniformInfo* info,
1370 const char* function_name,
1371 Program::UniformApiType api_type);
1373 // Gets the type of a uniform for a location in the current program. Sets GL
1374 // errors if the current program is not valid. Returns true if the current
1375 // program is valid and the location exists. Adjusts count so it
1376 // does not overflow the uniform.
1377 bool PrepForSetUniformByLocation(GLint fake_location,
1378 const char* function_name,
1379 Program::UniformApiType api_type,
1380 GLint* real_location,
1381 GLenum* type,
1382 GLsizei* count);
1384 // Gets the service id for any simulated backbuffer fbo.
1385 GLuint GetBackbufferServiceId() const;
1387 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1388 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1390 // Helper for glGetVertexAttrib
1391 void GetVertexAttribHelper(
1392 const VertexAttrib* attrib, GLenum pname, GLint* param);
1394 // Wrapper for glActiveTexture
1395 void DoActiveTexture(GLenum texture_unit);
1397 // Wrapper for glAttachShader
1398 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1400 // Wrapper for glBindBuffer since we need to track the current targets.
1401 void DoBindBuffer(GLenum target, GLuint buffer);
1403 // Wrapper for glBindBufferBase since we need to track the current targets.
1404 void DoBindBufferBase(GLenum target, GLuint index, GLuint buffer);
1406 // Wrapper for glBindBufferRange since we need to track the current targets.
1407 void DoBindBufferRange(GLenum target, GLuint index, GLuint buffer,
1408 GLintptr offset, GLsizeiptr size);
1410 // Wrapper for glBindFramebuffer since we need to track the current targets.
1411 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1413 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1414 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1416 // Wrapper for glBindTexture since we need to track the current targets.
1417 void DoBindTexture(GLenum target, GLuint texture);
1419 // Wrapper for glBindVertexArrayOES
1420 void DoBindVertexArrayOES(GLuint array);
1421 void EmulateVertexArrayState();
1423 // Wrapper for glBlitFramebufferCHROMIUM.
1424 void DoBlitFramebufferCHROMIUM(
1425 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1426 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1427 GLbitfield mask, GLenum filter);
1429 // Wrapper for glBufferSubData.
1430 void DoBufferSubData(
1431 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1433 // Wrapper for glCheckFramebufferStatus
1434 GLenum DoCheckFramebufferStatus(GLenum target);
1436 // Wrapper for glClear*()
1437 error::Error DoClear(GLbitfield mask);
1438 void DoClearBufferiv(
1439 GLenum buffer, GLint drawbuffer, const GLint* value);
1440 void DoClearBufferuiv(
1441 GLenum buffer, GLint drawbuffer, const GLuint* value);
1442 void DoClearBufferfv(
1443 GLenum buffer, GLint drawbuffer, const GLfloat* value);
1444 void DoClearBufferfi(
1445 GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
1447 // Wrappers for various state.
1448 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1449 void DoSampleCoverage(GLclampf value, GLboolean invert);
1451 // Wrapper for glCompileShader.
1452 void DoCompileShader(GLuint shader);
1454 // Wrapper for glDetachShader
1455 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1457 // Wrapper for glDisable
1458 void DoDisable(GLenum cap);
1460 // Wrapper for glDisableVertexAttribArray.
1461 void DoDisableVertexAttribArray(GLuint index);
1463 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1464 // attachments.
1465 void DoDiscardFramebufferEXT(GLenum target,
1466 GLsizei numAttachments,
1467 const GLenum* attachments);
1469 // Wrapper for glEnable
1470 void DoEnable(GLenum cap);
1472 // Wrapper for glEnableVertexAttribArray.
1473 void DoEnableVertexAttribArray(GLuint index);
1475 // Wrapper for glFinish.
1476 void DoFinish();
1478 // Wrapper for glFlush.
1479 void DoFlush();
1481 // Wrapper for glFramebufferRenderbufffer.
1482 void DoFramebufferRenderbuffer(
1483 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1484 GLuint renderbuffer);
1486 // Wrapper for glFramebufferTexture2D.
1487 void DoFramebufferTexture2D(
1488 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1489 GLint level);
1491 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1492 void DoFramebufferTexture2DMultisample(
1493 GLenum target, GLenum attachment, GLenum textarget,
1494 GLuint texture, GLint level, GLsizei samples);
1496 // Common implementation for both DoFramebufferTexture2D wrappers.
1497 void DoFramebufferTexture2DCommon(const char* name,
1498 GLenum target, GLenum attachment, GLenum textarget,
1499 GLuint texture, GLint level, GLsizei samples);
1501 // Wrapper for glFramebufferTextureLayer.
1502 void DoFramebufferTextureLayer(
1503 GLenum target, GLenum attachment, GLuint texture, GLint level,
1504 GLint layer);
1506 // Wrapper for glGenerateMipmap
1507 void DoGenerateMipmap(GLenum target);
1509 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1510 // to account for different pname values defined in different extension
1511 // variants.
1512 GLenum AdjustGetPname(GLenum pname);
1514 // Wrapper for DoGetBooleanv.
1515 void DoGetBooleanv(GLenum pname, GLboolean* params);
1517 // Wrapper for DoGetFloatv.
1518 void DoGetFloatv(GLenum pname, GLfloat* params);
1520 // Wrapper for glGetFramebufferAttachmentParameteriv.
1521 void DoGetFramebufferAttachmentParameteriv(
1522 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1524 // Wrapper for glGetInteger64v.
1525 void DoGetInteger64v(GLenum pname, GLint64* params);
1527 // Wrapper for glGetIntegerv.
1528 void DoGetIntegerv(GLenum pname, GLint* params);
1530 // Gets the max value in a range in a buffer.
1531 GLuint DoGetMaxValueInBufferCHROMIUM(
1532 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1534 // Wrapper for glGetBufferParameteri64v.
1535 void DoGetBufferParameteri64v(
1536 GLenum target, GLenum pname, GLint64* params);
1538 // Wrapper for glGetBufferParameteriv.
1539 void DoGetBufferParameteriv(
1540 GLenum target, GLenum pname, GLint* params);
1542 // Wrapper for glGetProgramiv.
1543 void DoGetProgramiv(
1544 GLuint program_id, GLenum pname, GLint* params);
1546 // Wrapper for glRenderbufferParameteriv.
1547 void DoGetRenderbufferParameteriv(
1548 GLenum target, GLenum pname, GLint* params);
1550 // Wrapper for glGetShaderiv
1551 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1553 // Wrappers for glGetTexParameter.
1554 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1555 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1556 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1558 // Wrappers for glGetVertexAttrib.
1559 template <typename T>
1560 void DoGetVertexAttribImpl(GLuint index, GLenum pname, T* params);
1561 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
1562 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
1563 void DoGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
1564 void DoGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
1566 // Wrappers for glIsXXX functions.
1567 bool DoIsEnabled(GLenum cap);
1568 bool DoIsBuffer(GLuint client_id);
1569 bool DoIsFramebuffer(GLuint client_id);
1570 bool DoIsProgram(GLuint client_id);
1571 bool DoIsRenderbuffer(GLuint client_id);
1572 bool DoIsShader(GLuint client_id);
1573 bool DoIsTexture(GLuint client_id);
1574 bool DoIsVertexArrayOES(GLuint client_id);
1575 bool DoIsPathCHROMIUM(GLuint client_id);
1577 // Wrapper for glLinkProgram
1578 void DoLinkProgram(GLuint program);
1580 // Wrapper for glReadBuffer
1581 void DoReadBuffer(GLenum src);
1583 // Wrapper for glRenderbufferStorage.
1584 void DoRenderbufferStorage(
1585 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1587 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1588 void DoRenderbufferStorageMultisampleCHROMIUM(
1589 GLenum target, GLsizei samples, GLenum internalformat,
1590 GLsizei width, GLsizei height);
1592 // Handler for glRenderbufferStorageMultisampleEXT
1593 // (multisampled_render_to_texture).
1594 void DoRenderbufferStorageMultisampleEXT(
1595 GLenum target, GLsizei samples, GLenum internalformat,
1596 GLsizei width, GLsizei height);
1598 // Common validation for multisample extensions.
1599 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1600 GLenum internalformat,
1601 GLsizei width,
1602 GLsizei height);
1604 // Verifies that the currently bound multisample renderbuffer is valid
1605 // Very slow! Only done on platforms with driver bugs that return invalid
1606 // buffers under memory pressure
1607 bool VerifyMultisampleRenderbufferIntegrity(
1608 GLuint renderbuffer, GLenum format);
1610 // Wrapper for glReleaseShaderCompiler.
1611 void DoReleaseShaderCompiler() { }
1613 // Wrappers for glSamplerParameter*v functions.
1614 void DoSamplerParameterfv(
1615 GLuint sampler, GLenum pname, const GLfloat* params);
1616 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1618 // Wrappers for glTexParameter functions.
1619 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1620 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1621 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1622 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1624 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1625 // spec only these 2 functions can be used to set sampler uniforms.
1626 void DoUniform1i(GLint fake_location, GLint v0);
1627 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1628 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1629 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1630 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1632 void DoUniform1ui(GLint fake_location, GLuint v0);
1633 void DoUniform1uiv(GLint fake_location, GLsizei count, const GLuint* value);
1634 void DoUniform2uiv(GLint fake_location, GLsizei count, const GLuint* value);
1635 void DoUniform3uiv(GLint fake_location, GLsizei count, const GLuint* value);
1636 void DoUniform4uiv(GLint fake_location, GLsizei count, const GLuint* value);
1638 // Wrappers for glUniformfv because some drivers don't correctly accept
1639 // bool uniforms.
1640 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1641 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1642 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1643 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1645 void DoUniformMatrix2fv(
1646 GLint fake_location, GLsizei count, GLboolean transpose,
1647 const GLfloat* value);
1648 void DoUniformMatrix3fv(
1649 GLint fake_location, GLsizei count, GLboolean transpose,
1650 const GLfloat* value);
1651 void DoUniformMatrix4fv(
1652 GLint fake_location, GLsizei count, GLboolean transpose,
1653 const GLfloat* value);
1654 void DoUniformMatrix2x3fv(
1655 GLint fake_location, GLsizei count, GLboolean transpose,
1656 const GLfloat* value);
1657 void DoUniformMatrix2x4fv(
1658 GLint fake_location, GLsizei count, GLboolean transpose,
1659 const GLfloat* value);
1660 void DoUniformMatrix3x2fv(
1661 GLint fake_location, GLsizei count, GLboolean transpose,
1662 const GLfloat* value);
1663 void DoUniformMatrix3x4fv(
1664 GLint fake_location, GLsizei count, GLboolean transpose,
1665 const GLfloat* value);
1666 void DoUniformMatrix4x2fv(
1667 GLint fake_location, GLsizei count, GLboolean transpose,
1668 const GLfloat* value);
1669 void DoUniformMatrix4x3fv(
1670 GLint fake_location, GLsizei count, GLboolean transpose,
1671 const GLfloat* value);
1673 template <typename T>
1674 bool SetVertexAttribValue(
1675 const char* function_name, GLuint index, const T* value);
1677 // Wrappers for glVertexAttrib??
1678 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1679 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1680 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1681 void DoVertexAttrib4f(
1682 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1683 void DoVertexAttrib1fv(GLuint index, const GLfloat* v);
1684 void DoVertexAttrib2fv(GLuint index, const GLfloat* v);
1685 void DoVertexAttrib3fv(GLuint index, const GLfloat* v);
1686 void DoVertexAttrib4fv(GLuint index, const GLfloat* v);
1687 void DoVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
1688 void DoVertexAttribI4iv(GLuint index, const GLint* v);
1689 void DoVertexAttribI4ui(
1690 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
1691 void DoVertexAttribI4uiv(GLuint index, const GLuint* v);
1693 // Wrapper for glViewport
1694 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1696 // Wrapper for glUseProgram
1697 void DoUseProgram(GLuint program);
1699 // Wrapper for glValidateProgram.
1700 void DoValidateProgram(GLuint program_client_id);
1702 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1703 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1704 void DoPopGroupMarkerEXT(void);
1706 // Gets the number of values that will be returned by glGetXXX. Returns
1707 // false if pname is unknown.
1708 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1710 // Checks if the current program and vertex attributes are valid for drawing.
1711 bool IsDrawValid(
1712 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1713 GLsizei primcount);
1715 // Returns true if successful, simulated will be true if attrib0 was
1716 // simulated.
1717 bool SimulateAttrib0(
1718 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1719 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1721 // If an image is bound to texture, this will call Will/DidUseTexImage
1722 // if needed.
1723 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1724 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1726 // Returns false if textures were replaced.
1727 bool PrepareTexturesForRender();
1728 void RestoreStateForTextures();
1730 // Returns true if GL_FIXED attribs were simulated.
1731 bool SimulateFixedAttribs(
1732 const char* function_name,
1733 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1734 void RestoreStateForSimulatedFixedAttribs();
1736 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1737 // cases (primcount is always 1 for non-instanced).
1738 error::Error DoDrawArrays(
1739 const char* function_name,
1740 bool instanced, GLenum mode, GLint first, GLsizei count,
1741 GLsizei primcount);
1742 error::Error DoDrawElements(
1743 const char* function_name,
1744 bool instanced, GLenum mode, GLsizei count, GLenum type,
1745 int32 offset, GLsizei primcount);
1747 GLenum GetBindTargetForSamplerType(GLenum type) {
1748 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1749 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1750 switch (type) {
1751 case GL_SAMPLER_2D:
1752 return GL_TEXTURE_2D;
1753 case GL_SAMPLER_CUBE:
1754 return GL_TEXTURE_CUBE_MAP;
1755 case GL_SAMPLER_EXTERNAL_OES:
1756 return GL_TEXTURE_EXTERNAL_OES;
1757 case GL_SAMPLER_2D_RECT_ARB:
1758 return GL_TEXTURE_RECTANGLE_ARB;
1761 NOTREACHED();
1762 return 0;
1765 // Gets the framebuffer info for a particular target.
1766 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1767 Framebuffer* framebuffer = NULL;
1768 switch (target) {
1769 case GL_FRAMEBUFFER:
1770 case GL_DRAW_FRAMEBUFFER_EXT:
1771 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1772 break;
1773 case GL_READ_FRAMEBUFFER_EXT:
1774 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1775 break;
1776 default:
1777 NOTREACHED();
1778 break;
1780 return framebuffer;
1783 Renderbuffer* GetRenderbufferInfoForTarget(
1784 GLenum target) {
1785 Renderbuffer* renderbuffer = NULL;
1786 switch (target) {
1787 case GL_RENDERBUFFER:
1788 renderbuffer = state_.bound_renderbuffer.get();
1789 break;
1790 default:
1791 NOTREACHED();
1792 break;
1794 return renderbuffer;
1797 // Validates the program and location for a glGetUniform call and returns
1798 // a SizeResult setup to receive the result. Returns true if glGetUniform
1799 // should be called.
1800 template <class T>
1801 bool GetUniformSetup(GLuint program,
1802 GLint fake_location,
1803 uint32 shm_id,
1804 uint32 shm_offset,
1805 error::Error* error,
1806 GLint* real_location,
1807 GLuint* service_id,
1808 SizedResult<T>** result,
1809 GLenum* result_type,
1810 GLsizei* result_size);
1812 bool WasContextLost() const override;
1813 bool WasContextLostByRobustnessExtension() const override;
1814 void MarkContextLost(error::ContextLostReason reason) override;
1815 bool CheckResetStatus();
1817 #if defined(OS_MACOSX)
1818 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1819 #endif
1821 bool GetCompressedTexSizeInBytes(
1822 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1823 GLenum format, GLsizei* size_in_bytes);
1825 bool ValidateCompressedTexDimensions(
1826 const char* function_name, GLenum target, GLint level,
1827 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1828 bool ValidateCompressedTexFuncData(
1829 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1830 GLenum format, GLsizei size);
1831 bool ValidateCompressedTexSubDimensions(
1832 const char* function_name,
1833 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1834 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1835 Texture* texture);
1836 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1837 GLenum target,
1838 TextureRef* source_texture_ref,
1839 TextureRef* dest_texture_ref,
1840 GLenum dest_internal_format);
1841 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name,
1842 GLenum target,
1843 TextureRef* source_texture_ref,
1844 TextureRef* dest_texture_ref);
1846 void RenderWarning(const char* filename, int line, const std::string& msg);
1847 void PerformanceWarning(
1848 const char* filename, int line, const std::string& msg);
1850 const FeatureInfo::FeatureFlags& features() const {
1851 return feature_info_->feature_flags();
1854 const FeatureInfo::Workarounds& workarounds() const {
1855 return feature_info_->workarounds();
1858 bool ShouldDeferDraws() {
1859 return !offscreen_target_frame_buffer_.get() &&
1860 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1861 surface_->DeferDraws();
1864 bool ShouldDeferReads() {
1865 return !offscreen_target_frame_buffer_.get() &&
1866 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1867 surface_->DeferDraws();
1870 bool IsRobustnessSupported() {
1871 return has_robustness_extension_ &&
1872 context_->WasAllocatedUsingRobustnessExtension();
1875 error::Error WillAccessBoundFramebufferForDraw() {
1876 if (ShouldDeferDraws())
1877 return error::kDeferCommandUntilLater;
1878 if (!offscreen_target_frame_buffer_.get() &&
1879 !framebuffer_state_.bound_draw_framebuffer.get() &&
1880 !surface_->SetBackbufferAllocation(true))
1881 return error::kLostContext;
1882 return error::kNoError;
1885 error::Error WillAccessBoundFramebufferForRead() {
1886 if (ShouldDeferReads())
1887 return error::kDeferCommandUntilLater;
1888 if (!offscreen_target_frame_buffer_.get() &&
1889 !framebuffer_state_.bound_read_framebuffer.get() &&
1890 !surface_->SetBackbufferAllocation(true))
1891 return error::kLostContext;
1892 return error::kNoError;
1895 bool BackBufferHasAlpha() const {
1896 if (back_buffer_draw_buffer_ == GL_NONE)
1897 return false;
1898 if (offscreen_target_frame_buffer_.get()) {
1899 return (offscreen_target_color_format_ == GL_RGBA ||
1900 offscreen_target_color_format_ == GL_RGBA8);
1902 return (back_buffer_color_format_ == GL_RGBA ||
1903 back_buffer_color_format_ == GL_RGBA8);
1906 // Set remaining commands to process to 0 to force DoCommands to return
1907 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1908 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1910 void ProcessPendingReadPixels(bool did_finish);
1911 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1913 // Generate a member function prototype for each command in an automated and
1914 // typesafe way.
1915 #define GLES2_CMD_OP(name) \
1916 Error Handle##name(uint32 immediate_data_size, const void* data);
1918 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1920 #undef GLES2_CMD_OP
1922 // The GL context this decoder renders to on behalf of the client.
1923 scoped_refptr<gfx::GLSurface> surface_;
1924 scoped_refptr<gfx::GLContext> context_;
1926 // The ContextGroup for this decoder uses to track resources.
1927 scoped_refptr<ContextGroup> group_;
1929 DebugMarkerManager debug_marker_manager_;
1930 Logger logger_;
1932 // All the state for this context.
1933 ContextState state_;
1935 // Current width and height of the offscreen frame buffer.
1936 gfx::Size offscreen_size_;
1938 // Util to help with GL.
1939 GLES2Util util_;
1941 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1942 GLuint attrib_0_buffer_id_;
1944 // The value currently in attrib_0.
1945 Vec4 attrib_0_value_;
1947 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1948 bool attrib_0_buffer_matches_value_;
1950 // The size of attrib 0.
1951 GLsizei attrib_0_size_;
1953 // The buffer used to simulate GL_FIXED attribs.
1954 GLuint fixed_attrib_buffer_id_;
1956 // The size of fiixed attrib buffer.
1957 GLsizei fixed_attrib_buffer_size_;
1959 // The offscreen frame buffer that the client renders to. With EGL, the
1960 // depth and stencil buffers are separate. With regular GL there is a single
1961 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1962 // offscreen_target_stencil_render_buffer_ is unused.
1963 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1964 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1965 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1966 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1967 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1968 GLenum offscreen_target_color_format_;
1969 GLenum offscreen_target_depth_format_;
1970 GLenum offscreen_target_stencil_format_;
1971 GLsizei offscreen_target_samples_;
1972 GLboolean offscreen_target_buffer_preserved_;
1974 // The copy that is saved when SwapBuffers is called.
1975 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1976 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1977 scoped_refptr<TextureRef>
1978 offscreen_saved_color_texture_info_;
1980 // The copy that is used as the destination for multi-sample resolves.
1981 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1982 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1983 GLenum offscreen_saved_color_format_;
1985 scoped_ptr<QueryManager> query_manager_;
1987 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1989 scoped_ptr<ImageManager> image_manager_;
1991 base::Callback<void(gfx::Size, float)> resize_callback_;
1993 WaitSyncPointCallback wait_sync_point_callback_;
1995 ShaderCacheCallback shader_cache_callback_;
1997 // The format of the back buffer_
1998 GLenum back_buffer_color_format_;
1999 bool back_buffer_has_depth_;
2000 bool back_buffer_has_stencil_;
2002 // Tracks read buffer and draw buffer for backbuffer, whether it's onscreen
2003 // or offscreen.
2004 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
2005 // setting is set correctly when SwapBuffers().
2006 GLenum back_buffer_read_buffer_;
2007 GLenum back_buffer_draw_buffer_;
2009 bool surfaceless_;
2011 // Backbuffer attachments that are currently undefined.
2012 uint32 backbuffer_needs_clear_bits_;
2014 // The current decoder error communicates the decoder error through command
2015 // processing functions that do not return the error value. Should be set only
2016 // if not returning an error.
2017 error::Error current_decoder_error_;
2019 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
2020 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
2022 DisallowedFeatures disallowed_features_;
2024 // Cached from ContextGroup
2025 const Validators* validators_;
2026 scoped_refptr<FeatureInfo> feature_info_;
2028 int frame_number_;
2030 // Number of commands remaining to be processed in DoCommands().
2031 int commands_to_process_;
2033 bool has_robustness_extension_;
2034 error::ContextLostReason context_lost_reason_;
2035 bool context_was_lost_;
2036 bool reset_by_robustness_extension_;
2037 bool supports_post_sub_buffer_;
2039 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2040 // 0: other types
2041 // 1: WebGL 1
2042 // 2: WebGL 2
2043 unsigned webgl_version_;
2045 // These flags are used to override the state of the shared feature_info_
2046 // member. Because the same FeatureInfo instance may be shared among many
2047 // contexts, the assumptions on the availablity of extensions in WebGL
2048 // contexts may be broken. These flags override the shared state to preserve
2049 // WebGL semantics.
2050 bool derivatives_explicitly_enabled_;
2051 bool frag_depth_explicitly_enabled_;
2052 bool draw_buffers_explicitly_enabled_;
2053 bool shader_texture_lod_explicitly_enabled_;
2055 bool compile_shader_always_succeeds_;
2057 // An optional behaviour to lose the context and group when OOM.
2058 bool lose_context_when_out_of_memory_;
2060 // Log extra info.
2061 bool service_logging_;
2063 #if defined(OS_MACOSX)
2064 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
2065 TextureToIOSurfaceMap texture_to_io_surface_map_;
2066 #endif
2068 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
2069 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
2071 // Cached values of the currently assigned viewport dimensions.
2072 GLsizei viewport_max_width_;
2073 GLsizei viewport_max_height_;
2075 // Command buffer stats.
2076 base::TimeDelta total_processing_commands_time_;
2078 // States related to each manager.
2079 DecoderTextureState texture_state_;
2080 DecoderFramebufferState framebuffer_state_;
2082 scoped_ptr<GPUTracer> gpu_tracer_;
2083 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
2084 const unsigned char* gpu_decoder_category_;
2085 int gpu_trace_level_;
2086 bool gpu_trace_commands_;
2087 bool gpu_debug_commands_;
2089 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
2091 // Used to validate multisample renderbuffers if needed
2092 GLuint validation_texture_;
2093 GLuint validation_fbo_multisample_;
2094 GLuint validation_fbo_;
2096 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
2097 uint32 immediate_data_size,
2098 const void* data);
2100 // A struct to hold info about each command.
2101 struct CommandInfo {
2102 CmdHandler cmd_handler;
2103 uint8 arg_flags; // How to handle the arguments for this command
2104 uint8 cmd_flags; // How to handle this command
2105 uint16 arg_count; // How many arguments are expected for this command.
2108 // A table of CommandInfo for all the commands.
2109 static const CommandInfo command_info[kNumCommands - kStartPoint];
2111 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
2114 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
2115 #define GLES2_CMD_OP(name) \
2117 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2118 cmds::name::cmd_flags, \
2119 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2121 , /* NOLINT */
2122 GLES2_COMMAND_LIST(GLES2_CMD_OP)
2123 #undef GLES2_CMD_OP
2126 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2127 const char* function_name, ErrorState* error_state)
2128 : function_name_(function_name),
2129 error_state_(error_state) {
2130 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
2133 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2134 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
2137 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
2138 TextureUnit& info = state->texture_units[0];
2139 GLuint last_id;
2140 scoped_refptr<TextureRef> texture_ref;
2141 switch (target) {
2142 case GL_TEXTURE_2D:
2143 texture_ref = info.bound_texture_2d;
2144 break;
2145 case GL_TEXTURE_CUBE_MAP:
2146 texture_ref = info.bound_texture_cube_map;
2147 break;
2148 case GL_TEXTURE_EXTERNAL_OES:
2149 texture_ref = info.bound_texture_external_oes;
2150 break;
2151 case GL_TEXTURE_RECTANGLE_ARB:
2152 texture_ref = info.bound_texture_rectangle_arb;
2153 break;
2154 default:
2155 NOTREACHED();
2156 break;
2158 if (texture_ref.get()) {
2159 last_id = texture_ref->service_id();
2160 } else {
2161 last_id = 0;
2164 glBindTexture(target, last_id);
2165 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2168 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2169 GLuint id,
2170 GLenum target)
2171 : state_(state),
2172 target_(target) {
2173 ScopedGLErrorSuppressor suppressor(
2174 "ScopedTextureBinder::ctor", state_->GetErrorState());
2176 // TODO(apatrick): Check if there are any other states that need to be reset
2177 // before binding a new texture.
2178 glActiveTexture(GL_TEXTURE0);
2179 glBindTexture(target, id);
2182 ScopedTextureBinder::~ScopedTextureBinder() {
2183 ScopedGLErrorSuppressor suppressor(
2184 "ScopedTextureBinder::dtor", state_->GetErrorState());
2185 RestoreCurrentTextureBindings(state_, target_);
2188 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2189 GLuint id)
2190 : state_(state) {
2191 ScopedGLErrorSuppressor suppressor(
2192 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2193 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2196 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2197 ScopedGLErrorSuppressor suppressor(
2198 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2199 state_->RestoreRenderbufferBindings();
2202 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2203 GLuint id)
2204 : decoder_(decoder) {
2205 ScopedGLErrorSuppressor suppressor(
2206 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2207 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2208 decoder->OnFboChanged();
2211 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2212 ScopedGLErrorSuppressor suppressor(
2213 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2214 decoder_->RestoreCurrentFramebufferBindings();
2217 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2218 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2219 : decoder_(decoder) {
2220 resolve_and_bind_ = (
2221 decoder_->offscreen_target_frame_buffer_.get() &&
2222 decoder_->IsOffscreenBufferMultisampled() &&
2223 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2224 enforce_internal_framebuffer));
2225 if (!resolve_and_bind_)
2226 return;
2228 ScopedGLErrorSuppressor suppressor(
2229 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2230 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2231 decoder_->offscreen_target_frame_buffer_->id());
2232 GLuint targetid;
2233 if (internal) {
2234 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2235 decoder_->offscreen_resolved_frame_buffer_.reset(
2236 new BackFramebuffer(decoder_));
2237 decoder_->offscreen_resolved_frame_buffer_->Create();
2238 decoder_->offscreen_resolved_color_texture_.reset(
2239 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2240 decoder_->offscreen_resolved_color_texture_->Create();
2242 DCHECK(decoder_->offscreen_saved_color_format_);
2243 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2244 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2245 false);
2246 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2247 decoder_->offscreen_resolved_color_texture_.get());
2248 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2249 GL_FRAMEBUFFER_COMPLETE) {
2250 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2251 << "because offscreen resolved FBO was incomplete.";
2252 return;
2255 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2256 } else {
2257 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2259 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2260 const int width = decoder_->offscreen_size_.width();
2261 const int height = decoder_->offscreen_size_.height();
2262 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2263 decoder->BlitFramebufferHelper(0,
2265 width,
2266 height,
2269 width,
2270 height,
2271 GL_COLOR_BUFFER_BIT,
2272 GL_NEAREST);
2273 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2276 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2277 if (!resolve_and_bind_)
2278 return;
2280 ScopedGLErrorSuppressor suppressor(
2281 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2282 decoder_->RestoreCurrentFramebufferBindings();
2283 if (decoder_->state_.enable_flags.scissor_test) {
2284 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2288 BackTexture::BackTexture(
2289 MemoryTracker* memory_tracker,
2290 ContextState* state)
2291 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2292 state_(state),
2293 bytes_allocated_(0),
2294 id_(0) {
2297 BackTexture::~BackTexture() {
2298 // This does not destroy the render texture because that would require that
2299 // the associated GL context was current. Just check that it was explicitly
2300 // destroyed.
2301 DCHECK_EQ(id_, 0u);
2304 void BackTexture::Create() {
2305 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2306 state_->GetErrorState());
2307 Destroy();
2308 glGenTextures(1, &id_);
2309 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2310 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2313 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2315 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2316 // never called on an offscreen context, no data will ever be uploaded to the
2317 // saved offscreen color texture (it is deferred until to when SwapBuffers
2318 // is called). My idea is that some nvidia drivers might have a bug where
2319 // deleting a texture that has never been populated might cause a
2320 // crash.
2321 glTexImage2D(
2322 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2324 bytes_allocated_ = 16u * 16u * 4u;
2325 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2328 bool BackTexture::AllocateStorage(
2329 const gfx::Size& size, GLenum format, bool zero) {
2330 DCHECK_NE(id_, 0u);
2331 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2332 state_->GetErrorState());
2333 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2334 uint32 image_size = 0;
2335 GLES2Util::ComputeImageDataSizes(
2336 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2337 NULL, NULL);
2339 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2340 return false;
2343 scoped_ptr<char[]> zero_data;
2344 if (zero) {
2345 zero_data.reset(new char[image_size]);
2346 memset(zero_data.get(), 0, image_size);
2349 glTexImage2D(GL_TEXTURE_2D,
2350 0, // mip level
2351 format,
2352 size.width(),
2353 size.height(),
2354 0, // border
2355 format,
2356 GL_UNSIGNED_BYTE,
2357 zero_data.get());
2359 size_ = size;
2361 bool success = glGetError() == GL_NO_ERROR;
2362 if (success) {
2363 memory_tracker_.TrackMemFree(bytes_allocated_);
2364 bytes_allocated_ = image_size;
2365 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2367 return success;
2370 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2371 DCHECK_NE(id_, 0u);
2372 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2373 state_->GetErrorState());
2374 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2375 glCopyTexImage2D(GL_TEXTURE_2D,
2376 0, // level
2377 format,
2378 0, 0,
2379 size.width(),
2380 size.height(),
2381 0); // border
2384 void BackTexture::Destroy() {
2385 if (id_ != 0) {
2386 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2387 state_->GetErrorState());
2388 glDeleteTextures(1, &id_);
2389 id_ = 0;
2391 memory_tracker_.TrackMemFree(bytes_allocated_);
2392 bytes_allocated_ = 0;
2395 void BackTexture::Invalidate() {
2396 id_ = 0;
2399 BackRenderbuffer::BackRenderbuffer(
2400 RenderbufferManager* renderbuffer_manager,
2401 MemoryTracker* memory_tracker,
2402 ContextState* state)
2403 : renderbuffer_manager_(renderbuffer_manager),
2404 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2405 state_(state),
2406 bytes_allocated_(0),
2407 id_(0) {
2410 BackRenderbuffer::~BackRenderbuffer() {
2411 // This does not destroy the render buffer because that would require that
2412 // the associated GL context was current. Just check that it was explicitly
2413 // destroyed.
2414 DCHECK_EQ(id_, 0u);
2417 void BackRenderbuffer::Create() {
2418 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2419 state_->GetErrorState());
2420 Destroy();
2421 glGenRenderbuffersEXT(1, &id_);
2424 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2425 const gfx::Size& size,
2426 GLenum format,
2427 GLsizei samples) {
2428 ScopedGLErrorSuppressor suppressor(
2429 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2430 ScopedRenderBufferBinder binder(state_, id_);
2432 uint32 estimated_size = 0;
2433 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2434 size.width(), size.height(), samples, format, &estimated_size)) {
2435 return false;
2438 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2439 return false;
2442 if (samples <= 1) {
2443 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2444 format,
2445 size.width(),
2446 size.height());
2447 } else {
2448 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2449 GL_RENDERBUFFER,
2450 samples,
2451 format,
2452 size.width(),
2453 size.height());
2455 bool success = glGetError() == GL_NO_ERROR;
2456 if (success) {
2457 // Mark the previously allocated bytes as free.
2458 memory_tracker_.TrackMemFree(bytes_allocated_);
2459 bytes_allocated_ = estimated_size;
2460 // Track the newly allocated bytes.
2461 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2463 return success;
2466 void BackRenderbuffer::Destroy() {
2467 if (id_ != 0) {
2468 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2469 state_->GetErrorState());
2470 glDeleteRenderbuffersEXT(1, &id_);
2471 id_ = 0;
2473 memory_tracker_.TrackMemFree(bytes_allocated_);
2474 bytes_allocated_ = 0;
2477 void BackRenderbuffer::Invalidate() {
2478 id_ = 0;
2481 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2482 : decoder_(decoder),
2483 id_(0) {
2486 BackFramebuffer::~BackFramebuffer() {
2487 // This does not destroy the frame buffer because that would require that
2488 // the associated GL context was current. Just check that it was explicitly
2489 // destroyed.
2490 DCHECK_EQ(id_, 0u);
2493 void BackFramebuffer::Create() {
2494 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2495 decoder_->GetErrorState());
2496 Destroy();
2497 glGenFramebuffersEXT(1, &id_);
2500 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2501 DCHECK_NE(id_, 0u);
2502 ScopedGLErrorSuppressor suppressor(
2503 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2504 ScopedFrameBufferBinder binder(decoder_, id_);
2505 GLuint attach_id = texture ? texture->id() : 0;
2506 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2507 GL_COLOR_ATTACHMENT0,
2508 GL_TEXTURE_2D,
2509 attach_id,
2513 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2514 BackRenderbuffer* render_buffer) {
2515 DCHECK_NE(id_, 0u);
2516 ScopedGLErrorSuppressor suppressor(
2517 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2518 ScopedFrameBufferBinder binder(decoder_, id_);
2519 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2520 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2521 target,
2522 GL_RENDERBUFFER,
2523 attach_id);
2526 void BackFramebuffer::Destroy() {
2527 if (id_ != 0) {
2528 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2529 decoder_->GetErrorState());
2530 glDeleteFramebuffersEXT(1, &id_);
2531 id_ = 0;
2535 void BackFramebuffer::Invalidate() {
2536 id_ = 0;
2539 GLenum BackFramebuffer::CheckStatus() {
2540 DCHECK_NE(id_, 0u);
2541 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2542 decoder_->GetErrorState());
2543 ScopedFrameBufferBinder binder(decoder_, id_);
2544 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2547 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2548 return new GLES2DecoderImpl(group);
2551 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2552 : GLES2Decoder(),
2553 group_(group),
2554 logger_(&debug_marker_manager_),
2555 state_(group_->feature_info(), this, &logger_),
2556 attrib_0_buffer_id_(0),
2557 attrib_0_buffer_matches_value_(true),
2558 attrib_0_size_(0),
2559 fixed_attrib_buffer_id_(0),
2560 fixed_attrib_buffer_size_(0),
2561 offscreen_target_color_format_(0),
2562 offscreen_target_depth_format_(0),
2563 offscreen_target_stencil_format_(0),
2564 offscreen_target_samples_(0),
2565 offscreen_target_buffer_preserved_(true),
2566 offscreen_saved_color_format_(0),
2567 back_buffer_color_format_(0),
2568 back_buffer_has_depth_(false),
2569 back_buffer_has_stencil_(false),
2570 back_buffer_read_buffer_(GL_BACK),
2571 back_buffer_draw_buffer_(GL_BACK),
2572 surfaceless_(false),
2573 backbuffer_needs_clear_bits_(0),
2574 current_decoder_error_(error::kNoError),
2575 validators_(group_->feature_info()->validators()),
2576 feature_info_(group_->feature_info()),
2577 frame_number_(0),
2578 has_robustness_extension_(false),
2579 context_lost_reason_(error::kUnknown),
2580 context_was_lost_(false),
2581 reset_by_robustness_extension_(false),
2582 supports_post_sub_buffer_(false),
2583 webgl_version_(0),
2584 derivatives_explicitly_enabled_(false),
2585 frag_depth_explicitly_enabled_(false),
2586 draw_buffers_explicitly_enabled_(false),
2587 shader_texture_lod_explicitly_enabled_(false),
2588 compile_shader_always_succeeds_(false),
2589 lose_context_when_out_of_memory_(false),
2590 service_logging_(base::CommandLine::InitializedForCurrentProcess()
2591 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2592 switches::kEnableGPUServiceLoggingGPU)
2593 : false),
2594 viewport_max_width_(0),
2595 viewport_max_height_(0),
2596 texture_state_(group_->feature_info()->workarounds()),
2597 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2598 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2599 gpu_trace_level_(2),
2600 gpu_trace_commands_(false),
2601 gpu_debug_commands_(false),
2602 validation_texture_(0),
2603 validation_fbo_multisample_(0),
2604 validation_fbo_(0) {
2605 DCHECK(group);
2608 GLES2DecoderImpl::~GLES2DecoderImpl() {
2611 bool GLES2DecoderImpl::Initialize(
2612 const scoped_refptr<gfx::GLSurface>& surface,
2613 const scoped_refptr<gfx::GLContext>& context,
2614 bool offscreen,
2615 const gfx::Size& offscreen_size,
2616 const DisallowedFeatures& disallowed_features,
2617 const std::vector<int32>& attribs) {
2618 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2619 DCHECK(context->IsCurrent(surface.get()));
2620 DCHECK(!context_.get());
2621 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2623 ContextCreationAttribHelper attrib_parser;
2624 if (!attrib_parser.Parse(attribs))
2625 return false;
2626 webgl_version_ = attrib_parser.webgl_version;
2628 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2630 set_initialized();
2631 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2633 if (base::CommandLine::InitializedForCurrentProcess()) {
2634 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2635 switches::kEnableGPUDebugging)) {
2636 set_debug(true);
2639 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2640 switches::kEnableGPUCommandLogging)) {
2641 set_log_commands(true);
2644 compile_shader_always_succeeds_ =
2645 base::CommandLine::ForCurrentProcess()->HasSwitch(
2646 switches::kCompileShaderAlwaysSucceeds);
2649 // Take ownership of the context and surface. The surface can be replaced with
2650 // SetSurface.
2651 context_ = context;
2652 surface_ = surface;
2654 // Create GPU Tracer for timing values.
2655 gpu_tracer_.reset(new GPUTracer(this));
2657 if (feature_info_->workarounds().disable_timestamp_queries) {
2658 // Forcing time elapsed query for any GPU Timing Client forces it for all
2659 // clients in the context.
2660 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2663 // Save the loseContextWhenOutOfMemory context creation attribute.
2664 lose_context_when_out_of_memory_ =
2665 attrib_parser.lose_context_when_out_of_memory;
2667 // If the failIfMajorPerformanceCaveat context creation attribute was true
2668 // and we are using a software renderer, fail.
2669 if (attrib_parser.fail_if_major_perf_caveat &&
2670 feature_info_->feature_flags().is_swiftshader) {
2671 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2672 Destroy(true);
2673 return false;
2676 disallowed_features_ = disallowed_features;
2677 if (webgl_version_ == 1) {
2678 disallowed_features_.npot_support = true;
2681 if (!group_->Initialize(this,
2682 ContextGroup::GetContextType(webgl_version_),
2683 disallowed_features_)) {
2684 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2685 Destroy(true);
2686 return false;
2688 CHECK_GL_ERROR();
2690 if (webgl_version_ == 2) {
2691 if (!feature_info_->IsES3Capable()) {
2692 LOG(ERROR) << "Underlying driver does not support ES3.";
2693 Destroy(true);
2694 return false;
2696 feature_info_->EnableES3Validators();
2697 set_unsafe_es3_apis_enabled(true);
2699 frag_depth_explicitly_enabled_ = true;
2700 draw_buffers_explicitly_enabled_ = true;
2701 // TODO(zmo): Look into shader_texture_lod_explicitly_enabled_ situation.
2704 state_.attrib_values.resize(group_->max_vertex_attribs());
2705 vertex_array_manager_.reset(new VertexArrayManager());
2707 GLuint default_vertex_attrib_service_id = 0;
2708 if (features().native_vertex_array_object) {
2709 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2710 glBindVertexArrayOES(default_vertex_attrib_service_id);
2713 state_.default_vertex_attrib_manager =
2714 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2716 state_.default_vertex_attrib_manager->Initialize(
2717 group_->max_vertex_attribs(),
2718 feature_info_->workarounds().init_vertex_attributes);
2720 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2721 DoBindVertexArrayOES(0);
2723 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2725 image_manager_.reset(new ImageManager);
2727 util_.set_num_compressed_texture_formats(
2728 validators_->compressed_texture_format.GetValues().size());
2730 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2731 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2732 // OpenGL ES 2.0 does not have this issue.
2733 glEnableVertexAttribArray(0);
2735 glGenBuffersARB(1, &attrib_0_buffer_id_);
2736 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2737 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2738 glBindBuffer(GL_ARRAY_BUFFER, 0);
2739 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2741 state_.texture_units.resize(group_->max_texture_units());
2742 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2743 glActiveTexture(GL_TEXTURE0 + tt);
2744 // We want the last bind to be 2D.
2745 TextureRef* ref;
2746 if (features().oes_egl_image_external) {
2747 ref = texture_manager()->GetDefaultTextureInfo(
2748 GL_TEXTURE_EXTERNAL_OES);
2749 state_.texture_units[tt].bound_texture_external_oes = ref;
2750 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2752 if (features().arb_texture_rectangle) {
2753 ref = texture_manager()->GetDefaultTextureInfo(
2754 GL_TEXTURE_RECTANGLE_ARB);
2755 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2756 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2758 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2759 state_.texture_units[tt].bound_texture_cube_map = ref;
2760 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2761 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2762 state_.texture_units[tt].bound_texture_2d = ref;
2763 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2765 glActiveTexture(GL_TEXTURE0);
2766 CHECK_GL_ERROR();
2768 // cache ALPHA_BITS result for re-use with clear behaviour
2769 GLint alpha_bits = 0;
2771 if (offscreen) {
2772 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2773 features().chromium_framebuffer_multisample) {
2774 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2775 // max_sample_count must be initialized to a sane value. If
2776 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2777 GLint max_sample_count = 1;
2778 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2779 offscreen_target_samples_ = std::min(attrib_parser.samples,
2780 max_sample_count);
2781 } else {
2782 offscreen_target_samples_ = 1;
2784 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2786 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2787 const bool rgb8_supported =
2788 context_->HasExtension("GL_OES_rgb8_rgba8");
2789 // The only available default render buffer formats in GLES2 have very
2790 // little precision. Don't enable multisampling unless 8-bit render
2791 // buffer formats are available--instead fall back to 8-bit textures.
2792 if (rgb8_supported && offscreen_target_samples_ > 1) {
2793 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2794 GL_RGBA8 : GL_RGB8;
2795 } else {
2796 offscreen_target_samples_ = 1;
2797 offscreen_target_color_format_ =
2798 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2799 ? GL_RGBA
2800 : GL_RGB;
2803 // ANGLE only supports packed depth/stencil formats, so use it if it is
2804 // available.
2805 const bool depth24_stencil8_supported =
2806 feature_info_->feature_flags().packed_depth24_stencil8;
2807 VLOG(1) << "GL_OES_packed_depth_stencil "
2808 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2809 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2810 depth24_stencil8_supported) {
2811 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2812 offscreen_target_stencil_format_ = 0;
2813 } else {
2814 // It may be the case that this depth/stencil combination is not
2815 // supported, but this will be checked later by CheckFramebufferStatus.
2816 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2817 GL_DEPTH_COMPONENT16 : 0;
2818 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2819 GL_STENCIL_INDEX8 : 0;
2821 } else {
2822 offscreen_target_color_format_ =
2823 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2824 ? GL_RGBA
2825 : GL_RGB;
2827 // If depth is requested at all, use the packed depth stencil format if
2828 // it's available, as some desktop GL drivers don't support any non-packed
2829 // formats for depth attachments.
2830 const bool depth24_stencil8_supported =
2831 feature_info_->feature_flags().packed_depth24_stencil8;
2832 VLOG(1) << "GL_EXT_packed_depth_stencil "
2833 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2835 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2836 depth24_stencil8_supported) {
2837 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2838 offscreen_target_stencil_format_ = 0;
2839 } else {
2840 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2841 GL_DEPTH_COMPONENT : 0;
2842 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2843 GL_STENCIL_INDEX : 0;
2847 offscreen_saved_color_format_ =
2848 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2849 ? GL_RGBA
2850 : GL_RGB;
2852 // Create the target frame buffer. This is the one that the client renders
2853 // directly to.
2854 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2855 offscreen_target_frame_buffer_->Create();
2856 // Due to GLES2 format limitations, either the color texture (for
2857 // non-multisampling) or the color render buffer (for multisampling) will be
2858 // attached to the offscreen frame buffer. The render buffer has more
2859 // limited formats available to it, but the texture can't do multisampling.
2860 if (IsOffscreenBufferMultisampled()) {
2861 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2862 renderbuffer_manager(), memory_tracker(), &state_));
2863 offscreen_target_color_render_buffer_->Create();
2864 } else {
2865 offscreen_target_color_texture_.reset(new BackTexture(
2866 memory_tracker(), &state_));
2867 offscreen_target_color_texture_->Create();
2869 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2870 renderbuffer_manager(), memory_tracker(), &state_));
2871 offscreen_target_depth_render_buffer_->Create();
2872 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2873 renderbuffer_manager(), memory_tracker(), &state_));
2874 offscreen_target_stencil_render_buffer_->Create();
2876 // Create the saved offscreen texture. The target frame buffer is copied
2877 // here when SwapBuffers is called.
2878 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2879 offscreen_saved_frame_buffer_->Create();
2881 offscreen_saved_color_texture_.reset(new BackTexture(
2882 memory_tracker(), &state_));
2883 offscreen_saved_color_texture_->Create();
2885 // Allocate the render buffers at their initial size and check the status
2886 // of the frame buffers is okay.
2887 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2888 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2889 Destroy(true);
2890 return false;
2893 state_.viewport_width = offscreen_size.width();
2894 state_.viewport_height = offscreen_size.height();
2896 // Allocate the offscreen saved color texture.
2897 DCHECK(offscreen_saved_color_format_);
2898 offscreen_saved_color_texture_->AllocateStorage(
2899 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2901 offscreen_saved_frame_buffer_->AttachRenderTexture(
2902 offscreen_saved_color_texture_.get());
2903 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2904 GL_FRAMEBUFFER_COMPLETE) {
2905 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2906 Destroy(true);
2907 return false;
2910 // Bind to the new default frame buffer (the offscreen target frame buffer).
2911 // This should now be associated with ID zero.
2912 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2913 } else {
2914 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2915 // These are NOT if the back buffer has these proprorties. They are
2916 // if we want the command buffer to enforce them regardless of what
2917 // the real backbuffer is assuming the real back buffer gives us more than
2918 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2919 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2920 // can't do anything about that.
2922 if (!surfaceless_) {
2923 GLint depth_bits = 0;
2924 GLint stencil_bits = 0;
2926 bool default_fb = (GetBackbufferServiceId() == 0);
2928 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2929 glGetFramebufferAttachmentParameterivEXT(
2930 GL_FRAMEBUFFER,
2931 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2932 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2933 glGetFramebufferAttachmentParameterivEXT(
2934 GL_FRAMEBUFFER,
2935 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2936 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2937 glGetFramebufferAttachmentParameterivEXT(
2938 GL_FRAMEBUFFER,
2939 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2940 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2941 } else {
2942 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2943 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2944 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2947 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2948 // the user requested RGB then RGB. If the user did not specify a
2949 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2950 back_buffer_color_format_ =
2951 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2952 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2953 back_buffer_has_stencil_ =
2954 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2957 state_.viewport_width = surface->GetSize().width();
2958 state_.viewport_height = surface->GetSize().height();
2961 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2962 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2963 // isn't well documented; it was discovered in the Khronos OpenGL ES
2964 // mailing list archives. It also implicitly enables the desktop GL
2965 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2966 // variable in fragment shaders.
2967 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2968 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2969 glEnable(GL_POINT_SPRITE);
2972 has_robustness_extension_ =
2973 context->HasExtension("GL_ARB_robustness") ||
2974 context->HasExtension("GL_KHR_robustness") ||
2975 context->HasExtension("GL_EXT_robustness");
2977 if (!InitializeShaderTranslator()) {
2978 return false;
2981 GLint viewport_params[4] = { 0 };
2982 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2983 viewport_max_width_ = viewport_params[0];
2984 viewport_max_height_ = viewport_params[1];
2986 state_.scissor_width = state_.viewport_width;
2987 state_.scissor_height = state_.viewport_height;
2989 // Set all the default state because some GL drivers get it wrong.
2990 state_.InitCapabilities(NULL);
2991 state_.InitState(NULL);
2992 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2994 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2995 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2996 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2997 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2998 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
3000 bool call_gl_clear = !surfaceless_;
3001 #if defined(OS_ANDROID)
3002 // Temporary workaround for Android WebView because this clear ignores the
3003 // clip and corrupts that external UI of the App. Not calling glClear is ok
3004 // because the system already clears the buffer before each draw. Proper
3005 // fix might be setting the scissor clip properly before initialize. See
3006 // crbug.com/259023 for details.
3007 call_gl_clear = surface_->GetHandle();
3008 #endif
3009 if (call_gl_clear) {
3010 // On configs where we report no alpha, if the underlying surface has
3011 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
3012 bool clear_alpha = back_buffer_color_format_ == GL_RGB && alpha_bits > 0;
3013 if (clear_alpha) {
3014 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3017 // Clear the backbuffer.
3018 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3020 // Restore alpha clear value if we changed it.
3021 if (clear_alpha) {
3022 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3026 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
3027 if (feature_info_->workarounds()
3028 .disable_post_sub_buffers_for_onscreen_surfaces &&
3029 !surface->IsOffscreen())
3030 supports_post_sub_buffer_ = false;
3032 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
3033 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
3036 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
3037 context_->SetUnbindFboOnMakeCurrent();
3040 // Only compositor contexts are known to use only the subset of GL
3041 // that can be safely migrated between the iGPU and the dGPU. Mark
3042 // those contexts as safe to forcibly transition between the GPUs.
3043 // http://crbug.com/180876, http://crbug.com/227228
3044 if (!offscreen)
3045 context_->SetSafeToForceGpuSwitch();
3047 if (workarounds().gl_clear_broken) {
3048 DCHECK(!clear_framebuffer_blit_.get());
3049 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3050 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
3051 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
3052 return false;
3055 framebuffer_manager()->AddObserver(this);
3057 return true;
3060 Capabilities GLES2DecoderImpl::GetCapabilities() {
3061 DCHECK(initialized());
3062 Capabilities caps;
3063 caps.VisitPrecisions([](GLenum shader, GLenum type,
3064 Capabilities::ShaderPrecision* shader_precision) {
3065 GLint range[2] = {0, 0};
3066 GLint precision = 0;
3067 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
3068 shader_precision->min_range = range[0];
3069 shader_precision->max_range = range[1];
3070 shader_precision->precision = precision;
3072 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
3073 &caps.max_combined_texture_image_units);
3074 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
3075 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
3076 &caps.max_fragment_uniform_vectors);
3077 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
3078 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
3079 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
3080 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
3081 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
3082 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
3083 &caps.max_vertex_texture_image_units);
3084 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
3085 &caps.max_vertex_uniform_vectors);
3086 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
3087 &caps.num_compressed_texture_formats);
3088 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
3089 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
3090 &caps.bind_generates_resource_chromium);
3091 if (unsafe_es3_apis_enabled()) {
3092 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3093 // but for now we clamp them to 32-bit max.
3094 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
3095 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
3096 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
3097 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
3098 &caps.max_combined_fragment_uniform_components);
3099 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
3100 &caps.max_combined_uniform_blocks);
3101 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
3102 &caps.max_combined_vertex_uniform_components);
3103 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
3104 DoGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
3105 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
3106 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
3107 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
3108 &caps.max_fragment_input_components);
3109 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
3110 &caps.max_fragment_uniform_blocks);
3111 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
3112 &caps.max_fragment_uniform_components);
3113 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
3114 &caps.max_program_texel_offset);
3115 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
3116 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3117 // returned.
3118 if (caps.max_server_wait_timeout < 0)
3119 caps.max_server_wait_timeout = 0;
3120 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps.max_texture_lod_bias);
3121 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
3122 &caps.max_transform_feedback_interleaved_components);
3123 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
3124 &caps.max_transform_feedback_separate_attribs);
3125 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
3126 &caps.max_transform_feedback_separate_components);
3127 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
3128 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
3129 &caps.max_uniform_buffer_bindings);
3130 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
3131 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
3132 &caps.max_vertex_output_components);
3133 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
3134 &caps.max_vertex_uniform_blocks);
3135 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
3136 &caps.max_vertex_uniform_components);
3137 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
3138 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
3139 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
3140 &caps.num_program_binary_formats);
3141 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
3142 &caps.uniform_buffer_offset_alignment);
3143 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3144 caps.major_version = 3;
3145 caps.minor_version = 0;
3147 if (feature_info_->feature_flags().multisampled_render_to_texture ||
3148 feature_info_->feature_flags().chromium_framebuffer_multisample ||
3149 unsafe_es3_apis_enabled()) {
3150 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
3153 caps.egl_image_external =
3154 feature_info_->feature_flags().oes_egl_image_external;
3155 caps.texture_format_astc =
3156 feature_info_->feature_flags().ext_texture_format_astc;
3157 caps.texture_format_atc =
3158 feature_info_->feature_flags().ext_texture_format_atc;
3159 caps.texture_format_bgra8888 =
3160 feature_info_->feature_flags().ext_texture_format_bgra8888;
3161 caps.texture_format_dxt1 =
3162 feature_info_->feature_flags().ext_texture_format_dxt1;
3163 caps.texture_format_dxt5 =
3164 feature_info_->feature_flags().ext_texture_format_dxt5;
3165 caps.texture_format_etc1 =
3166 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
3167 caps.texture_format_etc1_npot =
3168 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
3169 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
3170 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
3171 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
3172 caps.discard_framebuffer =
3173 feature_info_->feature_flags().ext_discard_framebuffer;
3174 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3176 #if defined(OS_MACOSX)
3177 // This is unconditionally true on mac, no need to test for it at runtime.
3178 caps.iosurface = true;
3179 #endif
3181 caps.post_sub_buffer = supports_post_sub_buffer_;
3182 caps.image = true;
3183 caps.surfaceless = surfaceless_;
3185 caps.blend_equation_advanced =
3186 feature_info_->feature_flags().blend_equation_advanced;
3187 caps.blend_equation_advanced_coherent =
3188 feature_info_->feature_flags().blend_equation_advanced_coherent;
3189 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3190 caps.image_ycbcr_422 =
3191 feature_info_->feature_flags().chromium_image_ycbcr_422;
3192 caps.max_copy_texture_chromium_size =
3193 feature_info_->workarounds().max_copy_texture_chromium_size;
3194 caps.render_buffer_format_bgra8888 =
3195 feature_info_->feature_flags().ext_render_buffer_format_bgra8888;
3196 caps.occlusion_query_boolean =
3197 feature_info_->feature_flags().occlusion_query_boolean;
3198 caps.timer_queries =
3199 query_manager_->GPUTimingAvailable();
3200 return caps;
3203 void GLES2DecoderImpl::UpdateCapabilities() {
3204 util_.set_num_compressed_texture_formats(
3205 validators_->compressed_texture_format.GetValues().size());
3206 util_.set_num_shader_binary_formats(
3207 validators_->shader_binary_format.GetValues().size());
3210 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3211 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3212 if (feature_info_->disable_shader_translator()) {
3213 return true;
3215 ShBuiltInResources resources;
3216 ShInitBuiltInResources(&resources);
3217 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3218 resources.MaxVertexUniformVectors =
3219 group_->max_vertex_uniform_vectors();
3220 resources.MaxVaryingVectors = group_->max_varying_vectors();
3221 resources.MaxVertexTextureImageUnits =
3222 group_->max_vertex_texture_image_units();
3223 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3224 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3225 resources.MaxFragmentUniformVectors =
3226 group_->max_fragment_uniform_vectors();
3227 resources.MaxDrawBuffers = group_->max_draw_buffers();
3228 resources.MaxExpressionComplexity = 256;
3229 resources.MaxCallStackDepth = 256;
3231 GLint range[2] = { 0, 0 };
3232 GLint precision = 0;
3233 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3234 range, &precision);
3235 resources.FragmentPrecisionHigh =
3236 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3238 if (IsWebGLContext()) {
3239 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3240 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3241 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3242 if (!draw_buffers_explicitly_enabled_)
3243 resources.MaxDrawBuffers = 1;
3244 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3245 resources.NV_draw_buffers =
3246 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3247 } else {
3248 resources.OES_standard_derivatives =
3249 features().oes_standard_derivatives ? 1 : 0;
3250 resources.ARB_texture_rectangle =
3251 features().arb_texture_rectangle ? 1 : 0;
3252 resources.OES_EGL_image_external =
3253 features().oes_egl_image_external ? 1 : 0;
3254 resources.EXT_draw_buffers =
3255 features().ext_draw_buffers ? 1 : 0;
3256 resources.EXT_frag_depth =
3257 features().ext_frag_depth ? 1 : 0;
3258 resources.EXT_shader_texture_lod =
3259 features().ext_shader_texture_lod ? 1 : 0;
3260 resources.NV_draw_buffers =
3261 features().nv_draw_buffers ? 1 : 0;
3264 ShShaderSpec shader_spec;
3265 if (IsWebGLContext()) {
3266 shader_spec = webgl_version_ == 2 ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3267 } else {
3268 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3271 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3272 features().enable_shader_name_hashing)
3273 resources.HashFunction = &CityHash64;
3274 else
3275 resources.HashFunction = NULL;
3277 int driver_bug_workarounds = 0;
3278 if (workarounds().needs_glsl_built_in_function_emulation)
3279 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3280 if (workarounds().init_gl_position_in_vertex_shader)
3281 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3282 if (workarounds().unfold_short_circuit_as_ternary_operation)
3283 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3284 if (workarounds().init_varyings_without_static_use)
3285 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3286 if (workarounds().unroll_for_loop_with_sampler_array_index)
3287 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3288 if (workarounds().scalarize_vec_and_mat_constructor_args)
3289 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3290 if (workarounds().regenerate_struct_names)
3291 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3292 if (workarounds().remove_pow_with_constant_exponent)
3293 driver_bug_workarounds |= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT;
3295 if (base::CommandLine::InitializedForCurrentProcess() &&
3296 base::CommandLine::ForCurrentProcess()->HasSwitch(
3297 switches::kEmulateShaderPrecision))
3298 resources.WEBGL_debug_shader_precision = true;
3300 ShShaderOutput shader_output_language =
3301 ShaderTranslator::GetShaderOutputLanguageForContext(
3302 feature_info_->gl_version_info());
3304 vertex_translator_ = shader_translator_cache()->GetTranslator(
3305 GL_VERTEX_SHADER, shader_spec, &resources, shader_output_language,
3306 static_cast<ShCompileOptions>(driver_bug_workarounds));
3307 if (!vertex_translator_.get()) {
3308 LOG(ERROR) << "Could not initialize vertex shader translator.";
3309 Destroy(true);
3310 return false;
3313 fragment_translator_ = shader_translator_cache()->GetTranslator(
3314 GL_FRAGMENT_SHADER, shader_spec, &resources, shader_output_language,
3315 static_cast<ShCompileOptions>(driver_bug_workarounds));
3316 if (!fragment_translator_.get()) {
3317 LOG(ERROR) << "Could not initialize fragment shader translator.";
3318 Destroy(true);
3319 return false;
3321 return true;
3324 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3325 for (GLsizei ii = 0; ii < n; ++ii) {
3326 if (GetBuffer(client_ids[ii])) {
3327 return false;
3330 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3331 glGenBuffersARB(n, service_ids.get());
3332 for (GLsizei ii = 0; ii < n; ++ii) {
3333 CreateBuffer(client_ids[ii], service_ids[ii]);
3335 return true;
3338 bool GLES2DecoderImpl::GenFramebuffersHelper(
3339 GLsizei n, const GLuint* client_ids) {
3340 for (GLsizei ii = 0; ii < n; ++ii) {
3341 if (GetFramebuffer(client_ids[ii])) {
3342 return false;
3345 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3346 glGenFramebuffersEXT(n, service_ids.get());
3347 for (GLsizei ii = 0; ii < n; ++ii) {
3348 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3350 return true;
3353 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3354 GLsizei n, const GLuint* client_ids) {
3355 for (GLsizei ii = 0; ii < n; ++ii) {
3356 if (GetRenderbuffer(client_ids[ii])) {
3357 return false;
3360 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3361 glGenRenderbuffersEXT(n, service_ids.get());
3362 for (GLsizei ii = 0; ii < n; ++ii) {
3363 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3365 return true;
3368 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3369 const GLuint* client_ids) {
3370 for (GLsizei ii = 0; ii < n; ++ii) {
3371 if (GetValuebuffer(client_ids[ii])) {
3372 return false;
3375 for (GLsizei ii = 0; ii < n; ++ii) {
3376 CreateValuebuffer(client_ids[ii]);
3378 return true;
3381 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3382 for (GLsizei ii = 0; ii < n; ++ii) {
3383 if (GetTexture(client_ids[ii])) {
3384 return false;
3387 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3388 glGenTextures(n, service_ids.get());
3389 for (GLsizei ii = 0; ii < n; ++ii) {
3390 CreateTexture(client_ids[ii], service_ids[ii]);
3392 return true;
3395 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id,
3396 GLsizei range) {
3397 GLuint last_client_id;
3398 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3399 return false;
3401 if (path_manager()->HasPathsInRange(first_client_id, last_client_id))
3402 return false;
3404 GLuint first_service_id = glGenPathsNV(range);
3405 if (first_service_id == 0) {
3406 // We have to fail the connection here, because client has already
3407 // succeeded in allocating the ids. This happens if we allocate
3408 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3409 // example).
3410 return false;
3412 // GenPathsNV does not wrap.
3413 DCHECK(first_service_id + range - 1 >= first_service_id);
3415 path_manager()->CreatePathRange(first_client_id, last_client_id,
3416 first_service_id);
3418 return true;
3421 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id,
3422 GLsizei range) {
3423 GLuint last_client_id;
3424 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3425 return false;
3427 path_manager()->RemovePaths(first_client_id, last_client_id);
3428 return true;
3431 void GLES2DecoderImpl::DeleteBuffersHelper(
3432 GLsizei n, const GLuint* client_ids) {
3433 for (GLsizei ii = 0; ii < n; ++ii) {
3434 Buffer* buffer = GetBuffer(client_ids[ii]);
3435 if (buffer && !buffer->IsDeleted()) {
3436 buffer->RemoveMappedRange();
3437 state_.RemoveBoundBuffer(buffer);
3438 RemoveBuffer(client_ids[ii]);
3443 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3444 GLsizei n, const GLuint* client_ids) {
3445 bool supports_separate_framebuffer_binds =
3446 features().chromium_framebuffer_multisample;
3448 for (GLsizei ii = 0; ii < n; ++ii) {
3449 Framebuffer* framebuffer =
3450 GetFramebuffer(client_ids[ii]);
3451 if (framebuffer && !framebuffer->IsDeleted()) {
3452 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3453 GLenum target = supports_separate_framebuffer_binds ?
3454 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3456 // Unbind attachments on FBO before deletion.
3457 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3458 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3460 glBindFramebufferEXT(target, GetBackbufferServiceId());
3461 framebuffer_state_.bound_draw_framebuffer = NULL;
3462 framebuffer_state_.clear_state_dirty = true;
3464 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3465 framebuffer_state_.bound_read_framebuffer = NULL;
3466 GLenum target = supports_separate_framebuffer_binds ?
3467 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3468 glBindFramebufferEXT(target, GetBackbufferServiceId());
3470 OnFboChanged();
3471 RemoveFramebuffer(client_ids[ii]);
3476 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3477 GLsizei n, const GLuint* client_ids) {
3478 bool supports_separate_framebuffer_binds =
3479 features().chromium_framebuffer_multisample;
3480 for (GLsizei ii = 0; ii < n; ++ii) {
3481 Renderbuffer* renderbuffer =
3482 GetRenderbuffer(client_ids[ii]);
3483 if (renderbuffer && !renderbuffer->IsDeleted()) {
3484 if (state_.bound_renderbuffer.get() == renderbuffer) {
3485 state_.bound_renderbuffer = NULL;
3487 // Unbind from current framebuffers.
3488 if (supports_separate_framebuffer_binds) {
3489 if (framebuffer_state_.bound_read_framebuffer.get()) {
3490 framebuffer_state_.bound_read_framebuffer
3491 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3493 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3494 framebuffer_state_.bound_draw_framebuffer
3495 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3497 } else {
3498 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3499 framebuffer_state_.bound_draw_framebuffer
3500 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3503 framebuffer_state_.clear_state_dirty = true;
3504 RemoveRenderbuffer(client_ids[ii]);
3509 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3510 GLsizei n,
3511 const GLuint* client_ids) {
3512 for (GLsizei ii = 0; ii < n; ++ii) {
3513 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3514 if (valuebuffer) {
3515 if (state_.bound_valuebuffer.get() == valuebuffer) {
3516 state_.bound_valuebuffer = NULL;
3518 RemoveValuebuffer(client_ids[ii]);
3523 void GLES2DecoderImpl::DeleteTexturesHelper(
3524 GLsizei n, const GLuint* client_ids) {
3525 bool supports_separate_framebuffer_binds =
3526 features().chromium_framebuffer_multisample;
3527 for (GLsizei ii = 0; ii < n; ++ii) {
3528 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3529 if (texture_ref) {
3530 Texture* texture = texture_ref->texture();
3531 if (texture->IsAttachedToFramebuffer()) {
3532 framebuffer_state_.clear_state_dirty = true;
3534 // Unbind texture_ref from texture_ref units.
3535 state_.UnbindTexture(texture_ref);
3537 // Unbind from current framebuffers.
3538 if (supports_separate_framebuffer_binds) {
3539 if (framebuffer_state_.bound_read_framebuffer.get()) {
3540 framebuffer_state_.bound_read_framebuffer
3541 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3543 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3544 framebuffer_state_.bound_draw_framebuffer
3545 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3547 } else {
3548 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3549 framebuffer_state_.bound_draw_framebuffer
3550 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3553 #if defined(OS_MACOSX)
3554 GLuint service_id = texture->service_id();
3555 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3556 ReleaseIOSurfaceForTexture(service_id);
3558 #endif
3559 RemoveTexture(client_ids[ii]);
3564 // } // anonymous namespace
3566 bool GLES2DecoderImpl::MakeCurrent() {
3567 if (!context_.get())
3568 return false;
3570 if (WasContextLost()) {
3571 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3572 return false;
3575 if (!context_->MakeCurrent(surface_.get())) {
3576 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3577 MarkContextLost(error::kMakeCurrentFailed);
3578 group_->LoseContexts(error::kUnknown);
3579 return false;
3582 if (CheckResetStatus()) {
3583 LOG(ERROR)
3584 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3585 group_->LoseContexts(error::kUnknown);
3586 return false;
3589 ProcessFinishedAsyncTransfers();
3591 // Rebind the FBO if it was unbound by the context.
3592 if (workarounds().unbind_fbo_on_context_switch)
3593 RestoreFramebufferBindings();
3595 framebuffer_state_.clear_state_dirty = true;
3597 return true;
3600 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3601 ProcessPendingReadPixels(false);
3602 if (engine() && query_manager_.get())
3603 query_manager_->ProcessPendingTransferQueries();
3606 static void RebindCurrentFramebuffer(
3607 GLenum target,
3608 Framebuffer* framebuffer,
3609 GLuint back_buffer_service_id) {
3610 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3612 if (framebuffer_id == 0) {
3613 framebuffer_id = back_buffer_service_id;
3616 glBindFramebufferEXT(target, framebuffer_id);
3619 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3620 framebuffer_state_.clear_state_dirty = true;
3622 if (!features().chromium_framebuffer_multisample) {
3623 RebindCurrentFramebuffer(
3624 GL_FRAMEBUFFER,
3625 framebuffer_state_.bound_draw_framebuffer.get(),
3626 GetBackbufferServiceId());
3627 } else {
3628 RebindCurrentFramebuffer(
3629 GL_READ_FRAMEBUFFER_EXT,
3630 framebuffer_state_.bound_read_framebuffer.get(),
3631 GetBackbufferServiceId());
3632 RebindCurrentFramebuffer(
3633 GL_DRAW_FRAMEBUFFER_EXT,
3634 framebuffer_state_.bound_draw_framebuffer.get(),
3635 GetBackbufferServiceId());
3637 OnFboChanged();
3640 bool GLES2DecoderImpl::CheckFramebufferValid(
3641 Framebuffer* framebuffer,
3642 GLenum target, const char* func_name) {
3643 if (!framebuffer) {
3644 if (surfaceless_)
3645 return false;
3646 if (backbuffer_needs_clear_bits_) {
3647 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3648 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3649 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3650 glClearStencil(0);
3651 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3652 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3653 glClearDepth(1.0f);
3654 state_.SetDeviceDepthMask(GL_TRUE);
3655 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3656 bool reset_draw_buffer = false;
3657 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3658 back_buffer_draw_buffer_ == GL_NONE) {
3659 reset_draw_buffer = true;
3660 GLenum buf = GL_BACK;
3661 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3662 buf = GL_COLOR_ATTACHMENT0;
3663 glDrawBuffersARB(1, &buf);
3665 glClear(backbuffer_needs_clear_bits_);
3666 if (reset_draw_buffer) {
3667 GLenum buf = GL_NONE;
3668 glDrawBuffersARB(1, &buf);
3670 backbuffer_needs_clear_bits_ = 0;
3671 RestoreClearState();
3673 return true;
3676 if (framebuffer_manager()->IsComplete(framebuffer)) {
3677 return true;
3680 GLenum completeness = framebuffer->IsPossiblyComplete();
3681 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3682 LOCAL_SET_GL_ERROR(
3683 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3684 return false;
3687 // Are all the attachments cleared?
3688 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3689 texture_manager()->HaveUnclearedMips()) {
3690 if (!framebuffer->IsCleared()) {
3691 // Can we clear them?
3692 if (framebuffer->GetStatus(texture_manager(), target) !=
3693 GL_FRAMEBUFFER_COMPLETE) {
3694 LOCAL_SET_GL_ERROR(
3695 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3696 "framebuffer incomplete (clear)");
3697 return false;
3699 ClearUnclearedAttachments(target, framebuffer);
3703 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3704 if (framebuffer->GetStatus(texture_manager(), target) !=
3705 GL_FRAMEBUFFER_COMPLETE) {
3706 LOCAL_SET_GL_ERROR(
3707 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3708 "framebuffer incomplete (check)");
3709 return false;
3711 framebuffer_manager()->MarkAsComplete(framebuffer);
3714 // NOTE: At this point we don't know if the framebuffer is complete but
3715 // we DO know that everything that needs to be cleared has been cleared.
3716 return true;
3719 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3720 if (!features().chromium_framebuffer_multisample) {
3721 bool valid = CheckFramebufferValid(
3722 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3723 func_name);
3725 if (valid)
3726 OnUseFramebuffer();
3728 return valid;
3730 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3731 GL_DRAW_FRAMEBUFFER_EXT,
3732 func_name) &&
3733 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3734 GL_READ_FRAMEBUFFER_EXT,
3735 func_name);
3738 bool GLES2DecoderImpl::CheckBoundDrawFramebufferValid(const char* func_name) {
3739 Framebuffer* framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
3740 if (!framebuffer) {
3741 // Assume the default back buffer is always complete.
3742 return true;
3744 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3745 if (framebuffer->GetStatus(texture_manager(), GL_DRAW_FRAMEBUFFER) !=
3746 GL_FRAMEBUFFER_COMPLETE) {
3747 LOCAL_SET_GL_ERROR(
3748 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3749 "framebuffer incomplete (check)");
3750 return false;
3752 framebuffer_manager()->MarkAsComplete(framebuffer);
3754 return true;
3757 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3758 const char* func_name) {
3759 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3760 framebuffer_state_.bound_read_framebuffer.get() :
3761 framebuffer_state_.bound_draw_framebuffer.get();
3762 if (!framebuffer)
3763 return true;
3764 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3765 LOCAL_SET_GL_ERROR(
3766 GL_INVALID_OPERATION, func_name, "no color image attached");
3767 return false;
3769 return true;
3772 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3773 TextureRef* texture, GLint level) {
3774 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3775 framebuffer_state_.bound_read_framebuffer.get() :
3776 framebuffer_state_.bound_draw_framebuffer.get();
3777 if (!framebuffer)
3778 return false;
3779 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3780 GL_COLOR_ATTACHMENT0);
3781 if (!attachment)
3782 return false;
3783 return attachment->FormsFeedbackLoop(texture, level);
3786 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3787 Framebuffer* framebuffer =
3788 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3789 if (framebuffer != NULL) {
3790 const Framebuffer::Attachment* attachment =
3791 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3792 if (attachment) {
3793 return gfx::Size(attachment->width(), attachment->height());
3795 return gfx::Size(0, 0);
3796 } else if (offscreen_target_frame_buffer_.get()) {
3797 return offscreen_size_;
3798 } else {
3799 return surface_->GetSize();
3803 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3804 Framebuffer* framebuffer =
3805 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3806 if (framebuffer) {
3807 return framebuffer->GetReadBufferTextureType();
3808 } else { // Back buffer.
3809 if (back_buffer_read_buffer_ == GL_NONE)
3810 return 0;
3811 return GL_UNSIGNED_BYTE;
3815 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3816 Framebuffer* framebuffer =
3817 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3818 if (framebuffer) {
3819 return framebuffer->GetReadBufferInternalFormat();
3820 } else { // Back buffer.
3821 if (back_buffer_read_buffer_ == GL_NONE)
3822 return 0;
3823 if (offscreen_target_frame_buffer_.get()) {
3824 return offscreen_target_color_format_;
3826 return back_buffer_color_format_;
3830 GLenum GLES2DecoderImpl::GetBoundColorDrawBufferInternalFormat(
3831 GLint drawbuffer_i) {
3832 DCHECK(drawbuffer_i >= 0 &&
3833 drawbuffer_i < static_cast<GLint>(group_->max_draw_buffers()));
3834 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3835 if (!framebuffer) {
3836 return 0;
3838 GLenum drawbuffer = static_cast<GLenum>(GL_DRAW_BUFFER0 + drawbuffer_i);
3839 if (framebuffer->GetDrawBuffer(drawbuffer) == GL_NONE) {
3840 return 0;
3842 GLenum attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + drawbuffer_i);
3843 const Framebuffer::Attachment* buffer =
3844 framebuffer->GetAttachment(attachment);
3845 if (!buffer) {
3846 return 0;
3848 return buffer->internal_format();
3851 void GLES2DecoderImpl::MarkDrawBufferAsCleared(
3852 GLenum buffer, GLint drawbuffer_i) {
3853 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3854 if (!framebuffer)
3855 return;
3856 GLenum attachment = 0;
3857 switch (buffer) {
3858 case GL_COLOR:
3859 DCHECK(drawbuffer_i >= 0 &&
3860 drawbuffer_i < static_cast<GLint>(group_->max_draw_buffers()));
3861 attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + drawbuffer_i);
3862 break;
3863 case GL_DEPTH:
3864 attachment = GL_DEPTH;
3865 break;
3866 case GL_STENCIL:
3867 attachment = GL_STENCIL;
3868 break;
3869 default:
3870 // Caller is responsible for breaking GL_DEPTH_STENCIL into GL_DEPTH and
3871 // GL_STENCIL.
3872 NOTREACHED();
3874 framebuffer->MarkAttachmentAsCleared(
3875 renderbuffer_manager(), texture_manager(), attachment, true);
3878 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3879 if (!offscreen_saved_color_texture_info_.get())
3880 return;
3881 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3882 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3883 texture_manager()->SetLevelInfo(
3884 offscreen_saved_color_texture_info_.get(), GL_TEXTURE_2D,
3885 0, // level
3886 GL_RGBA, offscreen_size_.width(), offscreen_size_.height(),
3887 1, // depth
3888 0, // border
3889 GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(offscreen_size_));
3890 texture_manager()->SetParameteri(
3891 "UpdateParentTextureInfo",
3892 GetErrorState(),
3893 offscreen_saved_color_texture_info_.get(),
3894 GL_TEXTURE_MAG_FILTER,
3895 GL_LINEAR);
3896 texture_manager()->SetParameteri(
3897 "UpdateParentTextureInfo",
3898 GetErrorState(),
3899 offscreen_saved_color_texture_info_.get(),
3900 GL_TEXTURE_MIN_FILTER,
3901 GL_LINEAR);
3902 texture_manager()->SetParameteri(
3903 "UpdateParentTextureInfo",
3904 GetErrorState(),
3905 offscreen_saved_color_texture_info_.get(),
3906 GL_TEXTURE_WRAP_S,
3907 GL_CLAMP_TO_EDGE);
3908 texture_manager()->SetParameteri(
3909 "UpdateParentTextureInfo",
3910 GetErrorState(),
3911 offscreen_saved_color_texture_info_.get(),
3912 GL_TEXTURE_WRAP_T,
3913 GL_CLAMP_TO_EDGE);
3914 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3915 &state_, target);
3916 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3919 void GLES2DecoderImpl::SetResizeCallback(
3920 const base::Callback<void(gfx::Size, float)>& callback) {
3921 resize_callback_ = callback;
3924 Logger* GLES2DecoderImpl::GetLogger() {
3925 return &logger_;
3928 void GLES2DecoderImpl::BeginDecoding() {
3929 gpu_tracer_->BeginDecoding();
3930 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3931 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_;
3932 query_manager_->ProcessFrameBeginUpdates();
3935 void GLES2DecoderImpl::EndDecoding() {
3936 gpu_tracer_->EndDecoding();
3939 ErrorState* GLES2DecoderImpl::GetErrorState() {
3940 return state_.GetErrorState();
3943 void GLES2DecoderImpl::SetShaderCacheCallback(
3944 const ShaderCacheCallback& callback) {
3945 shader_cache_callback_ = callback;
3948 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3949 const WaitSyncPointCallback& callback) {
3950 wait_sync_point_callback_ = callback;
3953 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3954 uint32* service_texture_id) {
3955 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3956 if (texture_ref) {
3957 *service_texture_id = texture_ref->service_id();
3958 return true;
3960 return false;
3963 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3964 return texture_state_.texture_upload_count;
3967 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3968 return texture_state_.total_texture_upload_time;
3971 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3972 return total_processing_commands_time_;
3975 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3976 total_processing_commands_time_ += time;
3979 void GLES2DecoderImpl::Destroy(bool have_context) {
3980 if (!initialized())
3981 return;
3983 DCHECK(!have_context || context_->IsCurrent(NULL));
3985 // Unbind everything.
3986 state_.vertex_attrib_manager = NULL;
3987 state_.default_vertex_attrib_manager = NULL;
3988 state_.texture_units.clear();
3989 state_.bound_array_buffer = NULL;
3990 state_.bound_copy_read_buffer = NULL;
3991 state_.bound_copy_write_buffer = NULL;
3992 state_.bound_pixel_pack_buffer = NULL;
3993 state_.bound_pixel_unpack_buffer = NULL;
3994 state_.bound_transform_feedback_buffer = NULL;
3995 state_.bound_uniform_buffer = NULL;
3996 framebuffer_state_.bound_read_framebuffer = NULL;
3997 framebuffer_state_.bound_draw_framebuffer = NULL;
3998 state_.bound_renderbuffer = NULL;
3999 state_.bound_valuebuffer = NULL;
4001 if (offscreen_saved_color_texture_info_.get()) {
4002 DCHECK(offscreen_target_color_texture_);
4003 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
4004 offscreen_saved_color_texture_->id());
4005 offscreen_saved_color_texture_->Invalidate();
4006 offscreen_saved_color_texture_info_ = NULL;
4008 if (have_context) {
4009 if (copy_texture_CHROMIUM_.get()) {
4010 copy_texture_CHROMIUM_->Destroy();
4011 copy_texture_CHROMIUM_.reset();
4014 clear_framebuffer_blit_.reset();
4016 if (state_.current_program.get()) {
4017 program_manager()->UnuseProgram(shader_manager(),
4018 state_.current_program.get());
4021 if (attrib_0_buffer_id_) {
4022 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
4024 if (fixed_attrib_buffer_id_) {
4025 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
4028 if (validation_texture_) {
4029 glDeleteTextures(1, &validation_texture_);
4030 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
4031 glDeleteFramebuffersEXT(1, &validation_fbo_);
4034 if (offscreen_target_frame_buffer_.get())
4035 offscreen_target_frame_buffer_->Destroy();
4036 if (offscreen_target_color_texture_.get())
4037 offscreen_target_color_texture_->Destroy();
4038 if (offscreen_target_color_render_buffer_.get())
4039 offscreen_target_color_render_buffer_->Destroy();
4040 if (offscreen_target_depth_render_buffer_.get())
4041 offscreen_target_depth_render_buffer_->Destroy();
4042 if (offscreen_target_stencil_render_buffer_.get())
4043 offscreen_target_stencil_render_buffer_->Destroy();
4044 if (offscreen_saved_frame_buffer_.get())
4045 offscreen_saved_frame_buffer_->Destroy();
4046 if (offscreen_saved_color_texture_.get())
4047 offscreen_saved_color_texture_->Destroy();
4048 if (offscreen_resolved_frame_buffer_.get())
4049 offscreen_resolved_frame_buffer_->Destroy();
4050 if (offscreen_resolved_color_texture_.get())
4051 offscreen_resolved_color_texture_->Destroy();
4052 } else {
4053 if (offscreen_target_frame_buffer_.get())
4054 offscreen_target_frame_buffer_->Invalidate();
4055 if (offscreen_target_color_texture_.get())
4056 offscreen_target_color_texture_->Invalidate();
4057 if (offscreen_target_color_render_buffer_.get())
4058 offscreen_target_color_render_buffer_->Invalidate();
4059 if (offscreen_target_depth_render_buffer_.get())
4060 offscreen_target_depth_render_buffer_->Invalidate();
4061 if (offscreen_target_stencil_render_buffer_.get())
4062 offscreen_target_stencil_render_buffer_->Invalidate();
4063 if (offscreen_saved_frame_buffer_.get())
4064 offscreen_saved_frame_buffer_->Invalidate();
4065 if (offscreen_saved_color_texture_.get())
4066 offscreen_saved_color_texture_->Invalidate();
4067 if (offscreen_resolved_frame_buffer_.get())
4068 offscreen_resolved_frame_buffer_->Invalidate();
4069 if (offscreen_resolved_color_texture_.get())
4070 offscreen_resolved_color_texture_->Invalidate();
4073 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4074 // Otherwise, we can leak objects. http://crbug.com/258772.
4075 // state_.current_program must be reset before group_ is reset because
4076 // the later deletes the ProgramManager object that referred by
4077 // state_.current_program object.
4078 state_.current_program = NULL;
4080 copy_texture_CHROMIUM_.reset();
4081 clear_framebuffer_blit_.reset();
4083 if (query_manager_.get()) {
4084 query_manager_->Destroy(have_context);
4085 query_manager_.reset();
4088 if (vertex_array_manager_ .get()) {
4089 vertex_array_manager_->Destroy(have_context);
4090 vertex_array_manager_.reset();
4093 if (image_manager_.get()) {
4094 image_manager_->Destroy(have_context);
4095 image_manager_.reset();
4098 offscreen_target_frame_buffer_.reset();
4099 offscreen_target_color_texture_.reset();
4100 offscreen_target_color_render_buffer_.reset();
4101 offscreen_target_depth_render_buffer_.reset();
4102 offscreen_target_stencil_render_buffer_.reset();
4103 offscreen_saved_frame_buffer_.reset();
4104 offscreen_saved_color_texture_.reset();
4105 offscreen_resolved_frame_buffer_.reset();
4106 offscreen_resolved_color_texture_.reset();
4108 // Need to release these before releasing |group_| which may own the
4109 // ShaderTranslatorCache.
4110 fragment_translator_ = NULL;
4111 vertex_translator_ = NULL;
4113 // Destroy the GPU Tracer which may own some in process GPU Timings.
4114 if (gpu_tracer_) {
4115 gpu_tracer_->Destroy(have_context);
4116 gpu_tracer_.reset();
4119 if (group_.get()) {
4120 framebuffer_manager()->RemoveObserver(this);
4121 group_->Destroy(this, have_context);
4122 group_ = NULL;
4125 if (context_.get()) {
4126 context_->ReleaseCurrent(NULL);
4127 context_ = NULL;
4130 #if defined(OS_MACOSX)
4131 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
4132 it != texture_to_io_surface_map_.end(); ++it) {
4133 CFRelease(it->second);
4135 texture_to_io_surface_map_.clear();
4136 #endif
4139 void GLES2DecoderImpl::SetSurface(
4140 const scoped_refptr<gfx::GLSurface>& surface) {
4141 DCHECK(context_->IsCurrent(NULL));
4142 DCHECK(surface_.get());
4143 surface_ = surface;
4144 RestoreCurrentFramebufferBindings();
4147 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
4148 if (!offscreen_saved_color_texture_.get()) {
4149 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
4150 return;
4152 if (!offscreen_saved_color_texture_info_.get()) {
4153 GLuint service_id = offscreen_saved_color_texture_->id();
4154 offscreen_saved_color_texture_info_ = TextureRef::Create(
4155 texture_manager(), 0, service_id);
4156 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
4157 GL_TEXTURE_2D);
4158 UpdateParentTextureInfo();
4160 mailbox_manager()->ProduceTexture(
4161 mailbox, offscreen_saved_color_texture_info_->texture());
4164 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
4165 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4166 if (!is_offscreen) {
4167 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4168 << " with an onscreen framebuffer.";
4169 return false;
4172 if (offscreen_size_ == size)
4173 return true;
4175 offscreen_size_ = size;
4176 int w = offscreen_size_.width();
4177 int h = offscreen_size_.height();
4178 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
4179 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4180 << "to allocate storage due to excessive dimensions.";
4181 return false;
4184 // Reallocate the offscreen target buffers.
4185 DCHECK(offscreen_target_color_format_);
4186 if (IsOffscreenBufferMultisampled()) {
4187 if (!offscreen_target_color_render_buffer_->AllocateStorage(
4188 feature_info_.get(),
4189 offscreen_size_,
4190 offscreen_target_color_format_,
4191 offscreen_target_samples_)) {
4192 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4193 << "to allocate storage for offscreen target color buffer.";
4194 return false;
4196 } else {
4197 if (!offscreen_target_color_texture_->AllocateStorage(
4198 offscreen_size_, offscreen_target_color_format_, false)) {
4199 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4200 << "to allocate storage for offscreen target color texture.";
4201 return false;
4204 if (offscreen_target_depth_format_ &&
4205 !offscreen_target_depth_render_buffer_->AllocateStorage(
4206 feature_info_.get(),
4207 offscreen_size_,
4208 offscreen_target_depth_format_,
4209 offscreen_target_samples_)) {
4210 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4211 << "to allocate storage for offscreen target depth buffer.";
4212 return false;
4214 if (offscreen_target_stencil_format_ &&
4215 !offscreen_target_stencil_render_buffer_->AllocateStorage(
4216 feature_info_.get(),
4217 offscreen_size_,
4218 offscreen_target_stencil_format_,
4219 offscreen_target_samples_)) {
4220 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4221 << "to allocate storage for offscreen target stencil buffer.";
4222 return false;
4225 // Attach the offscreen target buffers to the target frame buffer.
4226 if (IsOffscreenBufferMultisampled()) {
4227 offscreen_target_frame_buffer_->AttachRenderBuffer(
4228 GL_COLOR_ATTACHMENT0,
4229 offscreen_target_color_render_buffer_.get());
4230 } else {
4231 offscreen_target_frame_buffer_->AttachRenderTexture(
4232 offscreen_target_color_texture_.get());
4234 if (offscreen_target_depth_format_) {
4235 offscreen_target_frame_buffer_->AttachRenderBuffer(
4236 GL_DEPTH_ATTACHMENT,
4237 offscreen_target_depth_render_buffer_.get());
4239 const bool packed_depth_stencil =
4240 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4241 if (packed_depth_stencil) {
4242 offscreen_target_frame_buffer_->AttachRenderBuffer(
4243 GL_STENCIL_ATTACHMENT,
4244 offscreen_target_depth_render_buffer_.get());
4245 } else if (offscreen_target_stencil_format_) {
4246 offscreen_target_frame_buffer_->AttachRenderBuffer(
4247 GL_STENCIL_ATTACHMENT,
4248 offscreen_target_stencil_render_buffer_.get());
4251 if (offscreen_target_frame_buffer_->CheckStatus() !=
4252 GL_FRAMEBUFFER_COMPLETE) {
4253 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4254 << "because offscreen FBO was incomplete.";
4255 return false;
4258 // Clear the target frame buffer.
4260 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4261 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f);
4262 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4263 glClearStencil(0);
4264 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4265 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4266 glClearDepth(0);
4267 state_.SetDeviceDepthMask(GL_TRUE);
4268 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4269 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4270 RestoreClearState();
4273 // Destroy the offscreen resolved framebuffers.
4274 if (offscreen_resolved_frame_buffer_.get())
4275 offscreen_resolved_frame_buffer_->Destroy();
4276 if (offscreen_resolved_color_texture_.get())
4277 offscreen_resolved_color_texture_->Destroy();
4278 offscreen_resolved_color_texture_.reset();
4279 offscreen_resolved_frame_buffer_.reset();
4281 return true;
4284 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4285 const void* cmd_data) {
4286 const gles2::cmds::ResizeCHROMIUM& c =
4287 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4288 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4289 return error::kDeferCommandUntilLater;
4291 GLuint width = static_cast<GLuint>(c.width);
4292 GLuint height = static_cast<GLuint>(c.height);
4293 GLfloat scale_factor = c.scale_factor;
4294 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4296 width = std::max(1U, width);
4297 height = std::max(1U, height);
4299 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4300 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4301 // Make sure that we are done drawing to the back buffer before resizing.
4302 glFinish();
4303 #endif
4304 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4305 if (is_offscreen) {
4306 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4307 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4308 << "ResizeOffscreenFrameBuffer failed.";
4309 return error::kLostContext;
4313 if (!resize_callback_.is_null()) {
4314 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4315 DCHECK(context_->IsCurrent(surface_.get()));
4316 if (!context_->IsCurrent(surface_.get())) {
4317 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4318 << "current after resize callback.";
4319 return error::kLostContext;
4323 return error::kNoError;
4326 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4327 if (command_id > kStartPoint && command_id < kNumCommands) {
4328 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4330 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4333 // Decode a command, and call the corresponding GL functions.
4334 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4335 // of commands at once, and is now only used for tests that need to track
4336 // individual commands.
4337 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4338 unsigned int arg_count,
4339 const void* cmd_data) {
4340 return DoCommands(1, cmd_data, arg_count + 1, 0);
4343 // Decode multiple commands, and call the corresponding GL functions.
4344 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4345 // changed by a (malicious) client at any time, so if validation has to happen,
4346 // it should operate on a copy of them.
4347 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4348 // interest of performance in this critical execution loop.
4349 template <bool DebugImpl>
4350 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4351 const void* buffer,
4352 int num_entries,
4353 int* entries_processed) {
4354 commands_to_process_ = num_commands;
4355 error::Error result = error::kNoError;
4356 const CommandBufferEntry* cmd_data =
4357 static_cast<const CommandBufferEntry*>(buffer);
4358 int process_pos = 0;
4359 unsigned int command = 0;
4361 while (process_pos < num_entries && result == error::kNoError &&
4362 commands_to_process_--) {
4363 const unsigned int size = cmd_data->value_header.size;
4364 command = cmd_data->value_header.command;
4366 if (size == 0) {
4367 result = error::kInvalidSize;
4368 break;
4371 if (static_cast<int>(size) + process_pos > num_entries) {
4372 result = error::kOutOfBounds;
4373 break;
4376 if (DebugImpl && log_commands()) {
4377 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4378 << "cmd: " << GetCommandName(command);
4381 const unsigned int arg_count = size - 1;
4382 unsigned int command_index = command - kStartPoint - 1;
4383 if (command_index < arraysize(command_info)) {
4384 const CommandInfo& info = command_info[command_index];
4385 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4386 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4387 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4388 bool doing_gpu_trace = false;
4389 if (DebugImpl && gpu_trace_commands_) {
4390 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4391 doing_gpu_trace = true;
4392 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4393 GetCommandName(command),
4394 kTraceDecoder);
4398 uint32 immediate_data_size = (arg_count - info_arg_count) *
4399 sizeof(CommandBufferEntry); // NOLINT
4401 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4403 if (DebugImpl && doing_gpu_trace)
4404 gpu_tracer_->End(kTraceDecoder);
4406 if (DebugImpl && debug()) {
4407 GLenum error;
4408 while ((error = glGetError()) != GL_NO_ERROR) {
4409 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4410 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4411 << " : " << GetCommandName(command);
4412 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4415 } else {
4416 result = error::kInvalidArguments;
4418 } else {
4419 result = DoCommonCommand(command, arg_count, cmd_data);
4422 if (result == error::kNoError &&
4423 current_decoder_error_ != error::kNoError) {
4424 result = current_decoder_error_;
4425 current_decoder_error_ = error::kNoError;
4428 if (result != error::kDeferCommandUntilLater) {
4429 process_pos += size;
4430 cmd_data += size;
4434 if (entries_processed)
4435 *entries_processed = process_pos;
4437 if (error::IsError(result)) {
4438 LOG(ERROR) << "Error: " << result << " for Command "
4439 << GetCommandName(command);
4442 return result;
4445 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4446 const void* buffer,
4447 int num_entries,
4448 int* entries_processed) {
4449 if (gpu_debug_commands_) {
4450 return DoCommandsImpl<true>(
4451 num_commands, buffer, num_entries, entries_processed);
4452 } else {
4453 return DoCommandsImpl<false>(
4454 num_commands, buffer, num_entries, entries_processed);
4458 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4459 buffer_manager()->RemoveBuffer(client_id);
4462 void GLES2DecoderImpl::DoFinish() {
4463 glFinish();
4464 ProcessPendingReadPixels(true);
4465 ProcessPendingQueries(true);
4468 void GLES2DecoderImpl::DoFlush() {
4469 glFlush();
4470 ProcessPendingQueries(false);
4473 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4474 GLuint texture_index = texture_unit - GL_TEXTURE0;
4475 if (texture_index >= state_.texture_units.size()) {
4476 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4477 "glActiveTexture", texture_unit, "texture_unit");
4478 return;
4480 state_.active_texture_unit = texture_index;
4481 glActiveTexture(texture_unit);
4484 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4485 Buffer* buffer = NULL;
4486 GLuint service_id = 0;
4487 if (client_id != 0) {
4488 buffer = GetBuffer(client_id);
4489 if (!buffer) {
4490 if (!group_->bind_generates_resource()) {
4491 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4492 "glBindBuffer",
4493 "id not generated by glGenBuffers");
4494 return;
4497 // It's a new id so make a buffer buffer for it.
4498 glGenBuffersARB(1, &service_id);
4499 CreateBuffer(client_id, service_id);
4500 buffer = GetBuffer(client_id);
4503 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4504 if (buffer) {
4505 if (!buffer_manager()->SetTarget(buffer, target)) {
4506 LOCAL_SET_GL_ERROR(
4507 GL_INVALID_OPERATION,
4508 "glBindBuffer", "buffer bound to more than 1 target");
4509 return;
4511 service_id = buffer->service_id();
4513 state_.SetBoundBuffer(target, buffer);
4514 glBindBuffer(target, service_id);
4517 void GLES2DecoderImpl::DoBindBufferBase(GLenum target, GLuint index,
4518 GLuint client_id) {
4519 Buffer* buffer = NULL;
4520 GLuint service_id = 0;
4521 if (client_id != 0) {
4522 buffer = GetBuffer(client_id);
4523 if (!buffer) {
4524 if (!group_->bind_generates_resource()) {
4525 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4526 "glBindBufferBase",
4527 "id not generated by glGenBuffers");
4528 return;
4531 // It's a new id so make a buffer for it.
4532 glGenBuffersARB(1, &service_id);
4533 CreateBuffer(client_id, service_id);
4534 buffer = GetBuffer(client_id);
4537 LogClientServiceForInfo(buffer, client_id, "glBindBufferBase");
4538 if (buffer) {
4539 // TODO(kbr): track indexed bound buffers.
4540 service_id = buffer->service_id();
4542 glBindBufferBase(target, index, service_id);
4545 void GLES2DecoderImpl::DoBindBufferRange(GLenum target, GLuint index,
4546 GLuint client_id,
4547 GLintptr offset,
4548 GLsizeiptr size) {
4549 Buffer* buffer = NULL;
4550 GLuint service_id = 0;
4551 if (client_id != 0) {
4552 buffer = GetBuffer(client_id);
4553 if (!buffer) {
4554 if (!group_->bind_generates_resource()) {
4555 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4556 "glBindBufferRange",
4557 "id not generated by glGenBuffers");
4558 return;
4561 // It's a new id so make a buffer for it.
4562 glGenBuffersARB(1, &service_id);
4563 CreateBuffer(client_id, service_id);
4564 buffer = GetBuffer(client_id);
4567 LogClientServiceForInfo(buffer, client_id, "glBindBufferRange");
4568 if (buffer) {
4569 // TODO(kbr): track indexed bound buffers.
4570 service_id = buffer->service_id();
4572 glBindBufferRange(target, index, service_id, offset, size);
4575 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4576 Framebuffer* framebuffer =
4577 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4578 if (framebuffer)
4579 return framebuffer->HasAlphaMRT();
4580 return BackBufferHasAlpha();
4583 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4584 Framebuffer* framebuffer =
4585 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4586 if (framebuffer) {
4587 return framebuffer->HasDepthAttachment();
4589 if (offscreen_target_frame_buffer_.get()) {
4590 return offscreen_target_depth_format_ != 0;
4592 return back_buffer_has_depth_;
4595 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4596 Framebuffer* framebuffer =
4597 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4598 if (framebuffer) {
4599 return framebuffer->HasStencilAttachment();
4601 if (offscreen_target_frame_buffer_.get()) {
4602 return offscreen_target_stencil_format_ != 0 ||
4603 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4605 return back_buffer_has_stencil_;
4608 void GLES2DecoderImpl::ApplyDirtyState() {
4609 if (framebuffer_state_.clear_state_dirty) {
4610 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha();
4611 state_.SetDeviceColorMask(state_.color_mask_red,
4612 state_.color_mask_green,
4613 state_.color_mask_blue,
4614 state_.color_mask_alpha && have_alpha);
4616 bool have_depth = BoundFramebufferHasDepthAttachment();
4617 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4619 bool have_stencil = BoundFramebufferHasStencilAttachment();
4620 state_.SetDeviceStencilMaskSeparate(
4621 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4622 state_.SetDeviceStencilMaskSeparate(
4623 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4625 state_.SetDeviceCapabilityState(
4626 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4627 state_.SetDeviceCapabilityState(
4628 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4629 framebuffer_state_.clear_state_dirty = false;
4633 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4634 return (offscreen_target_frame_buffer_.get())
4635 ? offscreen_target_frame_buffer_->id()
4636 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4639 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4640 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4641 "context", logger_.GetLogPrefix());
4642 // Restore the Framebuffer first because of bugs in Intel drivers.
4643 // Intel drivers incorrectly clip the viewport settings to
4644 // the size of the current framebuffer object.
4645 RestoreFramebufferBindings();
4646 state_.RestoreState(prev_state);
4649 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4650 GLuint service_id =
4651 framebuffer_state_.bound_draw_framebuffer.get()
4652 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4653 : GetBackbufferServiceId();
4654 if (!features().chromium_framebuffer_multisample) {
4655 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4656 } else {
4657 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4658 service_id = framebuffer_state_.bound_read_framebuffer.get()
4659 ? framebuffer_state_.bound_read_framebuffer->service_id()
4660 : GetBackbufferServiceId();
4661 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4663 OnFboChanged();
4666 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4667 state_.RestoreRenderbufferBindings();
4670 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4671 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4672 if (texture) {
4673 GLenum target = texture->target();
4674 glBindTexture(target, service_id);
4675 glTexParameteri(
4676 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4677 glTexParameteri(
4678 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4679 glTexParameteri(
4680 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4681 glTexParameteri(
4682 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4683 RestoreTextureUnitBindings(state_.active_texture_unit);
4687 void GLES2DecoderImpl::ClearAllAttributes() const {
4688 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4689 // other VAOs.
4690 if (feature_info_->feature_flags().native_vertex_array_object)
4691 glBindVertexArrayOES(0);
4693 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4694 if (i != 0) // Never disable attribute 0
4695 glDisableVertexAttribArray(i);
4696 if (features().angle_instanced_arrays)
4697 glVertexAttribDivisorANGLE(i, 0);
4701 void GLES2DecoderImpl::RestoreAllAttributes() const {
4702 state_.RestoreVertexAttribs();
4705 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4706 state_.SetIgnoreCachedStateForTest(ignore);
4709 void GLES2DecoderImpl::OnFboChanged() const {
4710 if (workarounds().restore_scissor_on_fbo_change)
4711 state_.fbo_binding_for_scissor_workaround_dirty = true;
4713 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4714 GLint bound_fbo_unsigned = -1;
4715 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4716 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4717 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4718 surface_->NotifyWasBound();
4722 // Called after the FBO is checked for completeness.
4723 void GLES2DecoderImpl::OnUseFramebuffer() const {
4724 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4725 state_.fbo_binding_for_scissor_workaround_dirty = false;
4726 // The driver forgets the correct scissor when modifying the FBO binding.
4727 glScissor(state_.scissor_x,
4728 state_.scissor_y,
4729 state_.scissor_width,
4730 state_.scissor_height);
4732 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4733 // it's unclear how this bug works.
4734 glFlush();
4738 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4739 Framebuffer* framebuffer = NULL;
4740 GLuint service_id = 0;
4741 if (client_id != 0) {
4742 framebuffer = GetFramebuffer(client_id);
4743 if (!framebuffer) {
4744 if (!group_->bind_generates_resource()) {
4745 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4746 "glBindFramebuffer",
4747 "id not generated by glGenFramebuffers");
4748 return;
4751 // It's a new id so make a framebuffer framebuffer for it.
4752 glGenFramebuffersEXT(1, &service_id);
4753 CreateFramebuffer(client_id, service_id);
4754 framebuffer = GetFramebuffer(client_id);
4755 } else {
4756 service_id = framebuffer->service_id();
4758 framebuffer->MarkAsValid();
4760 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4762 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4763 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4766 // vmiura: This looks like dup code
4767 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4768 framebuffer_state_.bound_read_framebuffer = framebuffer;
4771 framebuffer_state_.clear_state_dirty = true;
4773 // If we are rendering to the backbuffer get the FBO id for any simulated
4774 // backbuffer.
4775 if (framebuffer == NULL) {
4776 service_id = GetBackbufferServiceId();
4779 glBindFramebufferEXT(target, service_id);
4780 OnFboChanged();
4783 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4784 Renderbuffer* renderbuffer = NULL;
4785 GLuint service_id = 0;
4786 if (client_id != 0) {
4787 renderbuffer = GetRenderbuffer(client_id);
4788 if (!renderbuffer) {
4789 if (!group_->bind_generates_resource()) {
4790 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4791 "glBindRenderbuffer",
4792 "id not generated by glGenRenderbuffers");
4793 return;
4796 // It's a new id so make a renderbuffer for it.
4797 glGenRenderbuffersEXT(1, &service_id);
4798 CreateRenderbuffer(client_id, service_id);
4799 renderbuffer = GetRenderbuffer(client_id);
4800 } else {
4801 service_id = renderbuffer->service_id();
4803 renderbuffer->MarkAsValid();
4805 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4806 state_.bound_renderbuffer = renderbuffer;
4807 state_.bound_renderbuffer_valid = true;
4808 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4811 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4812 TextureRef* texture_ref = NULL;
4813 GLuint service_id = 0;
4814 if (client_id != 0) {
4815 texture_ref = GetTexture(client_id);
4816 if (!texture_ref) {
4817 if (!group_->bind_generates_resource()) {
4818 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4819 "glBindTexture",
4820 "id not generated by glGenTextures");
4821 return;
4824 // It's a new id so make a texture texture for it.
4825 glGenTextures(1, &service_id);
4826 DCHECK_NE(0u, service_id);
4827 CreateTexture(client_id, service_id);
4828 texture_ref = GetTexture(client_id);
4830 } else {
4831 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4834 // Check the texture exists
4835 if (texture_ref) {
4836 Texture* texture = texture_ref->texture();
4837 // Check that we are not trying to bind it to a different target.
4838 if (texture->target() != 0 && texture->target() != target) {
4839 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4840 "glBindTexture",
4841 "texture bound to more than 1 target.");
4842 return;
4844 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4845 if (texture->target() == 0) {
4846 texture_manager()->SetTarget(texture_ref, target);
4848 glBindTexture(target, texture->service_id());
4849 } else {
4850 glBindTexture(target, 0);
4853 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4854 unit.bind_target = target;
4855 switch (target) {
4856 case GL_TEXTURE_2D:
4857 unit.bound_texture_2d = texture_ref;
4858 break;
4859 case GL_TEXTURE_CUBE_MAP:
4860 unit.bound_texture_cube_map = texture_ref;
4861 break;
4862 case GL_TEXTURE_EXTERNAL_OES:
4863 unit.bound_texture_external_oes = texture_ref;
4864 break;
4865 case GL_TEXTURE_RECTANGLE_ARB:
4866 unit.bound_texture_rectangle_arb = texture_ref;
4867 break;
4868 case GL_TEXTURE_3D:
4869 unit.bound_texture_3d = texture_ref;
4870 break;
4871 case GL_TEXTURE_2D_ARRAY:
4872 unit.bound_texture_2d_array = texture_ref;
4873 break;
4874 default:
4875 NOTREACHED(); // Validation should prevent us getting here.
4876 break;
4880 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4881 if (state_.vertex_attrib_manager->Enable(index, false)) {
4882 if (index != 0 ||
4883 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4884 glDisableVertexAttribArray(index);
4886 } else {
4887 LOCAL_SET_GL_ERROR(
4888 GL_INVALID_VALUE,
4889 "glDisableVertexAttribArray", "index out of range");
4893 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4894 GLsizei numAttachments,
4895 const GLenum* attachments) {
4896 if (workarounds().disable_discard_framebuffer)
4897 return;
4899 Framebuffer* framebuffer =
4900 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4902 // Validates the attachments. If one of them fails
4903 // the whole command fails.
4904 for (GLsizei i = 0; i < numAttachments; ++i) {
4905 if ((framebuffer &&
4906 !validators_->attachment.IsValid(attachments[i])) ||
4907 (!framebuffer &&
4908 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4909 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4910 "glDiscardFramebufferEXT", attachments[i], "attachments");
4911 return;
4915 // Marks each one of them as not cleared
4916 for (GLsizei i = 0; i < numAttachments; ++i) {
4917 if (framebuffer) {
4918 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4919 texture_manager(),
4920 attachments[i],
4921 false);
4922 } else {
4923 switch (attachments[i]) {
4924 case GL_COLOR_EXT:
4925 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4926 break;
4927 case GL_DEPTH_EXT:
4928 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4929 case GL_STENCIL_EXT:
4930 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4931 break;
4932 default:
4933 NOTREACHED();
4934 break;
4939 // If the default framebuffer is bound but we are still rendering to an
4940 // FBO, translate attachment names that refer to default framebuffer
4941 // channels to corresponding framebuffer attachments.
4942 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4943 for (GLsizei i = 0; i < numAttachments; ++i) {
4944 GLenum attachment = attachments[i];
4945 if (!framebuffer && GetBackbufferServiceId()) {
4946 switch (attachment) {
4947 case GL_COLOR_EXT:
4948 attachment = GL_COLOR_ATTACHMENT0;
4949 break;
4950 case GL_DEPTH_EXT:
4951 attachment = GL_DEPTH_ATTACHMENT;
4952 break;
4953 case GL_STENCIL_EXT:
4954 attachment = GL_STENCIL_ATTACHMENT;
4955 break;
4956 default:
4957 NOTREACHED();
4958 return;
4961 translated_attachments[i] = attachment;
4964 ScopedRenderTo do_render(framebuffer);
4965 if (feature_info_->gl_version_info().is_es3) {
4966 glInvalidateFramebuffer(
4967 target, numAttachments, translated_attachments.get());
4968 } else {
4969 glDiscardFramebufferEXT(
4970 target, numAttachments, translated_attachments.get());
4974 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4975 if (state_.vertex_attrib_manager->Enable(index, true)) {
4976 glEnableVertexAttribArray(index);
4977 } else {
4978 LOCAL_SET_GL_ERROR(
4979 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4983 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4984 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4985 &state_, target);
4986 if (!texture_ref ||
4987 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4988 LOCAL_SET_GL_ERROR(
4989 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4990 return;
4993 if (target == GL_TEXTURE_CUBE_MAP) {
4994 for (int i = 0; i < 6; ++i) {
4995 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4996 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4997 LOCAL_SET_GL_ERROR(
4998 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4999 return;
5002 } else {
5003 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
5004 LOCAL_SET_GL_ERROR(
5005 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
5006 return;
5010 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
5011 // Workaround for Mac driver bug. In the large scheme of things setting
5012 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
5013 // hit so there's probably no need to make this conditional. The bug appears
5014 // to be that if the filtering mode is set to something that doesn't require
5015 // mipmaps for rendering, or is never set to something other than the default,
5016 // then glGenerateMipmap misbehaves.
5017 if (workarounds().set_texture_filter_before_generating_mipmap) {
5018 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
5020 glGenerateMipmapEXT(target);
5021 if (workarounds().set_texture_filter_before_generating_mipmap) {
5022 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
5023 texture_ref->texture()->min_filter());
5025 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
5026 if (error == GL_NO_ERROR) {
5027 texture_manager()->MarkMipmapsGenerated(texture_ref);
5031 bool GLES2DecoderImpl::GetHelper(
5032 GLenum pname, GLint* params, GLsizei* num_written) {
5033 DCHECK(num_written);
5034 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
5035 switch (pname) {
5036 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
5037 *num_written = 1;
5038 // Return the GL implementation's preferred format and (see below type)
5039 // if we have the GL extension that exposes this. This allows the GPU
5040 // client to use the implementation's preferred format for glReadPixels
5041 // for optimisation.
5043 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
5044 // case when requested on integer/floating point buffers but which is
5045 // acceptable on GLES2 and with the GL_OES_read_format extension.
5047 // Therefore if an error occurs we swallow the error and use the
5048 // internal implementation.
5049 if (params) {
5050 if (context_->HasExtension("GL_OES_read_format")) {
5051 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
5052 GetErrorState());
5053 glGetIntegerv(pname, params);
5054 if (glGetError() == GL_NO_ERROR)
5055 return true;
5057 *params = GLES2Util::GetGLReadPixelsImplementationFormat(
5058 GetBoundReadFrameBufferInternalFormat());
5060 return true;
5061 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
5062 *num_written = 1;
5063 if (params) {
5064 if (context_->HasExtension("GL_OES_read_format")) {
5065 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
5066 GetErrorState());
5067 glGetIntegerv(pname, params);
5068 if (glGetError() == GL_NO_ERROR)
5069 return true;
5071 *params = GLES2Util::GetGLReadPixelsImplementationType(
5072 GetBoundReadFrameBufferInternalFormat(),
5073 GetBoundReadFrameBufferTextureType());
5075 return true;
5076 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
5077 *num_written = 1;
5078 if (params) {
5079 *params = group_->max_fragment_uniform_vectors();
5081 return true;
5082 case GL_MAX_VARYING_VECTORS:
5083 *num_written = 1;
5084 if (params) {
5085 *params = group_->max_varying_vectors();
5087 return true;
5088 case GL_MAX_VERTEX_UNIFORM_VECTORS:
5089 *num_written = 1;
5090 if (params) {
5091 *params = group_->max_vertex_uniform_vectors();
5093 return true;
5096 if (unsafe_es3_apis_enabled()) {
5097 switch (pname) {
5098 case GL_MAX_VARYING_COMPONENTS: {
5099 if (feature_info_->gl_version_info().is_es) {
5100 // We can just delegate this query to the driver.
5101 return false;
5104 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5105 // OpenGL core profile, so for simplicity, just compute it
5106 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5107 // configurations.
5108 GLint max_varying_vectors = 0;
5109 glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors);
5110 *num_written = 1;
5111 if (params) {
5112 *params = max_varying_vectors * 4;
5114 return true;
5116 case GL_READ_BUFFER:
5117 *num_written = 1;
5118 if (params) {
5119 Framebuffer* framebuffer =
5120 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
5121 GLenum read_buffer;
5122 if (framebuffer) {
5123 read_buffer = framebuffer->read_buffer();
5124 } else {
5125 read_buffer = back_buffer_read_buffer_;
5127 *params = static_cast<GLint>(read_buffer);
5129 return true;
5132 switch (pname) {
5133 case GL_MAX_VIEWPORT_DIMS:
5134 if (offscreen_target_frame_buffer_.get()) {
5135 *num_written = 2;
5136 if (params) {
5137 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5138 params[1] = renderbuffer_manager()->max_renderbuffer_size();
5140 return true;
5142 return false;
5143 case GL_MAX_SAMPLES:
5144 *num_written = 1;
5145 if (params) {
5146 params[0] = renderbuffer_manager()->max_samples();
5148 return true;
5149 case GL_MAX_RENDERBUFFER_SIZE:
5150 *num_written = 1;
5151 if (params) {
5152 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5154 return true;
5155 case GL_MAX_TEXTURE_SIZE:
5156 *num_written = 1;
5157 if (params) {
5158 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
5160 return true;
5161 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
5162 *num_written = 1;
5163 if (params) {
5164 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
5166 return true;
5167 case GL_MAX_COLOR_ATTACHMENTS_EXT:
5168 *num_written = 1;
5169 if (params) {
5170 params[0] = group_->max_color_attachments();
5172 return true;
5173 case GL_MAX_DRAW_BUFFERS_ARB:
5174 *num_written = 1;
5175 if (params) {
5176 params[0] = group_->max_draw_buffers();
5178 return true;
5179 case GL_ALPHA_BITS:
5180 *num_written = 1;
5181 if (params) {
5182 GLint v = 0;
5183 Framebuffer* framebuffer =
5184 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5185 if (framebuffer) {
5186 if (framebuffer->HasAlphaMRT() &&
5187 framebuffer->HasSameInternalFormatsMRT()) {
5188 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5189 glGetFramebufferAttachmentParameterivEXT(
5190 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5191 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
5192 } else {
5193 glGetIntegerv(GL_ALPHA_BITS, &v);
5196 } else {
5197 v = (BackBufferHasAlpha() ? 8 : 0);
5199 params[0] = v;
5201 return true;
5202 case GL_DEPTH_BITS:
5203 *num_written = 1;
5204 if (params) {
5205 GLint v = 0;
5206 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5207 Framebuffer* framebuffer =
5208 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5209 if (framebuffer) {
5210 glGetFramebufferAttachmentParameterivEXT(
5211 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
5212 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
5213 } else {
5214 v = (back_buffer_has_depth_ ? 24 : 0);
5216 } else {
5217 glGetIntegerv(GL_DEPTH_BITS, &v);
5219 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
5221 return true;
5222 case GL_RED_BITS:
5223 case GL_GREEN_BITS:
5224 case GL_BLUE_BITS:
5225 *num_written = 1;
5226 if (params) {
5227 GLint v = 0;
5228 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5229 Framebuffer* framebuffer =
5230 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5231 if (framebuffer) {
5232 GLenum framebuffer_enum = 0;
5233 switch (pname) {
5234 case GL_RED_BITS:
5235 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
5236 break;
5237 case GL_GREEN_BITS:
5238 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
5239 break;
5240 case GL_BLUE_BITS:
5241 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
5242 break;
5244 glGetFramebufferAttachmentParameterivEXT(
5245 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
5246 } else {
5247 v = 8;
5249 } else {
5250 glGetIntegerv(pname, &v);
5252 params[0] = v;
5254 return true;
5255 case GL_STENCIL_BITS:
5256 *num_written = 1;
5257 if (params) {
5258 GLint v = 0;
5259 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5260 Framebuffer* framebuffer =
5261 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5262 if (framebuffer) {
5263 glGetFramebufferAttachmentParameterivEXT(
5264 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
5265 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
5266 } else {
5267 v = (back_buffer_has_stencil_ ? 8 : 0);
5269 } else {
5270 glGetIntegerv(GL_STENCIL_BITS, &v);
5272 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
5274 return true;
5275 case GL_COMPRESSED_TEXTURE_FORMATS:
5276 *num_written = validators_->compressed_texture_format.GetValues().size();
5277 if (params) {
5278 for (GLint ii = 0; ii < *num_written; ++ii) {
5279 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
5282 return true;
5283 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
5284 *num_written = 1;
5285 if (params) {
5286 *params = validators_->compressed_texture_format.GetValues().size();
5288 return true;
5289 case GL_NUM_SHADER_BINARY_FORMATS:
5290 *num_written = 1;
5291 if (params) {
5292 *params = validators_->shader_binary_format.GetValues().size();
5294 return true;
5295 case GL_SHADER_BINARY_FORMATS:
5296 *num_written = validators_->shader_binary_format.GetValues().size();
5297 if (params) {
5298 for (GLint ii = 0; ii < *num_written; ++ii) {
5299 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5302 return true;
5303 case GL_SHADER_COMPILER:
5304 *num_written = 1;
5305 if (params) {
5306 *params = GL_TRUE;
5308 return true;
5309 case GL_ARRAY_BUFFER_BINDING:
5310 *num_written = 1;
5311 if (params) {
5312 *params = GetClientId(
5313 buffer_manager(), state_.bound_array_buffer.get());
5315 return true;
5316 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5317 *num_written = 1;
5318 if (params) {
5319 *params = GetClientId(
5320 buffer_manager(),
5321 state_.vertex_attrib_manager->element_array_buffer());
5323 return true;
5324 case GL_COPY_READ_BUFFER_BINDING:
5325 *num_written = 1;
5326 if (params) {
5327 *params = GetClientId(
5328 buffer_manager(), state_.bound_copy_read_buffer.get());
5330 return true;
5331 case GL_COPY_WRITE_BUFFER_BINDING:
5332 *num_written = 1;
5333 if (params) {
5334 *params = GetClientId(
5335 buffer_manager(), state_.bound_copy_write_buffer.get());
5337 return true;
5338 case GL_PIXEL_PACK_BUFFER_BINDING:
5339 *num_written = 1;
5340 if (params) {
5341 *params = GetClientId(
5342 buffer_manager(), state_.bound_pixel_pack_buffer.get());
5344 return true;
5345 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5346 *num_written = 1;
5347 if (params) {
5348 *params = GetClientId(
5349 buffer_manager(), state_.bound_pixel_unpack_buffer.get());
5351 return true;
5352 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5353 *num_written = 1;
5354 if (params) {
5355 *params = GetClientId(
5356 buffer_manager(), state_.bound_transform_feedback_buffer.get());
5358 return true;
5359 case GL_UNIFORM_BUFFER_BINDING:
5360 *num_written = 1;
5361 if (params) {
5362 *params = GetClientId(
5363 buffer_manager(), state_.bound_uniform_buffer.get());
5365 return true;
5366 case GL_FRAMEBUFFER_BINDING:
5367 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5368 *num_written = 1;
5369 if (params) {
5370 *params = GetClientId(
5371 framebuffer_manager(),
5372 GetFramebufferInfoForTarget(GL_FRAMEBUFFER));
5374 return true;
5375 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5376 *num_written = 1;
5377 if (params) {
5378 *params = GetClientId(
5379 framebuffer_manager(),
5380 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT));
5382 return true;
5383 case GL_RENDERBUFFER_BINDING:
5384 *num_written = 1;
5385 if (params) {
5386 Renderbuffer* renderbuffer =
5387 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5388 if (renderbuffer) {
5389 *params = renderbuffer->client_id();
5390 } else {
5391 *params = 0;
5394 return true;
5395 case GL_CURRENT_PROGRAM:
5396 *num_written = 1;
5397 if (params) {
5398 *params = GetClientId(program_manager(), state_.current_program.get());
5400 return true;
5401 case GL_VERTEX_ARRAY_BINDING_OES:
5402 *num_written = 1;
5403 if (params) {
5404 if (state_.vertex_attrib_manager.get() !=
5405 state_.default_vertex_attrib_manager.get()) {
5406 GLuint client_id = 0;
5407 vertex_array_manager_->GetClientId(
5408 state_.vertex_attrib_manager->service_id(), &client_id);
5409 *params = client_id;
5410 } else {
5411 *params = 0;
5414 return true;
5415 case GL_TEXTURE_BINDING_2D:
5416 *num_written = 1;
5417 if (params) {
5418 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5419 if (unit.bound_texture_2d.get()) {
5420 *params = unit.bound_texture_2d->client_id();
5421 } else {
5422 *params = 0;
5425 return true;
5426 case GL_TEXTURE_BINDING_CUBE_MAP:
5427 *num_written = 1;
5428 if (params) {
5429 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5430 if (unit.bound_texture_cube_map.get()) {
5431 *params = unit.bound_texture_cube_map->client_id();
5432 } else {
5433 *params = 0;
5436 return true;
5437 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5438 *num_written = 1;
5439 if (params) {
5440 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5441 if (unit.bound_texture_external_oes.get()) {
5442 *params = unit.bound_texture_external_oes->client_id();
5443 } else {
5444 *params = 0;
5447 return true;
5448 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5449 *num_written = 1;
5450 if (params) {
5451 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5452 if (unit.bound_texture_rectangle_arb.get()) {
5453 *params = unit.bound_texture_rectangle_arb->client_id();
5454 } else {
5455 *params = 0;
5458 return true;
5459 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5460 *num_written = 1;
5461 if (params) {
5462 params[0] = group_->bind_generates_resource() ? 1 : 0;
5464 return true;
5465 default:
5466 if (pname >= GL_DRAW_BUFFER0_ARB &&
5467 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5468 *num_written = 1;
5469 if (params) {
5470 Framebuffer* framebuffer =
5471 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5472 if (framebuffer) {
5473 params[0] = framebuffer->GetDrawBuffer(pname);
5474 } else { // backbuffer
5475 if (pname == GL_DRAW_BUFFER0_ARB)
5476 params[0] = back_buffer_draw_buffer_;
5477 else
5478 params[0] = GL_NONE;
5481 return true;
5483 *num_written = util_.GLGetNumValuesReturned(pname);
5484 return false;
5488 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5489 GLenum pname, GLsizei* num_values) {
5490 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5491 return true;
5493 return GetHelper(pname, NULL, num_values);
5496 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5497 if (GL_MAX_SAMPLES == pname &&
5498 features().use_img_for_multisampled_render_to_texture) {
5499 return GL_MAX_SAMPLES_IMG;
5501 return pname;
5504 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5505 DCHECK(params);
5506 GLsizei num_written = 0;
5507 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5508 scoped_ptr<GLint[]> values(new GLint[num_written]);
5509 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5510 GetHelper(pname, values.get(), &num_written);
5512 for (GLsizei ii = 0; ii < num_written; ++ii) {
5513 params[ii] = static_cast<GLboolean>(values[ii]);
5515 } else {
5516 pname = AdjustGetPname(pname);
5517 glGetBooleanv(pname, params);
5521 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5522 DCHECK(params);
5523 GLsizei num_written = 0;
5524 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5525 if (GetHelper(pname, NULL, &num_written)) {
5526 scoped_ptr<GLint[]> values(new GLint[num_written]);
5527 GetHelper(pname, values.get(), &num_written);
5528 for (GLsizei ii = 0; ii < num_written; ++ii) {
5529 params[ii] = static_cast<GLfloat>(values[ii]);
5531 } else {
5532 pname = AdjustGetPname(pname);
5533 glGetFloatv(pname, params);
5538 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5539 DCHECK(params);
5540 if (unsafe_es3_apis_enabled()) {
5541 switch (pname) {
5542 case GL_MAX_ELEMENT_INDEX: {
5543 if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
5544 feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
5545 glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
5546 } else {
5547 // Assume that desktop GL implementations can generally support
5548 // 32-bit indices.
5549 if (params) {
5550 *params = std::numeric_limits<unsigned int>::max();
5553 return;
5557 pname = AdjustGetPname(pname);
5558 glGetInteger64v(pname, params);
5561 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5562 DCHECK(params);
5563 GLsizei num_written;
5564 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5565 !GetHelper(pname, params, &num_written)) {
5566 pname = AdjustGetPname(pname);
5567 glGetIntegerv(pname, params);
5571 void GLES2DecoderImpl::DoGetProgramiv(
5572 GLuint program_id, GLenum pname, GLint* params) {
5573 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5574 if (!program) {
5575 return;
5577 program->GetProgramiv(pname, params);
5580 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5581 GLenum target, GLenum pname, GLint64* params) {
5582 // Just delegate it. Some validation is actually done before this.
5583 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5584 &state_, target, pname, params);
5587 void GLES2DecoderImpl::DoGetBufferParameteriv(
5588 GLenum target, GLenum pname, GLint* params) {
5589 // Just delegate it. Some validation is actually done before this.
5590 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5591 &state_, target, pname, params);
5594 void GLES2DecoderImpl::DoBindAttribLocation(
5595 GLuint program_id, GLuint index, const char* name) {
5596 if (!StringIsValidForGLES(name)) {
5597 LOCAL_SET_GL_ERROR(
5598 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5599 return;
5601 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5602 LOCAL_SET_GL_ERROR(
5603 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5604 return;
5606 if (index >= group_->max_vertex_attribs()) {
5607 LOCAL_SET_GL_ERROR(
5608 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5609 return;
5611 Program* program = GetProgramInfoNotShader(
5612 program_id, "glBindAttribLocation");
5613 if (!program) {
5614 return;
5616 // At this point, the program's shaders may not be translated yet,
5617 // therefore, we may not find the hashed attribute name.
5618 // glBindAttribLocation call with original name is useless.
5619 // So instead, we should simply cache the binding, and then call
5620 // Program::ExecuteBindAttribLocationCalls() right before link.
5621 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5622 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5623 glBindAttribLocation(program->service_id(), index, name);
5626 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5627 uint32 immediate_data_size,
5628 const void* cmd_data) {
5629 const gles2::cmds::BindAttribLocationBucket& c =
5630 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5631 GLuint program = static_cast<GLuint>(c.program);
5632 GLuint index = static_cast<GLuint>(c.index);
5633 Bucket* bucket = GetBucket(c.name_bucket_id);
5634 if (!bucket || bucket->size() == 0) {
5635 return error::kInvalidArguments;
5637 std::string name_str;
5638 if (!bucket->GetAsString(&name_str)) {
5639 return error::kInvalidArguments;
5641 DoBindAttribLocation(program, index, name_str.c_str());
5642 return error::kNoError;
5645 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5646 GLuint program_id, GLint location, const char* name) {
5647 if (!StringIsValidForGLES(name)) {
5648 LOCAL_SET_GL_ERROR(
5649 GL_INVALID_VALUE,
5650 "glBindUniformLocationCHROMIUM", "Invalid character");
5651 return;
5653 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5654 LOCAL_SET_GL_ERROR(
5655 GL_INVALID_OPERATION,
5656 "glBindUniformLocationCHROMIUM", "reserved prefix");
5657 return;
5659 if (location < 0 || static_cast<uint32>(location) >=
5660 (group_->max_fragment_uniform_vectors() +
5661 group_->max_vertex_uniform_vectors()) * 4) {
5662 LOCAL_SET_GL_ERROR(
5663 GL_INVALID_VALUE,
5664 "glBindUniformLocationCHROMIUM", "location out of range");
5665 return;
5667 Program* program = GetProgramInfoNotShader(
5668 program_id, "glBindUniformLocationCHROMIUM");
5669 if (!program) {
5670 return;
5672 if (!program->SetUniformLocationBinding(name, location)) {
5673 LOCAL_SET_GL_ERROR(
5674 GL_INVALID_VALUE,
5675 "glBindUniformLocationCHROMIUM", "location out of range");
5679 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5680 uint32 immediate_data_size,
5681 const void* cmd_data) {
5682 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5683 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5684 cmd_data);
5685 GLuint program = static_cast<GLuint>(c.program);
5686 GLint location = static_cast<GLint>(c.location);
5687 Bucket* bucket = GetBucket(c.name_bucket_id);
5688 if (!bucket || bucket->size() == 0) {
5689 return error::kInvalidArguments;
5691 std::string name_str;
5692 if (!bucket->GetAsString(&name_str)) {
5693 return error::kInvalidArguments;
5695 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5696 return error::kNoError;
5699 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5700 const void* cmd_data) {
5701 const gles2::cmds::DeleteShader& c =
5702 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5703 GLuint client_id = c.shader;
5704 if (client_id) {
5705 Shader* shader = GetShader(client_id);
5706 if (shader) {
5707 if (!shader->IsDeleted()) {
5708 shader_manager()->Delete(shader);
5710 } else {
5711 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5714 return error::kNoError;
5717 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5718 const void* cmd_data) {
5719 const gles2::cmds::DeleteProgram& c =
5720 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5721 GLuint client_id = c.program;
5722 if (client_id) {
5723 Program* program = GetProgram(client_id);
5724 if (program) {
5725 if (!program->IsDeleted()) {
5726 program_manager()->MarkAsDeleted(shader_manager(), program);
5728 } else {
5729 LOCAL_SET_GL_ERROR(
5730 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5733 return error::kNoError;
5736 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5737 DCHECK(!ShouldDeferDraws());
5738 if (CheckBoundFramebuffersValid("glClear")) {
5739 ApplyDirtyState();
5740 // TODO(zmo): Filter out INTEGER/SIGNED INTEGER images to avoid
5741 // undefined results.
5742 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5743 if (workarounds().gl_clear_broken) {
5744 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5745 GetErrorState());
5746 if (!BoundFramebufferHasDepthAttachment())
5747 mask &= ~GL_DEPTH_BUFFER_BIT;
5748 if (!BoundFramebufferHasStencilAttachment())
5749 mask &= ~GL_STENCIL_BUFFER_BIT;
5750 clear_framebuffer_blit_->ClearFramebuffer(
5751 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5752 state_.color_clear_green, state_.color_clear_blue,
5753 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5754 return error::kNoError;
5756 glClear(mask);
5758 return error::kNoError;
5761 void GLES2DecoderImpl::DoClearBufferiv(
5762 GLenum buffer, GLint drawbuffer, const GLint* value) {
5763 if (!CheckBoundDrawFramebufferValid("glClearBufferiv"))
5764 return;
5765 ApplyDirtyState();
5767 switch (buffer) {
5768 case GL_COLOR:
5769 case GL_STENCIL:
5770 break;
5771 default:
5772 LOCAL_SET_GL_ERROR(
5773 GL_INVALID_ENUM, "glClearBufferiv", "invalid buffer");
5774 return;
5776 GLenum attachment = 0;
5777 if (buffer == GL_COLOR) {
5778 if (drawbuffer < 0 ||
5779 drawbuffer >= static_cast<GLint>(group_->max_draw_buffers())) {
5780 LOCAL_SET_GL_ERROR(
5781 GL_INVALID_VALUE, "glClearBufferiv", "invalid drawBuffer");
5782 return;
5784 GLenum internal_format =
5785 GetBoundColorDrawBufferInternalFormat(drawbuffer);
5786 if (!GLES2Util::IsSignedIntegerFormat(internal_format)) {
5787 // To avoid undefined results, return without calling the gl function.
5788 return;
5790 attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + drawbuffer);
5791 } else {
5792 DCHECK(buffer == GL_STENCIL);
5793 if (drawbuffer != 0) {
5794 LOCAL_SET_GL_ERROR(
5795 GL_INVALID_VALUE, "glClearBufferiv", "invalid drawBuffer");
5796 return;
5798 if (!BoundFramebufferHasStencilAttachment()) {
5799 return;
5801 attachment = GL_STENCIL_ATTACHMENT;
5803 MarkDrawBufferAsCleared(buffer, drawbuffer);
5805 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get(),
5806 attachment);
5807 glClearBufferiv(buffer, drawbuffer, value);
5811 void GLES2DecoderImpl::DoClearBufferuiv(
5812 GLenum buffer, GLint drawbuffer, const GLuint* value) {
5813 if (!CheckBoundDrawFramebufferValid("glClearBufferuiv"))
5814 return;
5815 ApplyDirtyState();
5817 switch (buffer) {
5818 case GL_COLOR:
5819 break;
5820 default:
5821 LOCAL_SET_GL_ERROR(
5822 GL_INVALID_ENUM, "glClearBufferuiv", "invalid buffer");
5823 return;
5825 if (drawbuffer < 0 ||
5826 drawbuffer >= static_cast<GLint>(group_->max_draw_buffers())) {
5827 LOCAL_SET_GL_ERROR(
5828 GL_INVALID_VALUE, "glClearBufferuiv", "invalid drawBuffer");
5829 return;
5831 GLenum internal_format =
5832 GetBoundColorDrawBufferInternalFormat(drawbuffer);
5833 if (!GLES2Util::IsUnsignedIntegerFormat(internal_format)) {
5834 // To avoid undefined results, return without calling the gl function.
5835 return;
5837 MarkDrawBufferAsCleared(buffer, drawbuffer);
5838 GLenum attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + drawbuffer);
5840 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get(),
5841 attachment);
5842 glClearBufferuiv(buffer, drawbuffer, value);
5846 void GLES2DecoderImpl::DoClearBufferfv(
5847 GLenum buffer, GLint drawbuffer, const GLfloat* value) {
5848 if (!CheckBoundDrawFramebufferValid("glClearBufferfv"))
5849 return;
5850 ApplyDirtyState();
5852 switch (buffer) {
5853 case GL_COLOR:
5854 case GL_DEPTH:
5855 break;
5856 default:
5857 LOCAL_SET_GL_ERROR(
5858 GL_INVALID_ENUM, "glClearBufferfv", "invalid buffer");
5859 return;
5861 GLenum attachment = 0;
5862 if (buffer == GL_COLOR) {
5863 if (drawbuffer < 0 ||
5864 drawbuffer >= static_cast<GLint>(group_->max_draw_buffers())) {
5865 LOCAL_SET_GL_ERROR(
5866 GL_INVALID_VALUE, "glClearBufferfv", "invalid drawBuffer");
5867 return;
5869 GLenum internal_format =
5870 GetBoundColorDrawBufferInternalFormat(drawbuffer);
5871 if (GLES2Util::IsIntegerFormat(internal_format)) {
5872 // To avoid undefined results, return without calling the gl function.
5873 return;
5875 attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + drawbuffer);
5876 } else {
5877 DCHECK(buffer == GL_DEPTH);
5878 if (drawbuffer != 0) {
5879 LOCAL_SET_GL_ERROR(
5880 GL_INVALID_VALUE, "glClearBufferfv", "invalid drawBuffer");
5881 return;
5883 if (!BoundFramebufferHasDepthAttachment()) {
5884 return;
5886 attachment = GL_DEPTH_ATTACHMENT;
5888 MarkDrawBufferAsCleared(buffer, drawbuffer);
5890 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get(),
5891 attachment);
5892 glClearBufferfv(buffer, drawbuffer, value);
5896 void GLES2DecoderImpl::DoClearBufferfi(
5897 GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
5898 if (!CheckBoundDrawFramebufferValid("glClearBufferfi"))
5899 return;
5900 ApplyDirtyState();
5902 switch (buffer) {
5903 case GL_DEPTH_STENCIL:
5904 break;
5905 default:
5906 LOCAL_SET_GL_ERROR(
5907 GL_INVALID_ENUM, "glClearBufferfi", "invalid buffer");
5908 return;
5910 if (drawbuffer != 0) {
5911 LOCAL_SET_GL_ERROR(
5912 GL_INVALID_VALUE, "glClearBufferfi", "invalid drawBuffer");
5913 return;
5915 if (!BoundFramebufferHasDepthAttachment() &&
5916 !BoundFramebufferHasStencilAttachment()) {
5917 return;
5919 MarkDrawBufferAsCleared(GL_DEPTH, drawbuffer);
5920 MarkDrawBufferAsCleared(GL_STENCIL, drawbuffer);
5922 ScopedRenderTo do_render_depth(
5923 framebuffer_state_.bound_draw_framebuffer.get(),
5924 GL_DEPTH_ATTACHMENT);
5925 ScopedRenderTo do_render_stencil(
5926 framebuffer_state_.bound_draw_framebuffer.get(),
5927 GL_STENCIL_ATTACHMENT);
5928 glClearBufferfi(buffer, drawbuffer, depth, stencil);
5932 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5933 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5934 GLuint client_renderbuffer_id) {
5935 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5936 if (!framebuffer) {
5937 LOCAL_SET_GL_ERROR(
5938 GL_INVALID_OPERATION,
5939 "glFramebufferRenderbuffer", "no framebuffer bound");
5940 return;
5942 GLuint service_id = 0;
5943 Renderbuffer* renderbuffer = NULL;
5944 if (client_renderbuffer_id) {
5945 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5946 if (!renderbuffer) {
5947 LOCAL_SET_GL_ERROR(
5948 GL_INVALID_OPERATION,
5949 "glFramebufferRenderbuffer", "unknown renderbuffer");
5950 return;
5952 service_id = renderbuffer->service_id();
5954 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5955 glFramebufferRenderbufferEXT(
5956 target, attachment, renderbuffertarget, service_id);
5957 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5958 if (error == GL_NO_ERROR) {
5959 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5961 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5962 framebuffer_state_.clear_state_dirty = true;
5964 OnFboChanged();
5967 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5968 if (SetCapabilityState(cap, false)) {
5969 glDisable(cap);
5973 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5974 if (SetCapabilityState(cap, true)) {
5975 glEnable(cap);
5979 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5980 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5981 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5982 glDepthRange(znear, zfar);
5985 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5986 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5987 state_.sample_coverage_invert = (invert != 0);
5988 glSampleCoverage(state_.sample_coverage_value, invert);
5991 // Assumes framebuffer is complete.
5992 void GLES2DecoderImpl::ClearUnclearedAttachments(
5993 GLenum target, Framebuffer* framebuffer) {
5994 if (target == GL_READ_FRAMEBUFFER_EXT) {
5995 // bind this to the DRAW point, clear then bind back to READ
5996 // TODO(gman): I don't think there is any guarantee that an FBO that
5997 // is complete on the READ attachment will be complete as a DRAW
5998 // attachment.
5999 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
6000 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
6002 GLbitfield clear_bits = 0;
6003 if (framebuffer->HasUnclearedColorAttachments()) {
6004 // We should always use alpha == 0 here, because 1) some draw buffers may
6005 // have alpha and some may not; 2) we won't have the same situation as the
6006 // back buffer where alpha channel exists but is not requested.
6007 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6008 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6009 clear_bits |= GL_COLOR_BUFFER_BIT;
6010 if (feature_info_->feature_flags().ext_draw_buffers ||
6011 feature_info_->IsES3Enabled()) {
6012 framebuffer->PrepareDrawBuffersForClear();
6016 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
6017 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
6018 glClearStencil(0);
6019 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
6020 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
6021 clear_bits |= GL_STENCIL_BUFFER_BIT;
6024 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
6025 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
6026 glClearDepth(1.0f);
6027 state_.SetDeviceDepthMask(GL_TRUE);
6028 clear_bits |= GL_DEPTH_BUFFER_BIT;
6031 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6032 glClear(clear_bits);
6034 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
6035 (feature_info_->feature_flags().ext_draw_buffers ||
6036 feature_info_->IsES3Enabled())) {
6037 framebuffer->RestoreDrawBuffersAfterClear();
6040 if (feature_info_->IsES3Enabled()) {
6041 // TODO(zmo): track more state to know whether there are any integer
6042 // buffers attached to the current framebuffer.
6043 framebuffer->ClearIntegerBuffers();
6046 framebuffer_manager()->MarkAttachmentsAsCleared(
6047 framebuffer, renderbuffer_manager(), texture_manager());
6049 RestoreClearState();
6051 if (target == GL_READ_FRAMEBUFFER_EXT) {
6052 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
6053 Framebuffer* draw_framebuffer =
6054 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
6055 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
6056 GetBackbufferServiceId();
6057 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
6061 void GLES2DecoderImpl::RestoreClearState() {
6062 framebuffer_state_.clear_state_dirty = true;
6063 glClearColor(
6064 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
6065 state_.color_clear_alpha);
6066 glClearStencil(state_.stencil_clear);
6067 glClearDepth(state_.depth_clear);
6068 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
6069 state_.enable_flags.scissor_test);
6070 glScissor(state_.scissor_x, state_.scissor_y, state_.scissor_width,
6071 state_.scissor_height);
6074 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
6075 Framebuffer* framebuffer =
6076 GetFramebufferInfoForTarget(target);
6077 if (!framebuffer) {
6078 return GL_FRAMEBUFFER_COMPLETE;
6080 GLenum completeness = framebuffer->IsPossiblyComplete();
6081 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
6082 return completeness;
6084 return framebuffer->GetStatus(texture_manager(), target);
6087 void GLES2DecoderImpl::DoFramebufferTexture2D(
6088 GLenum target, GLenum attachment, GLenum textarget,
6089 GLuint client_texture_id, GLint level) {
6090 DoFramebufferTexture2DCommon(
6091 "glFramebufferTexture2D", target, attachment,
6092 textarget, client_texture_id, level, 0);
6095 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
6096 GLenum target, GLenum attachment, GLenum textarget,
6097 GLuint client_texture_id, GLint level, GLsizei samples) {
6098 DoFramebufferTexture2DCommon(
6099 "glFramebufferTexture2DMultisample", target, attachment,
6100 textarget, client_texture_id, level, samples);
6103 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
6104 const char* name, GLenum target, GLenum attachment, GLenum textarget,
6105 GLuint client_texture_id, GLint level, GLsizei samples) {
6106 if (samples > renderbuffer_manager()->max_samples()) {
6107 LOCAL_SET_GL_ERROR(
6108 GL_INVALID_VALUE,
6109 "glFramebufferTexture2DMultisample", "samples too large");
6110 return;
6112 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
6113 if (!framebuffer) {
6114 LOCAL_SET_GL_ERROR(
6115 GL_INVALID_OPERATION,
6116 name, "no framebuffer bound.");
6117 return;
6119 GLuint service_id = 0;
6120 TextureRef* texture_ref = NULL;
6121 if (client_texture_id) {
6122 texture_ref = GetTexture(client_texture_id);
6123 if (!texture_ref) {
6124 LOCAL_SET_GL_ERROR(
6125 GL_INVALID_OPERATION,
6126 name, "unknown texture_ref");
6127 return;
6129 service_id = texture_ref->service_id();
6132 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
6133 LOCAL_SET_GL_ERROR(
6134 GL_INVALID_VALUE,
6135 name, "level out of range");
6136 return;
6139 if (texture_ref)
6140 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
6142 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
6143 if (0 == samples) {
6144 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
6145 } else {
6146 if (features().use_img_for_multisampled_render_to_texture) {
6147 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
6148 service_id, level, samples);
6149 } else {
6150 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
6151 service_id, level, samples);
6154 GLenum error = LOCAL_PEEK_GL_ERROR(name);
6155 if (error == GL_NO_ERROR) {
6156 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
6157 samples);
6159 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
6160 framebuffer_state_.clear_state_dirty = true;
6163 if (texture_ref)
6164 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
6166 OnFboChanged();
6169 void GLES2DecoderImpl::DoFramebufferTextureLayer(
6170 GLenum target, GLenum attachment, GLuint client_texture_id,
6171 GLint level, GLint layer) {
6172 // TODO(zmo): Unsafe ES3 API, missing states update.
6173 GLuint service_id = 0;
6174 TextureRef* texture_ref = NULL;
6175 if (client_texture_id) {
6176 texture_ref = GetTexture(client_texture_id);
6177 if (!texture_ref) {
6178 LOCAL_SET_GL_ERROR(
6179 GL_INVALID_OPERATION,
6180 "glFramebufferTextureLayer", "unknown texture_ref");
6181 return;
6183 service_id = texture_ref->service_id();
6185 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
6188 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
6189 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
6190 const char kFunctionName[] = "glGetFramebufferAttachmentParameteriv";
6191 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
6192 if (!framebuffer) {
6193 if (!unsafe_es3_apis_enabled()) {
6194 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
6195 "no framebuffer bound");
6196 return;
6198 if (!validators_->backbuffer_attachment.IsValid(attachment)) {
6199 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
6200 "invalid attachment for backbuffer");
6201 return;
6203 switch (pname) {
6204 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
6205 *params = static_cast<GLint>(GL_FRAMEBUFFER_DEFAULT);
6206 return;
6207 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
6208 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
6209 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
6210 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
6211 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
6212 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
6213 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
6214 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
6215 // Delegate to underlying driver.
6216 break;
6217 default:
6218 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName,
6219 "invalid pname for backbuffer");
6220 return;
6222 if (GetBackbufferServiceId() != 0) { // Emulated backbuffer.
6223 switch (attachment) {
6224 case GL_BACK:
6225 attachment = GL_COLOR_ATTACHMENT0;
6226 break;
6227 case GL_DEPTH:
6228 attachment = GL_DEPTH_ATTACHMENT;
6229 break;
6230 case GL_STENCIL:
6231 attachment = GL_STENCIL_ATTACHMENT;
6232 break;
6233 default:
6234 NOTREACHED();
6235 break;
6239 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
6240 features().use_img_for_multisampled_render_to_texture) {
6241 pname = GL_TEXTURE_SAMPLES_IMG;
6243 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
6244 DCHECK(framebuffer);
6245 // If we query from the driver, it will be service ID; however, we need to
6246 // return the client ID here.
6247 const Framebuffer::Attachment* attachment_object =
6248 framebuffer->GetAttachment(attachment);
6249 *params = attachment_object ? attachment_object->object_name() : 0;
6250 return;
6253 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
6254 // We didn't perform a full error check before gl call.
6255 LOCAL_PEEK_GL_ERROR(kFunctionName);
6258 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
6259 GLenum target, GLenum pname, GLint* params) {
6260 Renderbuffer* renderbuffer =
6261 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6262 if (!renderbuffer) {
6263 LOCAL_SET_GL_ERROR(
6264 GL_INVALID_OPERATION,
6265 "glGetRenderbufferParameteriv", "no renderbuffer bound");
6266 return;
6269 EnsureRenderbufferBound();
6270 switch (pname) {
6271 case GL_RENDERBUFFER_INTERNAL_FORMAT:
6272 *params = renderbuffer->internal_format();
6273 break;
6274 case GL_RENDERBUFFER_WIDTH:
6275 *params = renderbuffer->width();
6276 break;
6277 case GL_RENDERBUFFER_HEIGHT:
6278 *params = renderbuffer->height();
6279 break;
6280 case GL_RENDERBUFFER_SAMPLES_EXT:
6281 if (features().use_img_for_multisampled_render_to_texture) {
6282 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
6283 params);
6284 } else {
6285 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
6286 params);
6288 default:
6289 glGetRenderbufferParameterivEXT(target, pname, params);
6290 break;
6294 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
6295 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
6296 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6297 GLbitfield mask, GLenum filter) {
6298 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
6300 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
6301 return;
6304 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6305 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6306 BlitFramebufferHelper(
6307 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6308 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
6309 state_.enable_flags.scissor_test);
6312 void GLES2DecoderImpl::EnsureRenderbufferBound() {
6313 if (!state_.bound_renderbuffer_valid) {
6314 state_.bound_renderbuffer_valid = true;
6315 glBindRenderbufferEXT(GL_RENDERBUFFER,
6316 state_.bound_renderbuffer.get()
6317 ? state_.bound_renderbuffer->service_id()
6318 : 0);
6322 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6323 const FeatureInfo* feature_info,
6324 GLenum target,
6325 GLsizei samples,
6326 GLenum internal_format,
6327 GLsizei width,
6328 GLsizei height) {
6329 // TODO(sievers): This could be resolved at the GL binding level, but the
6330 // binding process is currently a bit too 'brute force'.
6331 if (feature_info->gl_version_info().is_angle) {
6332 glRenderbufferStorageMultisampleANGLE(
6333 target, samples, internal_format, width, height);
6334 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
6335 glRenderbufferStorageMultisample(
6336 target, samples, internal_format, width, height);
6337 } else {
6338 glRenderbufferStorageMultisampleEXT(
6339 target, samples, internal_format, width, height);
6343 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
6344 GLint srcY0,
6345 GLint srcX1,
6346 GLint srcY1,
6347 GLint dstX0,
6348 GLint dstY0,
6349 GLint dstX1,
6350 GLint dstY1,
6351 GLbitfield mask,
6352 GLenum filter) {
6353 // TODO(sievers): This could be resolved at the GL binding level, but the
6354 // binding process is currently a bit too 'brute force'.
6355 if (feature_info_->gl_version_info().is_angle) {
6356 glBlitFramebufferANGLE(
6357 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6358 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
6359 glBlitFramebuffer(
6360 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6361 } else {
6362 glBlitFramebufferEXT(
6363 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6367 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6368 GLsizei samples,
6369 GLenum internalformat,
6370 GLsizei width,
6371 GLsizei height) {
6372 if (samples > renderbuffer_manager()->max_samples()) {
6373 LOCAL_SET_GL_ERROR(
6374 GL_INVALID_VALUE,
6375 "glRenderbufferStorageMultisample", "samples too large");
6376 return false;
6379 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6380 height > renderbuffer_manager()->max_renderbuffer_size()) {
6381 LOCAL_SET_GL_ERROR(
6382 GL_INVALID_VALUE,
6383 "glRenderbufferStorageMultisample", "dimensions too large");
6384 return false;
6387 uint32 estimated_size = 0;
6388 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6389 width, height, samples, internalformat, &estimated_size)) {
6390 LOCAL_SET_GL_ERROR(
6391 GL_OUT_OF_MEMORY,
6392 "glRenderbufferStorageMultisample", "dimensions too large");
6393 return false;
6396 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6397 LOCAL_SET_GL_ERROR(
6398 GL_OUT_OF_MEMORY,
6399 "glRenderbufferStorageMultisample", "out of memory");
6400 return false;
6403 return true;
6406 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6407 GLenum target, GLsizei samples, GLenum internalformat,
6408 GLsizei width, GLsizei height) {
6409 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6410 if (!renderbuffer) {
6411 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6412 "glRenderbufferStorageMultisampleCHROMIUM",
6413 "no renderbuffer bound");
6414 return;
6417 if (!ValidateRenderbufferStorageMultisample(
6418 samples, internalformat, width, height)) {
6419 return;
6422 EnsureRenderbufferBound();
6423 GLenum impl_format =
6424 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6425 internalformat);
6426 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6427 "glRenderbufferStorageMultisampleCHROMIUM");
6428 RenderbufferStorageMultisampleHelper(
6429 feature_info_.get(), target, samples, impl_format, width, height);
6430 GLenum error =
6431 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6432 if (error == GL_NO_ERROR) {
6433 if (workarounds().validate_multisample_buffer_allocation) {
6434 if (!VerifyMultisampleRenderbufferIntegrity(
6435 renderbuffer->service_id(), impl_format)) {
6436 LOCAL_SET_GL_ERROR(
6437 GL_OUT_OF_MEMORY,
6438 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6439 return;
6443 // TODO(gman): If renderbuffers tracked which framebuffers they were
6444 // attached to we could just mark those framebuffers as not complete.
6445 framebuffer_manager()->IncFramebufferStateChangeCount();
6446 renderbuffer_manager()->SetInfo(
6447 renderbuffer, samples, internalformat, width, height);
6451 // This is the handler for multisampled_render_to_texture extensions.
6452 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6453 GLenum target, GLsizei samples, GLenum internalformat,
6454 GLsizei width, GLsizei height) {
6455 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6456 if (!renderbuffer) {
6457 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6458 "glRenderbufferStorageMultisampleEXT",
6459 "no renderbuffer bound");
6460 return;
6463 if (!ValidateRenderbufferStorageMultisample(
6464 samples, internalformat, width, height)) {
6465 return;
6468 EnsureRenderbufferBound();
6469 GLenum impl_format =
6470 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6471 internalformat);
6472 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6473 if (features().use_img_for_multisampled_render_to_texture) {
6474 glRenderbufferStorageMultisampleIMG(
6475 target, samples, impl_format, width, height);
6476 } else {
6477 glRenderbufferStorageMultisampleEXT(
6478 target, samples, impl_format, width, height);
6480 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6481 if (error == GL_NO_ERROR) {
6482 // TODO(gman): If renderbuffers tracked which framebuffers they were
6483 // attached to we could just mark those framebuffers as not complete.
6484 framebuffer_manager()->IncFramebufferStateChangeCount();
6485 renderbuffer_manager()->SetInfo(
6486 renderbuffer, samples, internalformat, width, height);
6490 // This function validates the allocation of a multisampled renderbuffer
6491 // by clearing it to a key color, blitting the contents to a texture, and
6492 // reading back the color to ensure it matches the key.
6493 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6494 GLuint renderbuffer, GLenum format) {
6496 // Only validate color buffers.
6497 // These formats have been selected because they are very common or are known
6498 // to be used by the WebGL backbuffer. If problems are observed with other
6499 // color formats they can be added here.
6500 switch (format) {
6501 case GL_RGB:
6502 case GL_RGB8:
6503 case GL_RGBA:
6504 case GL_RGBA8:
6505 break;
6506 default:
6507 return true;
6510 GLint draw_framebuffer, read_framebuffer;
6512 // Cache framebuffer and texture bindings.
6513 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
6514 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
6516 if (!validation_texture_) {
6517 GLint bound_texture;
6518 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
6520 // Create additional resources needed for the verification.
6521 glGenTextures(1, &validation_texture_);
6522 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
6523 glGenFramebuffersEXT(1, &validation_fbo_);
6525 // Texture only needs to be 1x1.
6526 glBindTexture(GL_TEXTURE_2D, validation_texture_);
6527 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6528 // multisample will fail if the color format of the source and destination
6529 // do not match. Here, we assume that the source is GL_RGBA, and make the
6530 // destination GL_RGBA. http://crbug.com/484203
6531 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
6532 GL_UNSIGNED_BYTE, NULL);
6534 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6535 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6536 GL_TEXTURE_2D, validation_texture_, 0);
6538 glBindTexture(GL_TEXTURE_2D, bound_texture);
6541 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6542 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6543 GL_RENDERBUFFER, renderbuffer);
6545 // Cache current state and reset it to the values we require.
6546 GLboolean scissor_enabled = false;
6547 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6548 if (scissor_enabled)
6549 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6551 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6552 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6553 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6555 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6556 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6557 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6559 // Clear the buffer to the desired key color.
6560 glClear(GL_COLOR_BUFFER_BIT);
6562 // Blit from the multisample buffer to a standard texture.
6563 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6564 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6566 BlitFramebufferHelper(
6567 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6569 // Read a pixel from the buffer.
6570 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6572 unsigned char pixel[3] = {0, 0, 0};
6573 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6575 // Detach the renderbuffer.
6576 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6577 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6578 GL_RENDERBUFFER, 0);
6580 // Restore cached state.
6581 if (scissor_enabled)
6582 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6584 state_.SetDeviceColorMask(
6585 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6586 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6587 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6588 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6590 // Return true if the pixel matched the desired key color.
6591 return (pixel[0] == 0xFF &&
6592 pixel[1] == 0x00 &&
6593 pixel[2] == 0xFF);
6596 void GLES2DecoderImpl::DoRenderbufferStorage(
6597 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6598 Renderbuffer* renderbuffer =
6599 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6600 if (!renderbuffer) {
6601 LOCAL_SET_GL_ERROR(
6602 GL_INVALID_OPERATION,
6603 "glRenderbufferStorage", "no renderbuffer bound");
6604 return;
6607 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6608 height > renderbuffer_manager()->max_renderbuffer_size()) {
6609 LOCAL_SET_GL_ERROR(
6610 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6611 return;
6614 uint32 estimated_size = 0;
6615 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6616 width, height, 1, internalformat, &estimated_size)) {
6617 LOCAL_SET_GL_ERROR(
6618 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6619 return;
6622 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6623 LOCAL_SET_GL_ERROR(
6624 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6625 return;
6628 EnsureRenderbufferBound();
6629 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6630 glRenderbufferStorageEXT(
6631 target,
6632 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6633 internalformat),
6634 width,
6635 height);
6636 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6637 if (error == GL_NO_ERROR) {
6638 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6639 // we could just mark those framebuffers as not complete.
6640 framebuffer_manager()->IncFramebufferStateChangeCount();
6641 renderbuffer_manager()->SetInfo(
6642 renderbuffer, 1, internalformat, width, height);
6646 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6647 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6648 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6649 Program* program = GetProgramInfoNotShader(
6650 program_id, "glLinkProgram");
6651 if (!program) {
6652 return;
6655 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6656 if (program->Link(shader_manager(),
6657 workarounds().count_all_in_varyings_packing ?
6658 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6659 shader_cache_callback_)) {
6660 if (program == state_.current_program.get()) {
6661 if (workarounds().use_current_program_after_successful_link)
6662 glUseProgram(program->service_id());
6663 if (workarounds().clear_uniforms_before_first_program_use)
6664 program_manager()->ClearUniforms(program);
6668 // LinkProgram can be very slow. Exit command processing to allow for
6669 // context preemption and GPU watchdog checks.
6670 ExitCommandProcessingEarly();
6673 void GLES2DecoderImpl::DoReadBuffer(GLenum src) {
6674 switch (src) {
6675 case GL_NONE:
6676 case GL_BACK:
6677 break;
6678 default:
6680 GLenum upper_limit = static_cast<GLenum>(
6681 group_->max_color_attachments() + GL_COLOR_ATTACHMENT0);
6682 if (src < GL_COLOR_ATTACHMENT0 || src >= upper_limit) {
6683 LOCAL_SET_GL_ERROR(
6684 GL_INVALID_ENUM, "glReadBuffer", "invalid enum for src");
6685 return;
6688 break;
6691 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
6692 if (framebuffer) {
6693 if (src == GL_BACK) {
6694 LOCAL_SET_GL_ERROR(
6695 GL_INVALID_ENUM, "glReadBuffer",
6696 "invalid src for a named framebuffer");
6697 return;
6699 framebuffer->set_read_buffer(src);
6700 } else {
6701 if (src != GL_NONE && src != GL_BACK) {
6702 LOCAL_SET_GL_ERROR(
6703 GL_INVALID_ENUM, "glReadBuffer",
6704 "invalid src for the default framebuffer");
6705 return;
6707 back_buffer_read_buffer_ = src;
6708 if (GetBackbufferServiceId() && src == GL_BACK)
6709 src = GL_COLOR_ATTACHMENT0;
6711 glReadBuffer(src);
6714 void GLES2DecoderImpl::DoSamplerParameterfv(
6715 GLuint sampler, GLenum pname, const GLfloat* params) {
6716 DCHECK(params);
6717 glSamplerParameterf(sampler, pname, params[0]);
6720 void GLES2DecoderImpl::DoSamplerParameteriv(
6721 GLuint sampler, GLenum pname, const GLint* params) {
6722 DCHECK(params);
6723 glSamplerParameteri(sampler, pname, params[0]);
6726 void GLES2DecoderImpl::DoTexParameterf(
6727 GLenum target, GLenum pname, GLfloat param) {
6728 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6729 &state_, target);
6730 if (!texture) {
6731 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6732 return;
6735 texture_manager()->SetParameterf(
6736 "glTexParameterf", GetErrorState(), texture, pname, param);
6739 void GLES2DecoderImpl::DoTexParameteri(
6740 GLenum target, GLenum pname, GLint param) {
6741 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6742 &state_, target);
6743 if (!texture) {
6744 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6745 return;
6748 texture_manager()->SetParameteri(
6749 "glTexParameteri", GetErrorState(), texture, pname, param);
6752 void GLES2DecoderImpl::DoTexParameterfv(
6753 GLenum target, GLenum pname, const GLfloat* params) {
6754 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6755 &state_, target);
6756 if (!texture) {
6757 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6758 return;
6761 texture_manager()->SetParameterf(
6762 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6765 void GLES2DecoderImpl::DoTexParameteriv(
6766 GLenum target, GLenum pname, const GLint* params) {
6767 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6768 &state_, target);
6769 if (!texture) {
6770 LOCAL_SET_GL_ERROR(
6771 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6772 return;
6775 texture_manager()->SetParameteri(
6776 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6779 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6780 if (!state_.bound_valuebuffer.get()) {
6781 // There is no valuebuffer bound
6782 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6783 "no valuebuffer in use");
6784 return false;
6786 return true;
6789 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6790 GLenum subscription,
6791 const char* function_name) {
6792 if (!CheckCurrentValuebuffer(function_name)) {
6793 return false;
6795 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6796 // The valuebuffer is not subscribed to the target
6797 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6798 "valuebuffer is not subscribed");
6799 return false;
6801 return true;
6804 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6805 GLenum subscription,
6806 const char* function_name) {
6807 if (!CheckCurrentProgramForUniform(location, function_name)) {
6808 return false;
6810 GLint real_location = -1;
6811 GLint array_index = -1;
6812 const Program::UniformInfo* info =
6813 state_.current_program->GetUniformInfoByFakeLocation(
6814 location, &real_location, &array_index);
6815 if (!info) {
6816 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6817 return false;
6819 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6820 info->accepts_api_type) == 0) {
6821 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6822 "wrong type for subscription");
6823 return false;
6825 return true;
6828 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6829 if (!state_.current_program.get()) {
6830 // The program does not exist.
6831 LOCAL_SET_GL_ERROR(
6832 GL_INVALID_OPERATION, function_name, "no program in use");
6833 return false;
6835 if (!state_.current_program->InUse()) {
6836 LOCAL_SET_GL_ERROR(
6837 GL_INVALID_OPERATION, function_name, "program not linked");
6838 return false;
6840 return true;
6843 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6844 GLint location, const char* function_name) {
6845 if (!CheckCurrentProgram(function_name)) {
6846 return false;
6848 return location != -1;
6851 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6852 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6853 if (!framebuffer)
6854 return false;
6855 const Framebuffer::Attachment* attachment =
6856 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6857 if (!attachment)
6858 return false;
6860 DCHECK(state_.current_program.get());
6861 const Program::SamplerIndices& sampler_indices =
6862 state_.current_program->sampler_indices();
6863 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6864 const Program::UniformInfo* uniform_info =
6865 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6866 DCHECK(uniform_info);
6867 if (uniform_info->type != GL_SAMPLER_2D)
6868 continue;
6869 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6870 GLuint texture_unit_index = uniform_info->texture_units[jj];
6871 if (texture_unit_index >= state_.texture_units.size())
6872 continue;
6873 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6874 TextureRef* texture_ref =
6875 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6876 if (attachment->IsTexture(texture_ref))
6877 return true;
6880 return false;
6883 bool GLES2DecoderImpl::CheckUniformForApiType(
6884 const Program::UniformInfo* info,
6885 const char* function_name,
6886 Program::UniformApiType api_type) {
6887 DCHECK(info);
6888 if ((api_type & info->accepts_api_type) == 0) {
6889 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6890 "wrong uniform function for type");
6891 return false;
6893 return true;
6896 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6897 GLint fake_location,
6898 const char* function_name,
6899 Program::UniformApiType api_type,
6900 GLint* real_location,
6901 GLenum* type,
6902 GLsizei* count) {
6903 DCHECK(type);
6904 DCHECK(count);
6905 DCHECK(real_location);
6907 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6908 return false;
6910 GLint array_index = -1;
6911 const Program::UniformInfo* info =
6912 state_.current_program->GetUniformInfoByFakeLocation(
6913 fake_location, real_location, &array_index);
6914 if (!info) {
6915 LOCAL_SET_GL_ERROR(
6916 GL_INVALID_OPERATION, function_name, "unknown location");
6917 return false;
6919 if (!CheckUniformForApiType(info, function_name, api_type)) {
6920 return false;
6922 if (*count > 1 && !info->is_array) {
6923 LOCAL_SET_GL_ERROR(
6924 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6925 return false;
6927 *count = std::min(info->size - array_index, *count);
6928 if (*count <= 0) {
6929 return false;
6931 *type = info->type;
6932 return true;
6935 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6936 GLenum type = 0;
6937 GLsizei count = 1;
6938 GLint real_location = -1;
6939 if (!PrepForSetUniformByLocation(fake_location,
6940 "glUniform1i",
6941 Program::kUniform1i,
6942 &real_location,
6943 &type,
6944 &count)) {
6945 return;
6947 if (!state_.current_program->SetSamplers(
6948 state_.texture_units.size(), fake_location, 1, &v0)) {
6949 LOCAL_SET_GL_ERROR(
6950 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6951 return;
6953 glUniform1i(real_location, v0);
6956 void GLES2DecoderImpl::DoUniform1iv(
6957 GLint fake_location, GLsizei count, const GLint *value) {
6958 GLenum type = 0;
6959 GLint real_location = -1;
6960 if (!PrepForSetUniformByLocation(fake_location,
6961 "glUniform1iv",
6962 Program::kUniform1i,
6963 &real_location,
6964 &type,
6965 &count)) {
6966 return;
6968 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6969 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6970 if (!state_.current_program->SetSamplers(
6971 state_.texture_units.size(), fake_location, count, value)) {
6972 LOCAL_SET_GL_ERROR(
6973 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6974 return;
6977 glUniform1iv(real_location, count, value);
6980 void GLES2DecoderImpl::DoUniform1uiv(
6981 GLint fake_location, GLsizei count, const GLuint *value) {
6982 GLenum type = 0;
6983 GLint real_location = -1;
6984 if (!PrepForSetUniformByLocation(fake_location,
6985 "glUniform1uiv",
6986 Program::kUniform1ui,
6987 &real_location,
6988 &type,
6989 &count)) {
6990 return;
6992 glUniform1uiv(real_location, count, value);
6995 void GLES2DecoderImpl::DoUniform1fv(
6996 GLint fake_location, GLsizei count, const GLfloat* value) {
6997 GLenum type = 0;
6998 GLint real_location = -1;
6999 if (!PrepForSetUniformByLocation(fake_location,
7000 "glUniform1fv",
7001 Program::kUniform1f,
7002 &real_location,
7003 &type,
7004 &count)) {
7005 return;
7007 if (type == GL_BOOL) {
7008 scoped_ptr<GLint[]> temp(new GLint[count]);
7009 for (GLsizei ii = 0; ii < count; ++ii) {
7010 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
7012 DoUniform1iv(real_location, count, temp.get());
7013 } else {
7014 glUniform1fv(real_location, count, value);
7018 void GLES2DecoderImpl::DoUniform2fv(
7019 GLint fake_location, GLsizei count, const GLfloat* value) {
7020 GLenum type = 0;
7021 GLint real_location = -1;
7022 if (!PrepForSetUniformByLocation(fake_location,
7023 "glUniform2fv",
7024 Program::kUniform2f,
7025 &real_location,
7026 &type,
7027 &count)) {
7028 return;
7030 if (type == GL_BOOL_VEC2) {
7031 GLsizei num_values = count * 2;
7032 scoped_ptr<GLint[]> temp(new GLint[num_values]);
7033 for (GLsizei ii = 0; ii < num_values; ++ii) {
7034 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
7036 glUniform2iv(real_location, count, temp.get());
7037 } else {
7038 glUniform2fv(real_location, count, value);
7042 void GLES2DecoderImpl::DoUniform3fv(
7043 GLint fake_location, GLsizei count, const GLfloat* value) {
7044 GLenum type = 0;
7045 GLint real_location = -1;
7046 if (!PrepForSetUniformByLocation(fake_location,
7047 "glUniform3fv",
7048 Program::kUniform3f,
7049 &real_location,
7050 &type,
7051 &count)) {
7052 return;
7054 if (type == GL_BOOL_VEC3) {
7055 GLsizei num_values = count * 3;
7056 scoped_ptr<GLint[]> temp(new GLint[num_values]);
7057 for (GLsizei ii = 0; ii < num_values; ++ii) {
7058 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
7060 glUniform3iv(real_location, count, temp.get());
7061 } else {
7062 glUniform3fv(real_location, count, value);
7066 void GLES2DecoderImpl::DoUniform4fv(
7067 GLint fake_location, GLsizei count, const GLfloat* value) {
7068 GLenum type = 0;
7069 GLint real_location = -1;
7070 if (!PrepForSetUniformByLocation(fake_location,
7071 "glUniform4fv",
7072 Program::kUniform4f,
7073 &real_location,
7074 &type,
7075 &count)) {
7076 return;
7078 if (type == GL_BOOL_VEC4) {
7079 GLsizei num_values = count * 4;
7080 scoped_ptr<GLint[]> temp(new GLint[num_values]);
7081 for (GLsizei ii = 0; ii < num_values; ++ii) {
7082 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
7084 glUniform4iv(real_location, count, temp.get());
7085 } else {
7086 glUniform4fv(real_location, count, value);
7090 void GLES2DecoderImpl::DoUniform2iv(
7091 GLint fake_location, GLsizei count, const GLint* value) {
7092 GLenum type = 0;
7093 GLint real_location = -1;
7094 if (!PrepForSetUniformByLocation(fake_location,
7095 "glUniform2iv",
7096 Program::kUniform2i,
7097 &real_location,
7098 &type,
7099 &count)) {
7100 return;
7102 glUniform2iv(real_location, count, value);
7105 void GLES2DecoderImpl::DoUniform2uiv(
7106 GLint fake_location, GLsizei count, const GLuint* value) {
7107 GLenum type = 0;
7108 GLint real_location = -1;
7109 if (!PrepForSetUniformByLocation(fake_location,
7110 "glUniform2uiv",
7111 Program::kUniform2ui,
7112 &real_location,
7113 &type,
7114 &count)) {
7115 return;
7117 glUniform2uiv(real_location, count, value);
7120 void GLES2DecoderImpl::DoUniform3iv(
7121 GLint fake_location, GLsizei count, const GLint* value) {
7122 GLenum type = 0;
7123 GLint real_location = -1;
7124 if (!PrepForSetUniformByLocation(fake_location,
7125 "glUniform3iv",
7126 Program::kUniform3i,
7127 &real_location,
7128 &type,
7129 &count)) {
7130 return;
7132 glUniform3iv(real_location, count, value);
7135 void GLES2DecoderImpl::DoUniform3uiv(
7136 GLint fake_location, GLsizei count, const GLuint* value) {
7137 GLenum type = 0;
7138 GLint real_location = -1;
7139 if (!PrepForSetUniformByLocation(fake_location,
7140 "glUniform3uiv",
7141 Program::kUniform3ui,
7142 &real_location,
7143 &type,
7144 &count)) {
7145 return;
7147 glUniform3uiv(real_location, count, value);
7150 void GLES2DecoderImpl::DoUniform4iv(
7151 GLint fake_location, GLsizei count, const GLint* value) {
7152 GLenum type = 0;
7153 GLint real_location = -1;
7154 if (!PrepForSetUniformByLocation(fake_location,
7155 "glUniform4iv",
7156 Program::kUniform4i,
7157 &real_location,
7158 &type,
7159 &count)) {
7160 return;
7162 glUniform4iv(real_location, count, value);
7165 void GLES2DecoderImpl::DoUniform4uiv(
7166 GLint fake_location, GLsizei count, const GLuint* value) {
7167 GLenum type = 0;
7168 GLint real_location = -1;
7169 if (!PrepForSetUniformByLocation(fake_location,
7170 "glUniform4uiv",
7171 Program::kUniform4ui,
7172 &real_location,
7173 &type,
7174 &count)) {
7175 return;
7177 glUniform4uiv(real_location, count, value);
7180 void GLES2DecoderImpl::DoUniformMatrix2fv(
7181 GLint fake_location, GLsizei count, GLboolean transpose,
7182 const GLfloat* value) {
7183 GLenum type = 0;
7184 GLint real_location = -1;
7185 if (!PrepForSetUniformByLocation(fake_location,
7186 "glUniformMatrix2fv",
7187 Program::kUniformMatrix2f,
7188 &real_location,
7189 &type,
7190 &count)) {
7191 return;
7193 glUniformMatrix2fv(real_location, count, transpose, value);
7196 void GLES2DecoderImpl::DoUniformMatrix3fv(
7197 GLint fake_location, GLsizei count, GLboolean transpose,
7198 const GLfloat* value) {
7199 GLenum type = 0;
7200 GLint real_location = -1;
7201 if (!PrepForSetUniformByLocation(fake_location,
7202 "glUniformMatrix3fv",
7203 Program::kUniformMatrix3f,
7204 &real_location,
7205 &type,
7206 &count)) {
7207 return;
7209 glUniformMatrix3fv(real_location, count, transpose, value);
7212 void GLES2DecoderImpl::DoUniformMatrix4fv(
7213 GLint fake_location, GLsizei count, GLboolean transpose,
7214 const GLfloat* value) {
7215 GLenum type = 0;
7216 GLint real_location = -1;
7217 if (!PrepForSetUniformByLocation(fake_location,
7218 "glUniformMatrix4fv",
7219 Program::kUniformMatrix4f,
7220 &real_location,
7221 &type,
7222 &count)) {
7223 return;
7225 glUniformMatrix4fv(real_location, count, transpose, value);
7228 void GLES2DecoderImpl::DoUniformMatrix2x3fv(
7229 GLint fake_location, GLsizei count, GLboolean transpose,
7230 const GLfloat* value) {
7231 GLenum type = 0;
7232 GLint real_location = -1;
7233 if (!PrepForSetUniformByLocation(fake_location,
7234 "glUniformMatrix2x3fv",
7235 Program::kUniformMatrix2x3f,
7236 &real_location,
7237 &type,
7238 &count)) {
7239 return;
7241 glUniformMatrix2x3fv(real_location, count, transpose, value);
7244 void GLES2DecoderImpl::DoUniformMatrix2x4fv(
7245 GLint fake_location, GLsizei count, GLboolean transpose,
7246 const GLfloat* value) {
7247 GLenum type = 0;
7248 GLint real_location = -1;
7249 if (!PrepForSetUniformByLocation(fake_location,
7250 "glUniformMatrix2x4fv",
7251 Program::kUniformMatrix2x4f,
7252 &real_location,
7253 &type,
7254 &count)) {
7255 return;
7257 glUniformMatrix2x4fv(real_location, count, transpose, value);
7260 void GLES2DecoderImpl::DoUniformMatrix3x2fv(
7261 GLint fake_location, GLsizei count, GLboolean transpose,
7262 const GLfloat* value) {
7263 GLenum type = 0;
7264 GLint real_location = -1;
7265 if (!PrepForSetUniformByLocation(fake_location,
7266 "glUniformMatrix3x2fv",
7267 Program::kUniformMatrix3x2f,
7268 &real_location,
7269 &type,
7270 &count)) {
7271 return;
7273 glUniformMatrix3x2fv(real_location, count, transpose, value);
7276 void GLES2DecoderImpl::DoUniformMatrix3x4fv(
7277 GLint fake_location, GLsizei count, GLboolean transpose,
7278 const GLfloat* value) {
7279 GLenum type = 0;
7280 GLint real_location = -1;
7281 if (!PrepForSetUniformByLocation(fake_location,
7282 "glUniformMatrix3x4fv",
7283 Program::kUniformMatrix3x4f,
7284 &real_location,
7285 &type,
7286 &count)) {
7287 return;
7289 glUniformMatrix3x4fv(real_location, count, transpose, value);
7292 void GLES2DecoderImpl::DoUniformMatrix4x2fv(
7293 GLint fake_location, GLsizei count, GLboolean transpose,
7294 const GLfloat* value) {
7295 GLenum type = 0;
7296 GLint real_location = -1;
7297 if (!PrepForSetUniformByLocation(fake_location,
7298 "glUniformMatrix4x2fv",
7299 Program::kUniformMatrix4x2f,
7300 &real_location,
7301 &type,
7302 &count)) {
7303 return;
7305 glUniformMatrix4x2fv(real_location, count, transpose, value);
7308 void GLES2DecoderImpl::DoUniformMatrix4x3fv(
7309 GLint fake_location, GLsizei count, GLboolean transpose,
7310 const GLfloat* value) {
7311 GLenum type = 0;
7312 GLint real_location = -1;
7313 if (!PrepForSetUniformByLocation(fake_location,
7314 "glUniformMatrix4x3fv",
7315 Program::kUniformMatrix4x3f,
7316 &real_location,
7317 &type,
7318 &count)) {
7319 return;
7321 glUniformMatrix4x3fv(real_location, count, transpose, value);
7324 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
7325 GLuint service_id = 0;
7326 Program* program = NULL;
7327 if (program_id) {
7328 program = GetProgramInfoNotShader(program_id, "glUseProgram");
7329 if (!program) {
7330 return;
7332 if (!program->IsValid()) {
7333 // Program was not linked successfully. (ie, glLinkProgram)
7334 LOCAL_SET_GL_ERROR(
7335 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
7336 return;
7338 service_id = program->service_id();
7340 if (state_.current_program.get()) {
7341 program_manager()->UnuseProgram(shader_manager(),
7342 state_.current_program.get());
7344 state_.current_program = program;
7345 LogClientServiceMapping("glUseProgram", program_id, service_id);
7346 glUseProgram(service_id);
7347 if (state_.current_program.get()) {
7348 program_manager()->UseProgram(state_.current_program.get());
7349 if (workarounds().clear_uniforms_before_first_program_use)
7350 program_manager()->ClearUniforms(program);
7354 void GLES2DecoderImpl::RenderWarning(
7355 const char* filename, int line, const std::string& msg) {
7356 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
7359 void GLES2DecoderImpl::PerformanceWarning(
7360 const char* filename, int line, const std::string& msg) {
7361 logger_.LogMessage(filename, line,
7362 std::string("PERFORMANCE WARNING: ") + msg);
7365 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
7366 Texture* texture, GLenum textarget) {
7367 // Image is already in use if texture is attached to a framebuffer.
7368 if (texture && !texture->IsAttachedToFramebuffer()) {
7369 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
7370 if (image) {
7371 ScopedGLErrorSuppressor suppressor(
7372 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
7373 GetErrorState());
7374 glBindTexture(textarget, texture->service_id());
7375 image->WillUseTexImage();
7376 RestoreCurrentTextureBindings(&state_, textarget);
7381 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
7382 Texture* texture, GLenum textarget) {
7383 // Image is still in use if texture is attached to a framebuffer.
7384 if (texture && !texture->IsAttachedToFramebuffer()) {
7385 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
7386 if (image) {
7387 ScopedGLErrorSuppressor suppressor(
7388 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
7389 GetErrorState());
7390 glBindTexture(textarget, texture->service_id());
7391 image->DidUseTexImage();
7392 RestoreCurrentTextureBindings(&state_, textarget);
7397 bool GLES2DecoderImpl::PrepareTexturesForRender() {
7398 DCHECK(state_.current_program.get());
7399 if (!texture_manager()->HaveUnrenderableTextures() &&
7400 !texture_manager()->HaveImages()) {
7401 return true;
7403 bool textures_set = false;
7404 const Program::SamplerIndices& sampler_indices =
7405 state_.current_program->sampler_indices();
7406 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7407 const Program::UniformInfo* uniform_info =
7408 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7409 DCHECK(uniform_info);
7410 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7411 GLuint texture_unit_index = uniform_info->texture_units[jj];
7412 if (texture_unit_index < state_.texture_units.size()) {
7413 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7414 TextureRef* texture_ref =
7415 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7416 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
7417 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
7418 textures_set = true;
7419 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7420 glBindTexture(
7421 textarget,
7422 texture_manager()->black_texture_id(uniform_info->type));
7423 if (!texture_ref) {
7424 LOCAL_RENDER_WARNING(
7425 std::string("there is no texture bound to the unit ") +
7426 base::UintToString(texture_unit_index));
7427 } else {
7428 LOCAL_RENDER_WARNING(
7429 std::string("texture bound to texture unit ") +
7430 base::UintToString(texture_unit_index) +
7431 " is not renderable. It maybe non-power-of-2 and have"
7432 " incompatible texture filtering.");
7434 continue;
7437 if (textarget != GL_TEXTURE_CUBE_MAP) {
7438 Texture* texture = texture_ref->texture();
7439 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
7440 if (image && !texture->IsAttachedToFramebuffer()) {
7441 ScopedGLErrorSuppressor suppressor(
7442 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
7443 textures_set = true;
7444 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7445 image->WillUseTexImage();
7446 continue;
7450 // else: should this be an error?
7453 return !textures_set;
7456 void GLES2DecoderImpl::RestoreStateForTextures() {
7457 DCHECK(state_.current_program.get());
7458 const Program::SamplerIndices& sampler_indices =
7459 state_.current_program->sampler_indices();
7460 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7461 const Program::UniformInfo* uniform_info =
7462 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7463 DCHECK(uniform_info);
7464 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7465 GLuint texture_unit_index = uniform_info->texture_units[jj];
7466 if (texture_unit_index < state_.texture_units.size()) {
7467 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7468 TextureRef* texture_ref =
7469 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7470 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
7471 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7472 // Get the texture_ref info that was previously bound here.
7473 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
7474 ? texture_unit.bound_texture_2d.get()
7475 : texture_unit.bound_texture_cube_map.get();
7476 glBindTexture(texture_unit.bind_target,
7477 texture_ref ? texture_ref->service_id() : 0);
7478 continue;
7481 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
7482 Texture* texture = texture_ref->texture();
7483 gfx::GLImage* image =
7484 texture->GetLevelImage(texture_unit.bind_target, 0);
7485 if (image && !texture->IsAttachedToFramebuffer()) {
7486 ScopedGLErrorSuppressor suppressor(
7487 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7488 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7489 image->DidUseTexImage();
7490 continue;
7496 // Set the active texture back to whatever the user had it as.
7497 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
7500 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7501 // Only check if there are some uncleared textures.
7502 if (!texture_manager()->HaveUnsafeTextures()) {
7503 return true;
7506 // 1: Check all textures we are about to render with.
7507 if (state_.current_program.get()) {
7508 const Program::SamplerIndices& sampler_indices =
7509 state_.current_program->sampler_indices();
7510 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7511 const Program::UniformInfo* uniform_info =
7512 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7513 DCHECK(uniform_info);
7514 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7515 GLuint texture_unit_index = uniform_info->texture_units[jj];
7516 if (texture_unit_index < state_.texture_units.size()) {
7517 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7518 TextureRef* texture_ref =
7519 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7520 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
7521 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
7522 return false;
7529 return true;
7532 bool GLES2DecoderImpl::IsDrawValid(
7533 const char* function_name, GLuint max_vertex_accessed, bool instanced,
7534 GLsizei primcount) {
7535 DCHECK(instanced || primcount == 1);
7537 // NOTE: We specifically do not check current_program->IsValid() because
7538 // it could never be invalid since glUseProgram would have failed. While
7539 // glLinkProgram could later mark the program as invalid the previous
7540 // valid program will still function if it is still the current program.
7541 if (!state_.current_program.get()) {
7542 // The program does not exist.
7543 // But GL says no ERROR.
7544 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7545 return false;
7548 if (CheckDrawingFeedbackLoops()) {
7549 LOCAL_SET_GL_ERROR(
7550 GL_INVALID_OPERATION, function_name,
7551 "Source and destination textures of the draw are the same.");
7552 return false;
7555 return state_.vertex_attrib_manager
7556 ->ValidateBindings(function_name,
7557 this,
7558 feature_info_.get(),
7559 state_.current_program.get(),
7560 max_vertex_accessed,
7561 instanced,
7562 primcount);
7565 bool GLES2DecoderImpl::SimulateAttrib0(
7566 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
7567 DCHECK(simulated);
7568 *simulated = false;
7570 if (feature_info_->gl_version_info().BehavesLikeGLES())
7571 return true;
7573 const VertexAttrib* attrib =
7574 state_.vertex_attrib_manager->GetVertexAttrib(0);
7575 // If it's enabled or it's not used then we don't need to do anything.
7576 bool attrib_0_used =
7577 state_.current_program->GetAttribInfoByLocation(0) != NULL;
7578 if (attrib->enabled() && attrib_0_used) {
7579 return true;
7582 // Make a buffer with a single repeated vec4 value enough to
7583 // simulate the constant value that is supposed to be here.
7584 // This is required to emulate GLES2 on GL.
7585 GLuint num_vertices = max_vertex_accessed + 1;
7586 uint32 size_needed = 0;
7588 if (num_vertices == 0 ||
7589 !SafeMultiplyUint32(num_vertices, sizeof(Vec4f), &size_needed) ||
7590 size_needed > 0x7FFFFFFFU) {
7591 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7592 return false;
7595 LOCAL_PERFORMANCE_WARNING(
7596 "Attribute 0 is disabled. This has signficant performance penalty");
7598 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7599 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
7601 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
7602 if (new_buffer) {
7603 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7604 GLenum error = glGetError();
7605 if (error != GL_NO_ERROR) {
7606 LOCAL_SET_GL_ERROR(
7607 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7608 return false;
7612 const Vec4& value = state_.attrib_values[0];
7613 if (new_buffer ||
7614 (attrib_0_used &&
7615 (!attrib_0_buffer_matches_value_ || !value.Equal(attrib_0_value_)))){
7616 // TODO(zmo): This is not 100% correct because we might lose data when
7617 // casting to float type, but it is a corner case and once we migrate to
7618 // core profiles on desktop GL, it is no longer relevant.
7619 Vec4f fvalue(value);
7620 std::vector<Vec4f> temp(num_vertices, fvalue);
7621 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
7622 attrib_0_buffer_matches_value_ = true;
7623 attrib_0_value_ = value;
7624 attrib_0_size_ = size_needed;
7627 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
7629 if (attrib->divisor())
7630 glVertexAttribDivisorANGLE(0, 0);
7632 *simulated = true;
7633 return true;
7636 void GLES2DecoderImpl::RestoreStateForAttrib(
7637 GLuint attrib_index, bool restore_array_binding) {
7638 const VertexAttrib* attrib =
7639 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
7640 if (restore_array_binding) {
7641 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
7642 Buffer* buffer = attrib->buffer();
7643 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
7644 glVertexAttribPointer(
7645 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
7646 attrib->gl_stride(), ptr);
7648 if (attrib->divisor())
7649 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
7650 glBindBuffer(
7651 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
7652 state_.bound_array_buffer->service_id() : 0);
7654 // Never touch vertex attribute 0's state (in particular, never
7655 // disable it) when running on desktop GL because it will never be
7656 // re-enabled.
7657 if (attrib_index != 0 ||
7658 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
7659 if (attrib->enabled()) {
7660 glEnableVertexAttribArray(attrib_index);
7661 } else {
7662 glDisableVertexAttribArray(attrib_index);
7667 bool GLES2DecoderImpl::SimulateFixedAttribs(
7668 const char* function_name,
7669 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
7670 DCHECK(simulated);
7671 *simulated = false;
7672 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
7673 return true;
7675 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
7676 return true;
7679 LOCAL_PERFORMANCE_WARNING(
7680 "GL_FIXED attributes have a signficant performance penalty");
7682 // NOTE: we could be smart and try to check if a buffer is used
7683 // twice in 2 different attribs, find the overlapping parts and therefore
7684 // duplicate the minimum amount of data but this whole code path is not meant
7685 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7686 // tests so we just add to the buffer attrib used.
7688 GLuint elements_needed = 0;
7689 const VertexAttribManager::VertexAttribList& enabled_attribs =
7690 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
7691 for (VertexAttribManager::VertexAttribList::const_iterator it =
7692 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7693 const VertexAttrib* attrib = *it;
7694 const Program::VertexAttrib* attrib_info =
7695 state_.current_program->GetAttribInfoByLocation(attrib->index());
7696 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7697 max_vertex_accessed);
7698 GLuint num_vertices = max_accessed + 1;
7699 if (num_vertices == 0) {
7700 LOCAL_SET_GL_ERROR(
7701 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7702 return false;
7704 if (attrib_info &&
7705 attrib->CanAccess(max_accessed) &&
7706 attrib->type() == GL_FIXED) {
7707 uint32 elements_used = 0;
7708 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
7709 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
7710 LOCAL_SET_GL_ERROR(
7711 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7712 return false;
7717 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
7718 uint32 size_needed = 0;
7719 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
7720 size_needed > 0x7FFFFFFFU) {
7721 LOCAL_SET_GL_ERROR(
7722 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7723 return false;
7726 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7728 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
7729 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
7730 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7731 GLenum error = glGetError();
7732 if (error != GL_NO_ERROR) {
7733 LOCAL_SET_GL_ERROR(
7734 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7735 return false;
7739 // Copy the elements and convert to float
7740 GLintptr offset = 0;
7741 for (VertexAttribManager::VertexAttribList::const_iterator it =
7742 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7743 const VertexAttrib* attrib = *it;
7744 const Program::VertexAttrib* attrib_info =
7745 state_.current_program->GetAttribInfoByLocation(attrib->index());
7746 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7747 max_vertex_accessed);
7748 GLuint num_vertices = max_accessed + 1;
7749 if (num_vertices == 0) {
7750 LOCAL_SET_GL_ERROR(
7751 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7752 return false;
7754 if (attrib_info &&
7755 attrib->CanAccess(max_accessed) &&
7756 attrib->type() == GL_FIXED) {
7757 int num_elements = attrib->size() * num_vertices;
7758 const int src_size = num_elements * sizeof(int32);
7759 const int dst_size = num_elements * sizeof(float);
7760 scoped_ptr<float[]> data(new float[num_elements]);
7761 const int32* src = reinterpret_cast<const int32 *>(
7762 attrib->buffer()->GetRange(attrib->offset(), src_size));
7763 const int32* end = src + num_elements;
7764 float* dst = data.get();
7765 while (src != end) {
7766 *dst++ = static_cast<float>(*src++) / 65536.0f;
7768 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7769 glVertexAttribPointer(
7770 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7771 reinterpret_cast<GLvoid*>(offset));
7772 offset += dst_size;
7775 *simulated = true;
7776 return true;
7779 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7780 // There's no need to call glVertexAttribPointer because we shadow all the
7781 // settings and passing GL_FIXED to it will not work.
7782 glBindBuffer(
7783 GL_ARRAY_BUFFER,
7784 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7785 : 0);
7788 error::Error GLES2DecoderImpl::DoDrawArrays(
7789 const char* function_name,
7790 bool instanced,
7791 GLenum mode,
7792 GLint first,
7793 GLsizei count,
7794 GLsizei primcount) {
7795 error::Error error = WillAccessBoundFramebufferForDraw();
7796 if (error != error::kNoError)
7797 return error;
7798 if (!validators_->draw_mode.IsValid(mode)) {
7799 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7800 return error::kNoError;
7802 if (count < 0) {
7803 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7804 return error::kNoError;
7806 if (primcount < 0) {
7807 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7808 return error::kNoError;
7810 if (!CheckBoundFramebuffersValid(function_name)) {
7811 return error::kNoError;
7813 // We have to check this here because the prototype for glDrawArrays
7814 // is GLint not GLsizei.
7815 if (first < 0) {
7816 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7817 return error::kNoError;
7820 if (count == 0 || primcount == 0) {
7821 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7822 return error::kNoError;
7825 GLuint max_vertex_accessed = first + count - 1;
7826 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7827 if (!ClearUnclearedTextures()) {
7828 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7829 return error::kNoError;
7831 bool simulated_attrib_0 = false;
7832 if (!SimulateAttrib0(
7833 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7834 return error::kNoError;
7836 bool simulated_fixed_attribs = false;
7837 if (SimulateFixedAttribs(
7838 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7839 primcount)) {
7840 bool textures_set = !PrepareTexturesForRender();
7841 ApplyDirtyState();
7842 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7843 if (!instanced) {
7844 glDrawArrays(mode, first, count);
7845 } else {
7846 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7848 if (textures_set) {
7849 RestoreStateForTextures();
7851 if (simulated_fixed_attribs) {
7852 RestoreStateForSimulatedFixedAttribs();
7855 if (simulated_attrib_0) {
7856 // We don't have to restore attrib 0 generic data at the end of this
7857 // function even if it is simulated. This is because we will simulate
7858 // it in each draw call, and attrib 0 generic data queries use cached
7859 // values instead of passing down to the underlying driver.
7860 RestoreStateForAttrib(0, false);
7863 return error::kNoError;
7866 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7867 const void* cmd_data) {
7868 // TODO(zmo): crbug.com/481184
7869 // On Desktop GL with versions lower than 4.3, we need to emulate
7870 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7871 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7872 return DoDrawArrays("glDrawArrays",
7873 false,
7874 static_cast<GLenum>(c.mode),
7875 static_cast<GLint>(c.first),
7876 static_cast<GLsizei>(c.count),
7880 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7881 uint32 immediate_data_size,
7882 const void* cmd_data) {
7883 const gles2::cmds::DrawArraysInstancedANGLE& c =
7884 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7885 if (!features().angle_instanced_arrays) {
7886 LOCAL_SET_GL_ERROR(
7887 GL_INVALID_OPERATION,
7888 "glDrawArraysInstancedANGLE", "function not available");
7889 return error::kNoError;
7891 return DoDrawArrays("glDrawArraysIntancedANGLE",
7892 true,
7893 static_cast<GLenum>(c.mode),
7894 static_cast<GLint>(c.first),
7895 static_cast<GLsizei>(c.count),
7896 static_cast<GLsizei>(c.primcount));
7899 error::Error GLES2DecoderImpl::DoDrawElements(
7900 const char* function_name,
7901 bool instanced,
7902 GLenum mode,
7903 GLsizei count,
7904 GLenum type,
7905 int32 offset,
7906 GLsizei primcount) {
7907 error::Error error = WillAccessBoundFramebufferForDraw();
7908 if (error != error::kNoError)
7909 return error;
7910 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7911 LOCAL_SET_GL_ERROR(
7912 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7913 return error::kNoError;
7916 if (count < 0) {
7917 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7918 return error::kNoError;
7920 if (offset < 0) {
7921 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7922 return error::kNoError;
7924 if (!validators_->draw_mode.IsValid(mode)) {
7925 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7926 return error::kNoError;
7928 if (!validators_->index_type.IsValid(type)) {
7929 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7930 return error::kNoError;
7932 if (primcount < 0) {
7933 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7934 return error::kNoError;
7937 if (!CheckBoundFramebuffersValid(function_name)) {
7938 return error::kNoError;
7941 if (count == 0 || primcount == 0) {
7942 return error::kNoError;
7945 GLuint max_vertex_accessed;
7946 Buffer* element_array_buffer =
7947 state_.vertex_attrib_manager->element_array_buffer();
7949 if (!element_array_buffer->GetMaxValueForRange(
7950 offset, count, type, &max_vertex_accessed)) {
7951 LOCAL_SET_GL_ERROR(
7952 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7953 return error::kNoError;
7956 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7957 if (!ClearUnclearedTextures()) {
7958 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7959 return error::kNoError;
7961 bool simulated_attrib_0 = false;
7962 if (!SimulateAttrib0(
7963 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7964 return error::kNoError;
7966 bool simulated_fixed_attribs = false;
7967 if (SimulateFixedAttribs(
7968 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7969 primcount)) {
7970 bool textures_set = !PrepareTexturesForRender();
7971 ApplyDirtyState();
7972 // TODO(gman): Refactor to hide these details in BufferManager or
7973 // VertexAttribManager.
7974 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7975 bool used_client_side_array = false;
7976 if (element_array_buffer->IsClientSideArray()) {
7977 used_client_side_array = true;
7978 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7979 indices = element_array_buffer->GetRange(offset, 0);
7982 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7983 if (!instanced) {
7984 glDrawElements(mode, count, type, indices);
7985 } else {
7986 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7989 if (used_client_side_array) {
7990 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7991 element_array_buffer->service_id());
7994 if (textures_set) {
7995 RestoreStateForTextures();
7997 if (simulated_fixed_attribs) {
7998 RestoreStateForSimulatedFixedAttribs();
8001 if (simulated_attrib_0) {
8002 // We don't have to restore attrib 0 generic data at the end of this
8003 // function even if it is simulated. This is because we will simulate
8004 // it in each draw call, and attrib 0 generic data queries use cached
8005 // values instead of passing down to the underlying driver.
8006 RestoreStateForAttrib(0, false);
8009 return error::kNoError;
8012 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
8013 const void* cmd_data) {
8014 // TODO(zmo): crbug.com/481184
8015 // On Desktop GL with versions lower than 4.3, we need to emulate
8016 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
8017 const gles2::cmds::DrawElements& c =
8018 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
8019 return DoDrawElements("glDrawElements",
8020 false,
8021 static_cast<GLenum>(c.mode),
8022 static_cast<GLsizei>(c.count),
8023 static_cast<GLenum>(c.type),
8024 static_cast<int32>(c.index_offset),
8028 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
8029 uint32 immediate_data_size,
8030 const void* cmd_data) {
8031 const gles2::cmds::DrawElementsInstancedANGLE& c =
8032 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
8033 if (!features().angle_instanced_arrays) {
8034 LOCAL_SET_GL_ERROR(
8035 GL_INVALID_OPERATION,
8036 "glDrawElementsInstancedANGLE", "function not available");
8037 return error::kNoError;
8039 return DoDrawElements("glDrawElementsInstancedANGLE",
8040 true,
8041 static_cast<GLenum>(c.mode),
8042 static_cast<GLsizei>(c.count),
8043 static_cast<GLenum>(c.type),
8044 static_cast<int32>(c.index_offset),
8045 static_cast<GLsizei>(c.primcount));
8048 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
8049 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
8050 GLuint max_vertex_accessed = 0;
8051 Buffer* buffer = GetBuffer(buffer_id);
8052 if (!buffer) {
8053 // TODO(gman): Should this be a GL error or a command buffer error?
8054 LOCAL_SET_GL_ERROR(
8055 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
8056 } else {
8057 if (!buffer->GetMaxValueForRange(
8058 offset, count, type, &max_vertex_accessed)) {
8059 // TODO(gman): Should this be a GL error or a command buffer error?
8060 LOCAL_SET_GL_ERROR(
8061 GL_INVALID_OPERATION,
8062 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
8065 return max_vertex_accessed;
8068 void GLES2DecoderImpl::DoShaderSource(
8069 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
8070 std::string str;
8071 for (GLsizei ii = 0; ii < count; ++ii) {
8072 if (length && length[ii] > 0)
8073 str.append(data[ii], length[ii]);
8074 else
8075 str.append(data[ii]);
8077 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
8078 if (!shader) {
8079 return;
8081 // Note: We don't actually call glShaderSource here. We wait until
8082 // we actually compile the shader.
8083 shader->set_source(str);
8086 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
8087 GLuint client_program_id, GLsizei count, const char* const* varyings,
8088 GLenum buffer_mode) {
8089 Program* program = GetProgramInfoNotShader(
8090 client_program_id, "glTransformFeedbackVaryings");
8091 if (!program) {
8092 return;
8094 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
8097 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
8098 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
8099 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
8100 if (!shader) {
8101 return;
8104 scoped_refptr<ShaderTranslatorInterface> translator;
8105 if (!feature_info_->disable_shader_translator()) {
8106 translator = shader->shader_type() == GL_VERTEX_SHADER ?
8107 vertex_translator_ : fragment_translator_;
8110 const Shader::TranslatedShaderSourceType source_type =
8111 feature_info_->feature_flags().angle_translated_shader_source ?
8112 Shader::kANGLE : Shader::kGL;
8113 shader->RequestCompile(translator, source_type);
8116 void GLES2DecoderImpl::DoGetShaderiv(
8117 GLuint shader_id, GLenum pname, GLint* params) {
8118 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
8119 if (!shader) {
8120 return;
8123 // Compile now for statuses that require it.
8124 switch (pname) {
8125 case GL_COMPILE_STATUS:
8126 case GL_INFO_LOG_LENGTH:
8127 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
8128 shader->DoCompile();
8129 break;
8131 default:
8132 break;
8135 switch (pname) {
8136 case GL_SHADER_SOURCE_LENGTH:
8137 *params = shader->source().size();
8138 if (*params)
8139 ++(*params);
8140 return;
8141 case GL_COMPILE_STATUS:
8142 *params = compile_shader_always_succeeds_ ? true : shader->valid();
8143 return;
8144 case GL_INFO_LOG_LENGTH:
8145 *params = shader->log_info().size();
8146 if (*params)
8147 ++(*params);
8148 return;
8149 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
8150 *params = shader->translated_source().size();
8151 if (*params)
8152 ++(*params);
8153 return;
8154 default:
8155 break;
8157 glGetShaderiv(shader->service_id(), pname, params);
8160 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
8161 const void* cmd_data) {
8162 const gles2::cmds::GetShaderSource& c =
8163 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
8164 GLuint shader_id = c.shader;
8165 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8166 Bucket* bucket = CreateBucket(bucket_id);
8167 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
8168 if (!shader || shader->source().empty()) {
8169 bucket->SetSize(0);
8170 return error::kNoError;
8172 bucket->SetFromString(shader->source().c_str());
8173 return error::kNoError;
8176 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
8177 uint32 immediate_data_size,
8178 const void* cmd_data) {
8179 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
8180 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
8181 cmd_data);
8182 GLuint shader_id = c.shader;
8183 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8184 Bucket* bucket = CreateBucket(bucket_id);
8185 Shader* shader = GetShaderInfoNotProgram(
8186 shader_id, "glGetTranslatedShaderSourceANGLE");
8187 if (!shader) {
8188 bucket->SetSize(0);
8189 return error::kNoError;
8192 // Make sure translator has been utilized in compile.
8193 shader->DoCompile();
8195 bucket->SetFromString(shader->translated_source().c_str());
8196 return error::kNoError;
8199 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
8200 uint32 immediate_data_size,
8201 const void* cmd_data) {
8202 const gles2::cmds::GetProgramInfoLog& c =
8203 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
8204 GLuint program_id = c.program;
8205 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8206 Bucket* bucket = CreateBucket(bucket_id);
8207 Program* program = GetProgramInfoNotShader(
8208 program_id, "glGetProgramInfoLog");
8209 if (!program || !program->log_info()) {
8210 bucket->SetFromString("");
8211 return error::kNoError;
8213 bucket->SetFromString(program->log_info()->c_str());
8214 return error::kNoError;
8217 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
8218 uint32 immediate_data_size,
8219 const void* cmd_data) {
8220 const gles2::cmds::GetShaderInfoLog& c =
8221 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
8222 GLuint shader_id = c.shader;
8223 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8224 Bucket* bucket = CreateBucket(bucket_id);
8225 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
8226 if (!shader) {
8227 bucket->SetFromString("");
8228 return error::kNoError;
8231 // Shader must be compiled in order to get the info log.
8232 shader->DoCompile();
8234 bucket->SetFromString(shader->log_info().c_str());
8235 return error::kNoError;
8238 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
8239 return state_.GetEnabled(cap);
8242 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
8243 const Buffer* buffer = GetBuffer(client_id);
8244 return buffer && buffer->IsValid() && !buffer->IsDeleted();
8247 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
8248 const Framebuffer* framebuffer =
8249 GetFramebuffer(client_id);
8250 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
8253 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
8254 // IsProgram is true for programs as soon as they are created, until they are
8255 // deleted and no longer in use.
8256 const Program* program = GetProgram(client_id);
8257 return program != NULL && !program->IsDeleted();
8260 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
8261 const Renderbuffer* renderbuffer =
8262 GetRenderbuffer(client_id);
8263 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
8266 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
8267 // IsShader is true for shaders as soon as they are created, until they
8268 // are deleted and not attached to any programs.
8269 const Shader* shader = GetShader(client_id);
8270 return shader != NULL && !shader->IsDeleted();
8273 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
8274 const TextureRef* texture_ref = GetTexture(client_id);
8275 return texture_ref && texture_ref->texture()->IsValid();
8278 void GLES2DecoderImpl::DoAttachShader(
8279 GLuint program_client_id, GLint shader_client_id) {
8280 Program* program = GetProgramInfoNotShader(
8281 program_client_id, "glAttachShader");
8282 if (!program) {
8283 return;
8285 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
8286 if (!shader) {
8287 return;
8289 if (!program->AttachShader(shader_manager(), shader)) {
8290 LOCAL_SET_GL_ERROR(
8291 GL_INVALID_OPERATION,
8292 "glAttachShader",
8293 "can not attach more than one shader of the same type.");
8294 return;
8296 glAttachShader(program->service_id(), shader->service_id());
8299 void GLES2DecoderImpl::DoDetachShader(
8300 GLuint program_client_id, GLint shader_client_id) {
8301 Program* program = GetProgramInfoNotShader(
8302 program_client_id, "glDetachShader");
8303 if (!program) {
8304 return;
8306 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
8307 if (!shader) {
8308 return;
8310 if (!program->DetachShader(shader_manager(), shader)) {
8311 LOCAL_SET_GL_ERROR(
8312 GL_INVALID_OPERATION,
8313 "glDetachShader", "shader not attached to program");
8314 return;
8316 glDetachShader(program->service_id(), shader->service_id());
8319 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
8320 Program* program = GetProgramInfoNotShader(
8321 program_client_id, "glValidateProgram");
8322 if (!program) {
8323 return;
8325 program->Validate();
8328 void GLES2DecoderImpl::GetVertexAttribHelper(
8329 const VertexAttrib* attrib, GLenum pname, GLint* params) {
8330 switch (pname) {
8331 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
8333 Buffer* buffer = attrib->buffer();
8334 if (buffer && !buffer->IsDeleted()) {
8335 GLuint client_id;
8336 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
8337 *params = client_id;
8339 break;
8341 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
8342 *params = attrib->enabled();
8343 break;
8344 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
8345 *params = attrib->size();
8346 break;
8347 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
8348 *params = attrib->gl_stride();
8349 break;
8350 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
8351 *params = attrib->type();
8352 break;
8353 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
8354 *params = attrib->normalized();
8355 break;
8356 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
8357 *params = attrib->divisor();
8358 break;
8359 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
8360 *params = attrib->integer();
8361 break;
8362 default:
8363 NOTREACHED();
8364 break;
8368 void GLES2DecoderImpl::DoGetTexParameterfv(
8369 GLenum target, GLenum pname, GLfloat* params) {
8370 InitTextureMaxAnisotropyIfNeeded(target, pname);
8371 glGetTexParameterfv(target, pname, params);
8374 void GLES2DecoderImpl::DoGetTexParameteriv(
8375 GLenum target, GLenum pname, GLint* params) {
8376 InitTextureMaxAnisotropyIfNeeded(target, pname);
8377 glGetTexParameteriv(target, pname, params);
8380 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
8381 GLenum target, GLenum pname) {
8382 if (!workarounds().init_texture_max_anisotropy)
8383 return;
8384 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
8385 !validators_->texture_parameter.IsValid(pname)) {
8386 return;
8389 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8390 &state_, target);
8391 if (!texture_ref) {
8392 LOCAL_SET_GL_ERROR(
8393 GL_INVALID_OPERATION,
8394 "glGetTexParamter{fi}v", "unknown texture for target");
8395 return;
8397 Texture* texture = texture_ref->texture();
8398 texture->InitTextureMaxAnisotropyIfNeeded(target);
8401 template <typename T>
8402 void GLES2DecoderImpl::DoGetVertexAttribImpl(
8403 GLuint index, GLenum pname, T* params) {
8404 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
8405 if (!attrib) {
8406 LOCAL_SET_GL_ERROR(
8407 GL_INVALID_VALUE, "glGetVertexAttrib", "index out of range");
8408 return;
8410 switch (pname) {
8411 case GL_CURRENT_VERTEX_ATTRIB:
8412 state_.attrib_values[index].GetValues(params);
8413 break;
8414 default: {
8415 GLint value = 0;
8416 GetVertexAttribHelper(attrib, pname, &value);
8417 *params = static_cast<T>(value);
8418 break;
8423 void GLES2DecoderImpl::DoGetVertexAttribfv(
8424 GLuint index, GLenum pname, GLfloat* params) {
8425 DoGetVertexAttribImpl<GLfloat>(index, pname, params);
8428 void GLES2DecoderImpl::DoGetVertexAttribiv(
8429 GLuint index, GLenum pname, GLint* params) {
8430 DoGetVertexAttribImpl<GLint>(index, pname, params);
8433 void GLES2DecoderImpl::DoGetVertexAttribIiv(
8434 GLuint index, GLenum pname, GLint* params) {
8435 DoGetVertexAttribImpl<GLint>(index, pname, params);
8438 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
8439 GLuint index, GLenum pname, GLuint* params) {
8440 DoGetVertexAttribImpl<GLuint>(index, pname, params);
8443 template <typename T>
8444 bool GLES2DecoderImpl::SetVertexAttribValue(
8445 const char* function_name, GLuint index, const T* value) {
8446 if (index >= state_.attrib_values.size()) {
8447 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
8448 return false;
8450 state_.attrib_values[index].SetValues(value);
8451 return true;
8454 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
8455 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
8456 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
8457 glVertexAttrib1f(index, v0);
8461 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
8462 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
8463 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
8464 glVertexAttrib2f(index, v0, v1);
8468 void GLES2DecoderImpl::DoVertexAttrib3f(
8469 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
8470 GLfloat v[4] = { v0, v1, v2, 1.0f, };
8471 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
8472 glVertexAttrib3f(index, v0, v1, v2);
8476 void GLES2DecoderImpl::DoVertexAttrib4f(
8477 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
8478 GLfloat v[4] = { v0, v1, v2, v3, };
8479 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
8480 glVertexAttrib4f(index, v0, v1, v2, v3);
8484 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
8485 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
8486 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
8487 glVertexAttrib1fv(index, v);
8491 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
8492 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
8493 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
8494 glVertexAttrib2fv(index, v);
8498 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
8499 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
8500 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
8501 glVertexAttrib3fv(index, v);
8505 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
8506 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
8507 glVertexAttrib4fv(index, v);
8511 void GLES2DecoderImpl::DoVertexAttribI4i(
8512 GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
8513 GLint v[4] = { v0, v1, v2, v3 };
8514 if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
8515 glVertexAttribI4i(index, v0, v1, v2, v3);
8519 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
8520 if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
8521 glVertexAttribI4iv(index, v);
8525 void GLES2DecoderImpl::DoVertexAttribI4ui(
8526 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
8527 GLuint v[4] = { v0, v1, v2, v3 };
8528 if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
8529 glVertexAttribI4ui(index, v0, v1, v2, v3);
8533 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
8534 if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
8535 glVertexAttribI4uiv(index, v);
8539 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
8540 uint32 immediate_data_size,
8541 const void* cmd_data) {
8542 if (!unsafe_es3_apis_enabled())
8543 return error::kUnknownCommand;
8544 const gles2::cmds::VertexAttribIPointer& c =
8545 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
8547 if (!state_.bound_array_buffer.get() ||
8548 state_.bound_array_buffer->IsDeleted()) {
8549 if (state_.vertex_attrib_manager.get() ==
8550 state_.default_vertex_attrib_manager.get()) {
8551 LOCAL_SET_GL_ERROR(
8552 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
8553 return error::kNoError;
8554 } else if (c.offset != 0) {
8555 LOCAL_SET_GL_ERROR(
8556 GL_INVALID_VALUE,
8557 "glVertexAttribIPointer", "client side arrays are not allowed");
8558 return error::kNoError;
8562 GLuint indx = c.indx;
8563 GLint size = c.size;
8564 GLenum type = c.type;
8565 GLsizei stride = c.stride;
8566 GLsizei offset = c.offset;
8567 const void* ptr = reinterpret_cast<const void*>(offset);
8568 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
8569 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
8570 return error::kNoError;
8572 if (!validators_->vertex_attrib_size.IsValid(size)) {
8573 LOCAL_SET_GL_ERROR(
8574 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8575 return error::kNoError;
8577 if (indx >= group_->max_vertex_attribs()) {
8578 LOCAL_SET_GL_ERROR(
8579 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
8580 return error::kNoError;
8582 if (stride < 0) {
8583 LOCAL_SET_GL_ERROR(
8584 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
8585 return error::kNoError;
8587 if (stride > 255) {
8588 LOCAL_SET_GL_ERROR(
8589 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
8590 return error::kNoError;
8592 if (offset < 0) {
8593 LOCAL_SET_GL_ERROR(
8594 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
8595 return error::kNoError;
8597 GLsizei component_size =
8598 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8599 // component_size must be a power of two to use & as optimized modulo.
8600 DCHECK(GLES2Util::IsPOT(component_size));
8601 if (offset & (component_size - 1)) {
8602 LOCAL_SET_GL_ERROR(
8603 GL_INVALID_OPERATION,
8604 "glVertexAttribIPointer", "offset not valid for type");
8605 return error::kNoError;
8607 if (stride & (component_size - 1)) {
8608 LOCAL_SET_GL_ERROR(
8609 GL_INVALID_OPERATION,
8610 "glVertexAttribIPointer", "stride not valid for type");
8611 return error::kNoError;
8613 state_.vertex_attrib_manager
8614 ->SetAttribInfo(indx,
8615 state_.bound_array_buffer.get(),
8616 size,
8617 type,
8618 GL_FALSE,
8619 stride,
8620 stride != 0 ? stride : component_size * size,
8621 offset,
8622 GL_TRUE);
8623 glVertexAttribIPointer(indx, size, type, stride, ptr);
8624 return error::kNoError;
8627 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
8628 uint32 immediate_data_size,
8629 const void* cmd_data) {
8630 const gles2::cmds::VertexAttribPointer& c =
8631 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
8633 if (!state_.bound_array_buffer.get() ||
8634 state_.bound_array_buffer->IsDeleted()) {
8635 if (state_.vertex_attrib_manager.get() ==
8636 state_.default_vertex_attrib_manager.get()) {
8637 LOCAL_SET_GL_ERROR(
8638 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
8639 return error::kNoError;
8640 } else if (c.offset != 0) {
8641 LOCAL_SET_GL_ERROR(
8642 GL_INVALID_VALUE,
8643 "glVertexAttribPointer", "client side arrays are not allowed");
8644 return error::kNoError;
8648 GLuint indx = c.indx;
8649 GLint size = c.size;
8650 GLenum type = c.type;
8651 GLboolean normalized = static_cast<GLboolean>(c.normalized);
8652 GLsizei stride = c.stride;
8653 GLsizei offset = c.offset;
8654 const void* ptr = reinterpret_cast<const void*>(offset);
8655 if (!validators_->vertex_attrib_type.IsValid(type)) {
8656 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
8657 return error::kNoError;
8659 if (!validators_->vertex_attrib_size.IsValid(size)) {
8660 LOCAL_SET_GL_ERROR(
8661 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8662 return error::kNoError;
8664 if (indx >= group_->max_vertex_attribs()) {
8665 LOCAL_SET_GL_ERROR(
8666 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
8667 return error::kNoError;
8669 if (stride < 0) {
8670 LOCAL_SET_GL_ERROR(
8671 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
8672 return error::kNoError;
8674 if (stride > 255) {
8675 LOCAL_SET_GL_ERROR(
8676 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
8677 return error::kNoError;
8679 if (offset < 0) {
8680 LOCAL_SET_GL_ERROR(
8681 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
8682 return error::kNoError;
8684 GLsizei component_size =
8685 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8686 // component_size must be a power of two to use & as optimized modulo.
8687 DCHECK(GLES2Util::IsPOT(component_size));
8688 if (offset & (component_size - 1)) {
8689 LOCAL_SET_GL_ERROR(
8690 GL_INVALID_OPERATION,
8691 "glVertexAttribPointer", "offset not valid for type");
8692 return error::kNoError;
8694 if (stride & (component_size - 1)) {
8695 LOCAL_SET_GL_ERROR(
8696 GL_INVALID_OPERATION,
8697 "glVertexAttribPointer", "stride not valid for type");
8698 return error::kNoError;
8700 state_.vertex_attrib_manager
8701 ->SetAttribInfo(indx,
8702 state_.bound_array_buffer.get(),
8703 size,
8704 type,
8705 normalized,
8706 stride,
8707 stride != 0 ? stride : component_size * size,
8708 offset,
8709 GL_FALSE);
8710 // We support GL_FIXED natively on EGL/GLES2 implementations
8711 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
8712 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
8714 return error::kNoError;
8717 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
8718 GLsizei height) {
8719 state_.viewport_x = x;
8720 state_.viewport_y = y;
8721 state_.viewport_width = std::min(width, viewport_max_width_);
8722 state_.viewport_height = std::min(height, viewport_max_height_);
8723 glViewport(x, y, width, height);
8726 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8727 uint32 immediate_data_size,
8728 const void* cmd_data) {
8729 const gles2::cmds::VertexAttribDivisorANGLE& c =
8730 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
8731 if (!features().angle_instanced_arrays) {
8732 LOCAL_SET_GL_ERROR(
8733 GL_INVALID_OPERATION,
8734 "glVertexAttribDivisorANGLE", "function not available");
8735 return error::kNoError;
8737 GLuint index = c.index;
8738 GLuint divisor = c.divisor;
8739 if (index >= group_->max_vertex_attribs()) {
8740 LOCAL_SET_GL_ERROR(
8741 GL_INVALID_VALUE,
8742 "glVertexAttribDivisorANGLE", "index out of range");
8743 return error::kNoError;
8746 state_.vertex_attrib_manager->SetDivisor(
8747 index,
8748 divisor);
8749 glVertexAttribDivisorANGLE(index, divisor);
8750 return error::kNoError;
8753 template <typename pixel_data_type>
8754 static void WriteAlphaData(
8755 void* pixels, uint32 row_count, uint32 channel_count,
8756 uint32 alpha_channel_index, uint32 unpadded_row_size,
8757 uint32 padded_row_size, pixel_data_type alpha_value) {
8758 DCHECK_GT(channel_count, 0U);
8759 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8760 uint32 unpadded_row_size_in_elements =
8761 unpadded_row_size / sizeof(pixel_data_type);
8762 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8763 uint32 padded_row_size_in_elements =
8764 padded_row_size / sizeof(pixel_data_type);
8765 pixel_data_type* dst =
8766 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8767 for (uint32 yy = 0; yy < row_count; ++yy) {
8768 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8769 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8770 *d = alpha_value;
8772 dst += padded_row_size_in_elements;
8776 void GLES2DecoderImpl::FinishReadPixels(
8777 const cmds::ReadPixels& c,
8778 GLuint buffer) {
8779 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8780 GLsizei width = c.width;
8781 GLsizei height = c.height;
8782 GLenum format = c.format;
8783 GLenum type = c.type;
8784 typedef cmds::ReadPixels::Result Result;
8785 uint32 pixels_size;
8786 Result* result = NULL;
8787 if (c.result_shm_id != 0) {
8788 result = GetSharedMemoryAs<Result*>(
8789 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8790 if (!result) {
8791 if (buffer != 0) {
8792 glDeleteBuffersARB(1, &buffer);
8794 return;
8797 GLES2Util::ComputeImageDataSizes(
8798 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8799 NULL, NULL);
8800 void* pixels = GetSharedMemoryAs<void*>(
8801 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8802 if (!pixels) {
8803 if (buffer != 0) {
8804 glDeleteBuffersARB(1, &buffer);
8806 return;
8809 if (buffer != 0) {
8810 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8811 void* data;
8812 if (features().map_buffer_range) {
8813 data = glMapBufferRange(
8814 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8815 } else {
8816 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8818 if (!data) {
8819 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8820 "Unable to map memory for readback.");
8821 return;
8823 memcpy(pixels, data, pixels_size);
8824 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8825 // have to restore the state.
8826 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8827 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8828 glDeleteBuffersARB(1, &buffer);
8831 if (result != NULL) {
8832 *result = true;
8835 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8836 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8837 if ((channels_exist & 0x0008) == 0 &&
8838 workarounds().clear_alpha_in_readpixels) {
8839 // Set the alpha to 255 because some drivers are buggy in this regard.
8840 uint32 temp_size;
8842 uint32 unpadded_row_size;
8843 uint32 padded_row_size;
8844 if (!GLES2Util::ComputeImageDataSizes(
8845 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8846 &unpadded_row_size, &padded_row_size)) {
8847 return;
8850 uint32 channel_count = 0;
8851 uint32 alpha_channel = 0;
8852 switch (format) {
8853 case GL_RGBA:
8854 case GL_BGRA_EXT:
8855 channel_count = 4;
8856 alpha_channel = 3;
8857 break;
8858 case GL_ALPHA:
8859 channel_count = 1;
8860 alpha_channel = 0;
8861 break;
8864 if (channel_count > 0) {
8865 switch (type) {
8866 case GL_UNSIGNED_BYTE:
8867 WriteAlphaData<uint8>(
8868 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8869 padded_row_size, 0xFF);
8870 break;
8871 case GL_FLOAT:
8872 WriteAlphaData<float>(
8873 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8874 padded_row_size, 1.0f);
8875 break;
8876 case GL_HALF_FLOAT:
8877 WriteAlphaData<uint16>(
8878 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8879 padded_row_size, 0x3C00);
8880 break;
8886 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8887 const void* cmd_data) {
8888 const gles2::cmds::ReadPixels& c =
8889 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8890 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8891 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8892 if (fbo_error != error::kNoError)
8893 return fbo_error;
8894 GLint x = c.x;
8895 GLint y = c.y;
8896 GLsizei width = c.width;
8897 GLsizei height = c.height;
8898 GLenum format = c.format;
8899 GLenum type = c.type;
8900 GLboolean async = static_cast<GLboolean>(c.async);
8901 if (width < 0 || height < 0) {
8902 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8903 return error::kNoError;
8905 typedef cmds::ReadPixels::Result Result;
8906 uint32 pixels_size;
8907 if (!GLES2Util::ComputeImageDataSizes(
8908 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8909 NULL, NULL)) {
8910 return error::kOutOfBounds;
8912 void* pixels = GetSharedMemoryAs<void*>(
8913 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8914 if (!pixels) {
8915 return error::kOutOfBounds;
8917 Result* result = NULL;
8918 if (c.result_shm_id != 0) {
8919 result = GetSharedMemoryAs<Result*>(
8920 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8921 if (!result) {
8922 return error::kOutOfBounds;
8926 if (!validators_->read_pixel_format.IsValid(format)) {
8927 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8928 return error::kNoError;
8930 if (!validators_->read_pixel_type.IsValid(type)) {
8931 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8932 return error::kNoError;
8935 GLenum src_internal_format = GetBoundReadFrameBufferInternalFormat();
8936 if (src_internal_format == 0) {
8937 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels",
8938 "no valid read buffer source");
8939 return error::kNoError;
8941 std::vector<GLenum> accepted_formats;
8942 std::vector<GLenum> accepted_types;
8943 switch (src_internal_format) {
8944 case GL_R8UI:
8945 case GL_R16UI:
8946 case GL_R32UI:
8947 case GL_RG8UI:
8948 case GL_RG16UI:
8949 case GL_RG32UI:
8950 // All the RGB_INTEGER formats are not renderable.
8951 case GL_RGBA8UI:
8952 case GL_RGB10_A2UI:
8953 case GL_RGBA16UI:
8954 case GL_RGBA32UI:
8955 accepted_formats.push_back(GL_RGBA_INTEGER);
8956 accepted_types.push_back(GL_UNSIGNED_INT);
8957 break;
8958 case GL_R8I:
8959 case GL_R16I:
8960 case GL_R32I:
8961 case GL_RG8I:
8962 case GL_RG16I:
8963 case GL_RG32I:
8964 case GL_RGBA8I:
8965 case GL_RGBA16I:
8966 case GL_RGBA32I:
8967 accepted_formats.push_back(GL_RGBA_INTEGER);
8968 accepted_types.push_back(GL_INT);
8969 break;
8970 case GL_RGB10_A2:
8971 accepted_formats.push_back(GL_RGBA);
8972 accepted_types.push_back(GL_UNSIGNED_BYTE);
8973 // Special case with an extra supported format/type.
8974 accepted_formats.push_back(GL_RGBA);
8975 accepted_types.push_back(GL_UNSIGNED_INT_2_10_10_10_REV);
8976 break;
8977 default:
8978 accepted_formats.push_back(GL_RGBA);
8980 GLenum src_type = GetBoundReadFrameBufferTextureType();
8981 switch (src_type) {
8982 case GL_HALF_FLOAT:
8983 case GL_HALF_FLOAT_OES:
8984 case GL_FLOAT:
8985 case GL_UNSIGNED_INT_10F_11F_11F_REV:
8986 if (!feature_info_->IsES3Enabled()) {
8987 accepted_types.push_back(GL_UNSIGNED_BYTE);
8988 } else {
8989 accepted_types.push_back(GL_FLOAT);
8991 break;
8992 default:
8993 accepted_types.push_back(GL_UNSIGNED_BYTE);
8994 break;
8997 break;
8999 if (!IsWebGLContext()) {
9000 accepted_formats.push_back(GL_BGRA_EXT);
9001 accepted_types.push_back(GL_UNSIGNED_BYTE);
9003 DCHECK_EQ(accepted_formats.size(), accepted_types.size());
9004 bool format_type_acceptable = false;
9005 for (size_t ii = 0; ii < accepted_formats.size(); ++ii) {
9006 if (format == accepted_formats[ii] && type == accepted_types[ii]) {
9007 format_type_acceptable = true;
9008 break;
9011 if (!format_type_acceptable) {
9012 // format and type are acceptable enums but not guaranteed to be supported
9013 // for this framebuffer. Have to ask gl if they are valid.
9014 GLint preferred_format = 0;
9015 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
9016 GLint preferred_type = 0;
9017 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
9018 if (format == static_cast<GLenum>(preferred_format) &&
9019 type == static_cast<GLenum>(preferred_type)) {
9020 format_type_acceptable = true;
9023 if (!format_type_acceptable) {
9024 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadPixels",
9025 "format and type incompatible with the current read framebuffer");
9026 return error::kNoError;
9028 if (width == 0 || height == 0) {
9029 return error::kNoError;
9032 // Get the size of the current fbo or backbuffer.
9033 gfx::Size max_size = GetBoundReadFrameBufferSize();
9035 int32 max_x;
9036 int32 max_y;
9037 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
9038 LOCAL_SET_GL_ERROR(
9039 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
9040 return error::kNoError;
9043 if (!CheckBoundFramebuffersValid("glReadPixels")) {
9044 return error::kNoError;
9047 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
9049 ScopedResolvedFrameBufferBinder binder(this, false, true);
9051 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
9052 // The user requested an out of range area. Get the results 1 line
9053 // at a time.
9054 uint32 temp_size;
9055 uint32 unpadded_row_size;
9056 uint32 padded_row_size;
9057 if (!GLES2Util::ComputeImageDataSizes(
9058 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
9059 &unpadded_row_size, &padded_row_size)) {
9060 LOCAL_SET_GL_ERROR(
9061 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
9062 return error::kNoError;
9065 GLint dest_x_offset = std::max(-x, 0);
9066 uint32 dest_row_offset;
9067 if (!GLES2Util::ComputeImageDataSizes(
9068 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
9069 &dest_row_offset, NULL, NULL)) {
9070 LOCAL_SET_GL_ERROR(
9071 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
9072 return error::kNoError;
9075 // Copy each row into the larger dest rect.
9076 int8* dst = static_cast<int8*>(pixels);
9077 GLint read_x = std::max(0, x);
9078 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
9079 GLint read_width = read_end_x - read_x;
9080 for (GLint yy = 0; yy < height; ++yy) {
9081 GLint ry = y + yy;
9083 // Clear the row.
9084 memset(dst, 0, unpadded_row_size);
9086 // If the row is in range, copy it.
9087 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
9088 glReadPixels(
9089 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
9091 dst += padded_row_size;
9093 } else {
9094 if (async && features().use_async_readpixels) {
9095 GLuint buffer = 0;
9096 glGenBuffersARB(1, &buffer);
9097 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
9098 // For ANGLE client version 2, GL_STREAM_READ is not available.
9099 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
9100 GL_STATIC_DRAW : GL_STREAM_READ;
9101 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
9102 GLenum error = glGetError();
9103 if (error == GL_NO_ERROR) {
9104 glReadPixels(x, y, width, height, format, type, 0);
9105 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
9106 new FenceCallback()));
9107 WaitForReadPixels(base::Bind(
9108 &GLES2DecoderImpl::FinishReadPixels,
9109 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
9110 <GLES2DecoderImpl>(this),
9111 c, buffer));
9112 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
9113 return error::kNoError;
9114 } else {
9115 // On error, unbind pack buffer and fall through to sync readpixels
9116 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
9117 glDeleteBuffersARB(1, &buffer);
9120 glReadPixels(x, y, width, height, format, type, pixels);
9122 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
9123 if (error == GL_NO_ERROR) {
9124 if (result != NULL) {
9125 *result = true;
9127 FinishReadPixels(c, 0);
9130 return error::kNoError;
9133 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
9134 const void* cmd_data) {
9135 const gles2::cmds::PixelStorei& c =
9136 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
9137 GLenum pname = c.pname;
9138 GLenum param = c.param;
9139 if (!validators_->pixel_store.IsValid(pname)) {
9140 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
9141 return error::kNoError;
9143 switch (pname) {
9144 case GL_PACK_ALIGNMENT:
9145 case GL_UNPACK_ALIGNMENT:
9146 if (!validators_->pixel_store_alignment.IsValid(param)) {
9147 LOCAL_SET_GL_ERROR(
9148 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
9149 return error::kNoError;
9151 break;
9152 default:
9153 break;
9155 glPixelStorei(pname, param);
9156 switch (pname) {
9157 case GL_PACK_ALIGNMENT:
9158 state_.pack_alignment = param;
9159 break;
9160 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
9161 state_.pack_reverse_row_order = (param != 0);
9162 break;
9163 case GL_UNPACK_ALIGNMENT:
9164 state_.unpack_alignment = param;
9165 break;
9166 default:
9167 // Validation should have prevented us from getting here.
9168 NOTREACHED();
9169 break;
9171 return error::kNoError;
9174 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
9175 uint32 immediate_data_size,
9176 const void* cmd_data) {
9177 const gles2::cmds::PostSubBufferCHROMIUM& c =
9178 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
9179 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
9181 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9183 if (!supports_post_sub_buffer_) {
9184 LOCAL_SET_GL_ERROR(
9185 GL_INVALID_OPERATION,
9186 "glPostSubBufferCHROMIUM", "command not supported by surface");
9187 return error::kNoError;
9189 bool is_tracing;
9190 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9191 &is_tracing);
9192 if (is_tracing) {
9193 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9194 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9195 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9196 is_offscreen ? offscreen_size_ : surface_->GetSize());
9198 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height) !=
9199 gfx::SwapResult::SWAP_FAILED) {
9200 return error::kNoError;
9201 } else {
9202 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
9203 return error::kLostContext;
9207 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
9208 uint32 immediate_data_size,
9209 const void* cmd_data) {
9210 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
9211 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
9212 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
9213 if (!ref) {
9214 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9215 "glScheduleOverlayPlaneCHROMIUM",
9216 "unknown texture");
9217 return error::kNoError;
9219 gfx::GLImage* image =
9220 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
9221 if (!image) {
9222 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9223 "glScheduleOverlayPlaneCHROMIUM",
9224 "unsupported texture format");
9225 return error::kNoError;
9227 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
9228 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
9229 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
9230 "glScheduleOverlayPlaneCHROMIUM",
9231 "invalid transform enum");
9232 return error::kNoError;
9234 if (!surface_->ScheduleOverlayPlane(
9235 c.plane_z_order,
9236 transform,
9237 image,
9238 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
9239 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
9240 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9241 "glScheduleOverlayPlaneCHROMIUM",
9242 "failed to schedule overlay");
9244 return error::kNoError;
9247 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
9248 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
9249 const std::string& name_str) {
9250 if (!StringIsValidForGLES(name_str.c_str())) {
9251 LOCAL_SET_GL_ERROR(
9252 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
9253 return error::kNoError;
9255 Program* program = GetProgramInfoNotShader(
9256 client_id, "glGetAttribLocation");
9257 if (!program) {
9258 return error::kNoError;
9260 if (!program->IsValid()) {
9261 LOCAL_SET_GL_ERROR(
9262 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
9263 return error::kNoError;
9265 GLint* location = GetSharedMemoryAs<GLint*>(
9266 location_shm_id, location_shm_offset, sizeof(GLint));
9267 if (!location) {
9268 return error::kOutOfBounds;
9270 // Require the client to init this incase the context is lost and we are no
9271 // longer executing commands.
9272 if (*location != -1) {
9273 return error::kGenericError;
9275 *location = program->GetAttribLocation(name_str);
9276 return error::kNoError;
9279 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
9280 uint32 immediate_data_size,
9281 const void* cmd_data) {
9282 const gles2::cmds::GetAttribLocation& c =
9283 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
9284 Bucket* bucket = GetBucket(c.name_bucket_id);
9285 if (!bucket) {
9286 return error::kInvalidArguments;
9288 std::string name_str;
9289 if (!bucket->GetAsString(&name_str)) {
9290 return error::kInvalidArguments;
9292 return GetAttribLocationHelper(
9293 c.program, c.location_shm_id, c.location_shm_offset, name_str);
9296 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
9297 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
9298 const std::string& name_str) {
9299 if (!StringIsValidForGLES(name_str.c_str())) {
9300 LOCAL_SET_GL_ERROR(
9301 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
9302 return error::kNoError;
9304 Program* program = GetProgramInfoNotShader(
9305 client_id, "glGetUniformLocation");
9306 if (!program) {
9307 return error::kNoError;
9309 if (!program->IsValid()) {
9310 LOCAL_SET_GL_ERROR(
9311 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
9312 return error::kNoError;
9314 GLint* location = GetSharedMemoryAs<GLint*>(
9315 location_shm_id, location_shm_offset, sizeof(GLint));
9316 if (!location) {
9317 return error::kOutOfBounds;
9319 // Require the client to init this incase the context is lost an we are no
9320 // longer executing commands.
9321 if (*location != -1) {
9322 return error::kGenericError;
9324 *location = program->GetUniformFakeLocation(name_str);
9325 return error::kNoError;
9328 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
9329 uint32 immediate_data_size,
9330 const void* cmd_data) {
9331 const gles2::cmds::GetUniformLocation& c =
9332 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
9333 Bucket* bucket = GetBucket(c.name_bucket_id);
9334 if (!bucket) {
9335 return error::kInvalidArguments;
9337 std::string name_str;
9338 if (!bucket->GetAsString(&name_str)) {
9339 return error::kInvalidArguments;
9341 return GetUniformLocationHelper(
9342 c.program, c.location_shm_id, c.location_shm_offset, name_str);
9345 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
9346 uint32 immediate_data_size,
9347 const void* cmd_data) {
9348 if (!unsafe_es3_apis_enabled())
9349 return error::kUnknownCommand;
9350 const gles2::cmds::GetUniformIndices& c =
9351 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
9352 Bucket* bucket = GetBucket(c.names_bucket_id);
9353 if (!bucket) {
9354 return error::kInvalidArguments;
9356 GLsizei count = 0;
9357 std::vector<char*> names;
9358 std::vector<GLint> len;
9359 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
9360 return error::kInvalidArguments;
9362 typedef cmds::GetUniformIndices::Result Result;
9363 Result* result = GetSharedMemoryAs<Result*>(
9364 c.indices_shm_id, c.indices_shm_offset,
9365 Result::ComputeSize(static_cast<size_t>(count)));
9366 GLuint* indices = result ? result->GetData() : NULL;
9367 if (indices == NULL) {
9368 return error::kOutOfBounds;
9370 // Check that the client initialized the result.
9371 if (result->size != 0) {
9372 return error::kInvalidArguments;
9374 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
9375 if (!program) {
9376 return error::kNoError;
9378 GLuint service_id = program->service_id();
9379 GLint link_status = GL_FALSE;
9380 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
9381 if (link_status != GL_TRUE) {
9382 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9383 "glGetUniformIndices", "program not linked");
9384 return error::kNoError;
9386 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
9387 glGetUniformIndices(service_id, count, &names[0], indices);
9388 GLenum error = glGetError();
9389 if (error == GL_NO_ERROR) {
9390 result->SetNumResults(count);
9391 } else {
9392 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
9394 return error::kNoError;
9397 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
9398 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
9399 const std::string& name_str) {
9400 GLint* location = GetSharedMemoryAs<GLint*>(
9401 location_shm_id, location_shm_offset, sizeof(GLint));
9402 if (!location) {
9403 return error::kOutOfBounds;
9405 // Require the client to init this incase the context is lost and we are no
9406 // longer executing commands.
9407 if (*location != -1) {
9408 return error::kGenericError;
9410 Program* program = GetProgramInfoNotShader(
9411 client_id, "glGetFragDataLocation");
9412 if (!program) {
9413 return error::kNoError;
9415 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
9416 return error::kNoError;
9419 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
9420 uint32 immediate_data_size,
9421 const void* cmd_data) {
9422 if (!unsafe_es3_apis_enabled())
9423 return error::kUnknownCommand;
9424 const gles2::cmds::GetFragDataLocation& c =
9425 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
9426 Bucket* bucket = GetBucket(c.name_bucket_id);
9427 if (!bucket) {
9428 return error::kInvalidArguments;
9430 std::string name_str;
9431 if (!bucket->GetAsString(&name_str)) {
9432 return error::kInvalidArguments;
9434 return GetFragDataLocationHelper(
9435 c.program, c.location_shm_id, c.location_shm_offset, name_str);
9438 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
9439 uint32 immediate_data_size, const void* cmd_data) {
9440 if (!unsafe_es3_apis_enabled())
9441 return error::kUnknownCommand;
9442 const gles2::cmds::GetUniformBlockIndex& c =
9443 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
9444 Bucket* bucket = GetBucket(c.name_bucket_id);
9445 if (!bucket) {
9446 return error::kInvalidArguments;
9448 std::string name_str;
9449 if (!bucket->GetAsString(&name_str)) {
9450 return error::kInvalidArguments;
9452 GLuint* index = GetSharedMemoryAs<GLuint*>(
9453 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
9454 if (!index) {
9455 return error::kOutOfBounds;
9457 // Require the client to init this in case the context is lost and we are no
9458 // longer executing commands.
9459 if (*index != GL_INVALID_INDEX) {
9460 return error::kGenericError;
9462 Program* program = GetProgramInfoNotShader(
9463 c.program, "glGetUniformBlockIndex");
9464 if (!program) {
9465 return error::kNoError;
9467 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
9468 return error::kNoError;
9471 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
9472 const void* cmd_data) {
9473 const gles2::cmds::GetString& c =
9474 *static_cast<const gles2::cmds::GetString*>(cmd_data);
9475 GLenum name = static_cast<GLenum>(c.name);
9476 if (!validators_->string_type.IsValid(name)) {
9477 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
9478 return error::kNoError;
9481 const char* str = nullptr;
9482 std::string extensions;
9483 switch (name) {
9484 case GL_VERSION:
9485 if (unsafe_es3_apis_enabled())
9486 str = "OpenGL ES 3.0 Chromium";
9487 else
9488 str = "OpenGL ES 2.0 Chromium";
9489 break;
9490 case GL_SHADING_LANGUAGE_VERSION:
9491 if (unsafe_es3_apis_enabled())
9492 str = "OpenGL ES GLSL ES 3.0 Chromium";
9493 else
9494 str = "OpenGL ES GLSL ES 1.0 Chromium";
9495 break;
9496 case GL_RENDERER:
9497 case GL_VENDOR:
9498 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9499 // They are used by WEBGL_debug_renderer_info.
9500 if (!IsWebGLContext())
9501 str = "Chromium";
9502 else
9503 str = reinterpret_cast<const char*>(glGetString(name));
9504 break;
9505 case GL_EXTENSIONS:
9507 // For WebGL contexts, strip out the OES derivatives and
9508 // EXT frag depth extensions if they have not been enabled.
9509 if (IsWebGLContext()) {
9510 extensions = feature_info_->extensions();
9511 if (!derivatives_explicitly_enabled_) {
9512 size_t offset = extensions.find(kOESDerivativeExtension);
9513 if (std::string::npos != offset) {
9514 extensions.replace(offset, arraysize(kOESDerivativeExtension),
9515 std::string());
9518 if (!frag_depth_explicitly_enabled_) {
9519 size_t offset = extensions.find(kEXTFragDepthExtension);
9520 if (std::string::npos != offset) {
9521 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
9522 std::string());
9525 if (!draw_buffers_explicitly_enabled_) {
9526 size_t offset = extensions.find(kEXTDrawBuffersExtension);
9527 if (std::string::npos != offset) {
9528 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
9529 std::string());
9532 if (!shader_texture_lod_explicitly_enabled_) {
9533 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
9534 if (std::string::npos != offset) {
9535 extensions.replace(offset,
9536 arraysize(kEXTShaderTextureLodExtension),
9537 std::string());
9540 } else {
9541 extensions = feature_info_->extensions().c_str();
9543 if (supports_post_sub_buffer_)
9544 extensions += " GL_CHROMIUM_post_sub_buffer";
9545 str = extensions.c_str();
9547 break;
9548 default:
9549 str = reinterpret_cast<const char*>(glGetString(name));
9550 break;
9552 Bucket* bucket = CreateBucket(c.bucket_id);
9553 bucket->SetFromString(str);
9554 return error::kNoError;
9557 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
9558 const void* cmd_data) {
9559 const gles2::cmds::BufferData& c =
9560 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
9561 GLenum target = static_cast<GLenum>(c.target);
9562 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
9563 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9564 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9565 GLenum usage = static_cast<GLenum>(c.usage);
9566 const void* data = NULL;
9567 if (data_shm_id != 0 || data_shm_offset != 0) {
9568 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
9569 if (!data) {
9570 return error::kOutOfBounds;
9573 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
9574 return error::kNoError;
9577 void GLES2DecoderImpl::DoBufferSubData(
9578 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
9579 // Just delegate it. Some validation is actually done before this.
9580 buffer_manager()->ValidateAndDoBufferSubData(
9581 &state_, target, offset, size, data);
9584 bool GLES2DecoderImpl::ClearLevel(Texture* texture,
9585 unsigned target,
9586 int level,
9587 unsigned format,
9588 unsigned type,
9589 int xoffset,
9590 int yoffset,
9591 int width,
9592 int height) {
9593 uint32 channels = GLES2Util::GetChannelsForFormat(format);
9594 if ((feature_info_->feature_flags().angle_depth_texture ||
9595 feature_info_->IsES3Enabled())
9596 && (channels & GLES2Util::kDepth) != 0) {
9597 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9598 // on depth formats.
9599 GLuint fb = 0;
9600 glGenFramebuffersEXT(1, &fb);
9601 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
9603 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
9604 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
9605 GL_DEPTH_ATTACHMENT;
9607 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
9608 texture->service_id(), level);
9609 // ANGLE promises a depth only attachment ok.
9610 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
9611 GL_FRAMEBUFFER_COMPLETE) {
9612 return false;
9614 glClearStencil(0);
9615 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
9616 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
9617 glClearDepth(1.0f);
9618 state_.SetDeviceDepthMask(GL_TRUE);
9619 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
9620 glScissor(xoffset, yoffset, width, height);
9621 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
9623 RestoreClearState();
9625 glDeleteFramebuffersEXT(1, &fb);
9626 Framebuffer* framebuffer =
9627 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
9628 GLuint fb_service_id =
9629 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
9630 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
9631 return true;
9634 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
9636 uint32 size;
9637 uint32 padded_row_size;
9638 if (!GLES2Util::ComputeImageDataSizes(
9639 width, height, 1, format, type, state_.unpack_alignment, &size,
9640 NULL, &padded_row_size)) {
9641 return false;
9644 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
9646 int tile_height;
9648 if (size > kMaxZeroSize) {
9649 if (kMaxZeroSize < padded_row_size) {
9650 // That'd be an awfully large texture.
9651 return false;
9653 // We should never have a large total size with a zero row size.
9654 DCHECK_GT(padded_row_size, 0U);
9655 tile_height = kMaxZeroSize / padded_row_size;
9656 if (!GLES2Util::ComputeImageDataSizes(
9657 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
9658 NULL, NULL)) {
9659 return false;
9661 } else {
9662 tile_height = height;
9665 // Assumes the size has already been checked.
9666 scoped_ptr<char[]> zero(new char[size]);
9667 memset(zero.get(), 0, size);
9668 glBindTexture(texture->target(), texture->service_id());
9670 GLint y = 0;
9671 while (y < height) {
9672 GLint h = y + tile_height > height ? height - y : tile_height;
9673 glTexSubImage2D(target, level, xoffset, yoffset + y, width, h, format, type,
9674 zero.get());
9675 y += tile_height;
9677 TextureRef* bound_texture =
9678 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
9679 glBindTexture(texture->target(),
9680 bound_texture ? bound_texture->service_id() : 0);
9681 return true;
9684 namespace {
9686 const int kASTCBlockSize = 16;
9687 const int kS3TCBlockWidth = 4;
9688 const int kS3TCBlockHeight = 4;
9689 const int kS3TCDXT1BlockSize = 8;
9690 const int kS3TCDXT3AndDXT5BlockSize = 16;
9691 const int kEACAndETC2BlockSize = 4;
9693 typedef struct {
9694 int blockWidth;
9695 int blockHeight;
9696 } ASTCBlockArray;
9698 const ASTCBlockArray kASTCBlockArray[] = {
9699 {4, 4}, /* GL_COMPRESSED_RGBA_ASTC_4x4_KHR */
9700 {5, 4}, /* and GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR */
9701 {5, 5},
9702 {6, 5},
9703 {6, 6},
9704 {8, 5},
9705 {8, 6},
9706 {8, 8},
9707 {10, 5},
9708 {10, 6},
9709 {10, 8},
9710 {10, 10},
9711 {12, 10},
9712 {12, 12}};
9714 bool IsValidDXTSize(GLint level, GLsizei size) {
9715 return (size == 1) ||
9716 (size == 2) || !(size % kS3TCBlockWidth);
9719 bool IsValidPVRTCSize(GLint level, GLsizei size) {
9720 return GLES2Util::IsPOT(size);
9723 } // anonymous namespace.
9725 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9726 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9727 GLenum format, GLsizei* size_in_bytes) {
9728 base::CheckedNumeric<GLsizei> bytes_required(0);
9730 switch (format) {
9731 case GL_ATC_RGB_AMD:
9732 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9733 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9734 case GL_ETC1_RGB8_OES:
9735 bytes_required =
9736 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9737 bytes_required *=
9738 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9739 bytes_required *= kS3TCDXT1BlockSize;
9740 break;
9741 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
9742 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
9743 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
9744 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
9745 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
9746 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
9747 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
9748 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
9749 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
9750 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
9751 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
9752 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
9753 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
9754 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
9755 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
9756 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
9757 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
9758 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
9759 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
9760 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
9761 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
9762 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
9763 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
9764 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
9765 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
9766 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
9767 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
9768 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: {
9769 const int index = (format < GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) ?
9770 static_cast<int>(format - GL_COMPRESSED_RGBA_ASTC_4x4_KHR) :
9771 static_cast<int>(format - GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
9773 const int kBlockWidth = kASTCBlockArray[index].blockWidth;
9774 const int kBlockHeight = kASTCBlockArray[index].blockHeight;
9776 bytes_required =
9777 (width + kBlockWidth - 1) / kBlockWidth;
9778 bytes_required *=
9779 (height + kBlockHeight - 1) / kBlockHeight;
9781 bytes_required *= kASTCBlockSize;
9782 break;
9784 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9785 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9786 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9787 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9788 bytes_required =
9789 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9790 bytes_required *=
9791 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9792 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
9793 break;
9794 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9795 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9796 bytes_required = std::max(width, 8);
9797 bytes_required *= std::max(height, 8);
9798 bytes_required *= 4;
9799 bytes_required += 7;
9800 bytes_required /= 8;
9801 break;
9802 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9803 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9804 bytes_required = std::max(width, 16);
9805 bytes_required *= std::max(height, 8);
9806 bytes_required *= 2;
9807 bytes_required += 7;
9808 bytes_required /= 8;
9809 break;
9811 // ES3 formats.
9812 case GL_COMPRESSED_R11_EAC:
9813 case GL_COMPRESSED_SIGNED_R11_EAC:
9814 case GL_COMPRESSED_RGB8_ETC2:
9815 case GL_COMPRESSED_SRGB8_ETC2:
9816 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9817 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9818 bytes_required =
9819 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9820 bytes_required *=
9821 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9822 bytes_required *= 8;
9823 bytes_required *= depth;
9824 break;
9825 case GL_COMPRESSED_RG11_EAC:
9826 case GL_COMPRESSED_SIGNED_RG11_EAC:
9827 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9828 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9829 bytes_required =
9830 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9831 bytes_required *=
9832 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9833 bytes_required *= 16;
9834 bytes_required *= depth;
9835 break;
9836 default:
9837 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
9838 return false;
9841 if (!bytes_required.IsValid()) {
9842 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid size");
9843 return false;
9846 *size_in_bytes = bytes_required.ValueOrDefault(0);
9847 return true;
9850 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9851 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9852 GLenum format, GLsizei size) {
9853 GLsizei bytes_required = 0;
9854 if (!GetCompressedTexSizeInBytes(
9855 function_name, width, height, depth, format, &bytes_required)) {
9856 return false;
9859 if (size != bytes_required) {
9860 LOCAL_SET_GL_ERROR(
9861 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
9862 return false;
9865 return true;
9868 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9869 const char* function_name, GLenum target, GLint level,
9870 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
9871 switch (format) {
9872 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9873 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9874 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9875 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9876 DCHECK_EQ(1, depth); // 2D formats.
9877 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
9878 LOCAL_SET_GL_ERROR(
9879 GL_INVALID_OPERATION, function_name,
9880 "width or height invalid for level");
9881 return false;
9883 return true;
9884 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
9885 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
9886 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
9887 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
9888 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
9889 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
9890 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
9891 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
9892 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
9893 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
9894 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
9895 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
9896 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
9897 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
9898 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
9899 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
9900 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
9901 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
9902 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
9903 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
9904 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
9905 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
9906 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
9907 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
9908 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
9909 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
9910 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
9911 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
9912 case GL_ATC_RGB_AMD:
9913 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9914 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9915 case GL_ETC1_RGB8_OES:
9916 DCHECK_EQ(1, depth); // 2D formats.
9917 if (width <= 0 || height <= 0) {
9918 LOCAL_SET_GL_ERROR(
9919 GL_INVALID_OPERATION, function_name,
9920 "width or height invalid for level");
9921 return false;
9923 return true;
9924 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9925 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9926 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9927 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9928 DCHECK_EQ(1, depth); // 2D formats.
9929 if (!IsValidPVRTCSize(level, width) ||
9930 !IsValidPVRTCSize(level, height)) {
9931 LOCAL_SET_GL_ERROR(
9932 GL_INVALID_OPERATION, function_name,
9933 "width or height invalid for level");
9934 return false;
9936 return true;
9938 // ES3 formats.
9939 case GL_COMPRESSED_R11_EAC:
9940 case GL_COMPRESSED_SIGNED_R11_EAC:
9941 case GL_COMPRESSED_RG11_EAC:
9942 case GL_COMPRESSED_SIGNED_RG11_EAC:
9943 case GL_COMPRESSED_RGB8_ETC2:
9944 case GL_COMPRESSED_SRGB8_ETC2:
9945 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9946 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9947 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9948 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9949 if (width <= 0 || height <= 0 || depth <= 0) {
9950 LOCAL_SET_GL_ERROR(
9951 GL_INVALID_OPERATION, function_name,
9952 "width, height, or depth invalid");
9953 return false;
9955 if (target == GL_TEXTURE_3D) {
9956 LOCAL_SET_GL_ERROR(
9957 GL_INVALID_OPERATION, function_name,
9958 "target invalid for format");
9959 return false;
9961 return true;
9962 default:
9963 return false;
9967 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9968 const char* function_name,
9969 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9970 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9971 Texture* texture) {
9972 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9973 LOCAL_SET_GL_ERROR(
9974 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9975 return false;
9978 switch (format) {
9979 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9980 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9981 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9982 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9983 const int kBlockWidth = 4;
9984 const int kBlockHeight = 4;
9985 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9986 LOCAL_SET_GL_ERROR(
9987 GL_INVALID_OPERATION, function_name,
9988 "xoffset or yoffset not multiple of 4");
9989 return false;
9991 GLsizei tex_width = 0;
9992 GLsizei tex_height = 0;
9993 if (!texture->GetLevelSize(target, level,
9994 &tex_width, &tex_height, nullptr) ||
9995 width - xoffset > tex_width ||
9996 height - yoffset > tex_height) {
9997 LOCAL_SET_GL_ERROR(
9998 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9999 return false;
10001 return ValidateCompressedTexDimensions(
10002 function_name, target, level, width, height, 1, format);
10004 case GL_ATC_RGB_AMD:
10005 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
10006 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
10007 LOCAL_SET_GL_ERROR(
10008 GL_INVALID_OPERATION, function_name,
10009 "not supported for ATC textures");
10010 return false;
10012 case GL_ETC1_RGB8_OES: {
10013 LOCAL_SET_GL_ERROR(
10014 GL_INVALID_OPERATION, function_name,
10015 "not supported for ECT1_RGB8_OES textures");
10016 return false;
10018 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
10019 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
10020 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
10021 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
10022 if ((xoffset != 0) || (yoffset != 0)) {
10023 LOCAL_SET_GL_ERROR(
10024 GL_INVALID_OPERATION, function_name,
10025 "xoffset and yoffset must be zero");
10026 return false;
10028 GLsizei tex_width = 0;
10029 GLsizei tex_height = 0;
10030 if (!texture->GetLevelSize(target, level,
10031 &tex_width, &tex_height, nullptr) ||
10032 width != tex_width ||
10033 height != tex_height) {
10034 LOCAL_SET_GL_ERROR(
10035 GL_INVALID_OPERATION, function_name,
10036 "dimensions must match existing texture level dimensions");
10037 return false;
10039 return ValidateCompressedTexDimensions(
10040 function_name, target, level, width, height, 1, format);
10043 // ES3 formats
10044 case GL_COMPRESSED_R11_EAC:
10045 case GL_COMPRESSED_SIGNED_R11_EAC:
10046 case GL_COMPRESSED_RG11_EAC:
10047 case GL_COMPRESSED_SIGNED_RG11_EAC:
10048 case GL_COMPRESSED_RGB8_ETC2:
10049 case GL_COMPRESSED_SRGB8_ETC2:
10050 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
10051 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
10052 case GL_COMPRESSED_RGBA8_ETC2_EAC:
10053 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
10055 const int kBlockSize = 4;
10056 GLsizei tex_width, tex_height;
10057 if (target == GL_TEXTURE_3D ||
10058 !texture->GetLevelSize(target, level,
10059 &tex_width, &tex_height, nullptr) ||
10060 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
10061 ((width % kBlockSize) && xoffset + width != tex_width) ||
10062 ((height % kBlockSize) && yoffset + height != tex_height)) {
10063 LOCAL_SET_GL_ERROR(
10064 GL_INVALID_OPERATION, function_name,
10065 "dimensions must match existing texture level dimensions");
10066 return false;
10068 return true;
10070 default:
10071 return false;
10075 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
10076 GLenum target,
10077 GLint level,
10078 GLenum internal_format,
10079 GLsizei width,
10080 GLsizei height,
10081 GLint border,
10082 GLsizei image_size,
10083 const void* data) {
10084 if (!validators_->texture_target.IsValid(target)) {
10085 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10086 "glCompressedTexImage2D", target, "target");
10087 return error::kNoError;
10089 if (!validators_->compressed_texture_format.IsValid(
10090 internal_format)) {
10091 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10092 "glCompressedTexImage2D", internal_format, "internal_format");
10093 return error::kNoError;
10095 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
10096 border != 0) {
10097 LOCAL_SET_GL_ERROR(
10098 GL_INVALID_VALUE,
10099 "glCompressedTexImage2D", "dimensions out of range");
10100 return error::kNoError;
10102 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10103 &state_, target);
10104 if (!texture_ref) {
10105 LOCAL_SET_GL_ERROR(
10106 GL_INVALID_VALUE,
10107 "glCompressedTexImage2D", "unknown texture target");
10108 return error::kNoError;
10110 Texture* texture = texture_ref->texture();
10111 if (texture->IsImmutable()) {
10112 LOCAL_SET_GL_ERROR(
10113 GL_INVALID_OPERATION,
10114 "glCompressedTexImage2D", "texture is immutable");
10115 return error::kNoError;
10117 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
10118 width, height, 1, internal_format) ||
10119 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
10120 1, internal_format, image_size)) {
10121 return error::kNoError;
10124 if (!EnsureGPUMemoryAvailable(image_size)) {
10125 LOCAL_SET_GL_ERROR(
10126 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
10127 return error::kNoError;
10130 if (texture->IsAttachedToFramebuffer()) {
10131 framebuffer_state_.clear_state_dirty = true;
10134 scoped_ptr<int8[]> zero;
10135 if (!data) {
10136 zero.reset(new int8[image_size]);
10137 memset(zero.get(), 0, image_size);
10138 data = zero.get();
10140 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
10141 glCompressedTexImage2D(
10142 target, level, internal_format, width, height, border, image_size, data);
10143 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
10144 if (error == GL_NO_ERROR) {
10145 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10146 width, height, 1, border, 0, 0,
10147 gfx::Rect(width, height));
10150 // This may be a slow command. Exit command processing to allow for
10151 // context preemption and GPU watchdog checks.
10152 ExitCommandProcessingEarly();
10153 return error::kNoError;
10156 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
10157 uint32 immediate_data_size,
10158 const void* cmd_data) {
10159 const gles2::cmds::CompressedTexImage2D& c =
10160 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
10161 GLenum target = static_cast<GLenum>(c.target);
10162 GLint level = static_cast<GLint>(c.level);
10163 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10164 GLsizei width = static_cast<GLsizei>(c.width);
10165 GLsizei height = static_cast<GLsizei>(c.height);
10166 GLint border = static_cast<GLint>(c.border);
10167 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
10168 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
10169 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
10170 const void* data = NULL;
10171 if (data_shm_id != 0 || data_shm_offset != 0) {
10172 data = GetSharedMemoryAs<const void*>(
10173 data_shm_id, data_shm_offset, image_size);
10174 if (!data) {
10175 return error::kOutOfBounds;
10178 return DoCompressedTexImage2D(
10179 target, level, internal_format, width, height, border, image_size, data);
10182 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
10183 uint32 immediate_data_size,
10184 const void* cmd_data) {
10185 const gles2::cmds::CompressedTexImage2DBucket& c =
10186 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
10187 GLenum target = static_cast<GLenum>(c.target);
10188 GLint level = static_cast<GLint>(c.level);
10189 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10190 GLsizei width = static_cast<GLsizei>(c.width);
10191 GLsizei height = static_cast<GLsizei>(c.height);
10192 GLint border = static_cast<GLint>(c.border);
10193 Bucket* bucket = GetBucket(c.bucket_id);
10194 if (!bucket) {
10195 return error::kInvalidArguments;
10197 uint32 data_size = bucket->size();
10198 GLsizei imageSize = data_size;
10199 const void* data = bucket->GetData(0, data_size);
10200 if (!data) {
10201 return error::kInvalidArguments;
10203 return DoCompressedTexImage2D(
10204 target, level, internal_format, width, height, border,
10205 imageSize, data);
10208 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
10209 uint32 immediate_data_size,
10210 const void* cmd_data) {
10211 const gles2::cmds::CompressedTexSubImage2DBucket& c =
10212 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
10213 GLenum target = static_cast<GLenum>(c.target);
10214 GLint level = static_cast<GLint>(c.level);
10215 GLint xoffset = static_cast<GLint>(c.xoffset);
10216 GLint yoffset = static_cast<GLint>(c.yoffset);
10217 GLsizei width = static_cast<GLsizei>(c.width);
10218 GLsizei height = static_cast<GLsizei>(c.height);
10219 GLenum format = static_cast<GLenum>(c.format);
10220 Bucket* bucket = GetBucket(c.bucket_id);
10221 if (!bucket) {
10222 return error::kInvalidArguments;
10224 uint32 data_size = bucket->size();
10225 GLsizei imageSize = data_size;
10226 const void* data = bucket->GetData(0, data_size);
10227 if (!data) {
10228 return error::kInvalidArguments;
10230 if (!validators_->texture_target.IsValid(target)) {
10231 LOCAL_SET_GL_ERROR(
10232 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
10233 return error::kNoError;
10235 if (!validators_->compressed_texture_format.IsValid(format)) {
10236 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10237 "glCompressedTexSubImage2D", format, "format");
10238 return error::kNoError;
10240 if (width < 0) {
10241 LOCAL_SET_GL_ERROR(
10242 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
10243 return error::kNoError;
10245 if (height < 0) {
10246 LOCAL_SET_GL_ERROR(
10247 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
10248 return error::kNoError;
10250 if (imageSize < 0) {
10251 LOCAL_SET_GL_ERROR(
10252 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
10253 return error::kNoError;
10255 DoCompressedTexSubImage2D(
10256 target, level, xoffset, yoffset, width, height, format, imageSize, data);
10257 return error::kNoError;
10260 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
10261 GLenum target,
10262 GLint level,
10263 GLenum internal_format,
10264 GLsizei width,
10265 GLsizei height,
10266 GLsizei depth,
10267 GLint border,
10268 GLsizei image_size,
10269 const void* data) {
10270 if (!validators_->texture_3_d_target.IsValid(target)) {
10271 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10272 "glCompressedTexImage3D", target, "target");
10273 return error::kNoError;
10275 if (!validators_->compressed_texture_format.IsValid(
10276 internal_format)) {
10277 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10278 "glCompressedTexImage3D", internal_format, "internal_format");
10279 return error::kNoError;
10281 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
10282 border != 0) {
10283 LOCAL_SET_GL_ERROR(
10284 GL_INVALID_VALUE,
10285 "glCompressedTexImage3D", "dimensions out of range");
10286 return error::kNoError;
10288 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10289 &state_, target);
10290 if (!texture_ref) {
10291 LOCAL_SET_GL_ERROR(
10292 GL_INVALID_VALUE,
10293 "glCompressedTexImage3D", "unknown texture target");
10294 return error::kNoError;
10296 Texture* texture = texture_ref->texture();
10297 if (texture->IsImmutable()) {
10298 LOCAL_SET_GL_ERROR(
10299 GL_INVALID_OPERATION,
10300 "glCompressedTexImage3D", "texture is immutable");
10301 return error::kNoError;
10304 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
10305 width, height, depth, internal_format) ||
10306 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
10307 depth, internal_format, image_size)) {
10308 return error::kNoError;
10311 if (!EnsureGPUMemoryAvailable(image_size)) {
10312 LOCAL_SET_GL_ERROR(
10313 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
10314 return error::kNoError;
10317 if (texture->IsAttachedToFramebuffer()) {
10318 framebuffer_state_.clear_state_dirty = true;
10321 scoped_ptr<int8[]> zero;
10322 if (!data) {
10323 zero.reset(new int8[image_size]);
10324 memset(zero.get(), 0, image_size);
10325 data = zero.get();
10327 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
10328 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
10329 border, image_size, data);
10330 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
10331 if (error == GL_NO_ERROR) {
10332 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10333 width, height, depth, border, 0, 0,
10334 gfx::Rect(width, height));
10337 // This may be a slow command. Exit command processing to allow for
10338 // context preemption and GPU watchdog checks.
10339 ExitCommandProcessingEarly();
10340 return error::kNoError;
10343 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
10344 uint32 immediate_data_size, const void* cmd_data) {
10345 if (!unsafe_es3_apis_enabled())
10346 return error::kUnknownCommand;
10348 const gles2::cmds::CompressedTexImage3D& c =
10349 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
10350 GLenum target = static_cast<GLenum>(c.target);
10351 GLint level = static_cast<GLint>(c.level);
10352 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10353 GLsizei width = static_cast<GLsizei>(c.width);
10354 GLsizei height = static_cast<GLsizei>(c.height);
10355 GLsizei depth = static_cast<GLsizei>(c.depth);
10356 GLint border = static_cast<GLint>(c.border);
10357 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
10358 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
10359 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
10360 const void* data = NULL;
10361 if (data_shm_id != 0 || data_shm_offset != 0) {
10362 data = GetSharedMemoryAs<const void*>(
10363 data_shm_id, data_shm_offset, image_size);
10364 if (!data) {
10365 return error::kOutOfBounds;
10368 return DoCompressedTexImage3D(target, level, internal_format, width, height,
10369 depth, border, image_size, data);
10372 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
10373 uint32 immediate_data_size, const void* cmd_data) {
10374 if (!unsafe_es3_apis_enabled())
10375 return error::kUnknownCommand;
10377 const gles2::cmds::CompressedTexImage3DBucket& c =
10378 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
10379 GLenum target = static_cast<GLenum>(c.target);
10380 GLint level = static_cast<GLint>(c.level);
10381 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10382 GLsizei width = static_cast<GLsizei>(c.width);
10383 GLsizei height = static_cast<GLsizei>(c.height);
10384 GLsizei depth = static_cast<GLsizei>(c.depth);
10385 GLint border = static_cast<GLint>(c.border);
10386 Bucket* bucket = GetBucket(c.bucket_id);
10387 if (!bucket) {
10388 return error::kInvalidArguments;
10390 uint32 data_size = bucket->size();
10391 GLsizei imageSize = data_size;
10392 const void* data = bucket->GetData(0, data_size);
10393 if (!data) {
10394 return error::kInvalidArguments;
10396 return DoCompressedTexImage3D(target, level, internal_format, width, height,
10397 depth, border, imageSize, data);
10400 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
10401 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
10402 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
10403 GLsizei image_size, const void* data) {
10404 if (!validators_->texture_3_d_target.IsValid(target)) {
10405 LOCAL_SET_GL_ERROR(
10406 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
10407 return;
10409 if (!validators_->compressed_texture_format.IsValid(format)) {
10410 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10411 "glCompressedTexSubImage3D", format, "format");
10412 return;
10414 if (width < 0 || height < 0 || depth < 0) {
10415 LOCAL_SET_GL_ERROR(
10416 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
10417 return;
10419 if (image_size < 0) {
10420 LOCAL_SET_GL_ERROR(
10421 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
10422 return;
10424 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10425 &state_, target);
10426 if (!texture_ref) {
10427 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
10428 "unknown texture for target");
10429 return;
10431 Texture* texture = texture_ref->texture();
10432 GLenum type = 0, internal_format = 0;
10433 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
10434 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
10435 "level does not exist");
10436 return;
10438 if (internal_format != format) {
10439 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
10440 "format does not match internal format");
10441 return;
10443 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
10444 width, height, depth)) {
10445 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
10446 "bad dimensions");
10447 return;
10449 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
10450 width, height, depth, format,
10451 image_size) ||
10452 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
10453 target, level, xoffset, yoffset,
10454 zoffset, width, height, depth,
10455 format, texture)) {
10456 return;
10459 // Note: There is no need to deal with texture cleared tracking here
10460 // because the validation above means you can only get here if the level
10461 // is already a matching compressed format and in that case
10462 // CompressedTexImage3D already cleared the texture.
10463 glCompressedTexSubImage3D(
10464 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
10465 image_size, data);
10467 // This may be a slow command. Exit command processing to allow for
10468 // context preemption and GPU watchdog checks.
10469 ExitCommandProcessingEarly();
10472 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
10473 uint32 immediate_data_size, const void* cmd_data) {
10474 if (!unsafe_es3_apis_enabled())
10475 return error::kUnknownCommand;
10476 const gles2::cmds::CompressedTexSubImage3DBucket& c =
10477 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
10478 GLenum target = static_cast<GLenum>(c.target);
10479 GLint level = static_cast<GLint>(c.level);
10480 GLint xoffset = static_cast<GLint>(c.xoffset);
10481 GLint yoffset = static_cast<GLint>(c.yoffset);
10482 GLint zoffset = static_cast<GLint>(c.zoffset);
10483 GLsizei width = static_cast<GLsizei>(c.width);
10484 GLsizei height = static_cast<GLsizei>(c.height);
10485 GLsizei depth = static_cast<GLsizei>(c.depth);
10486 GLenum format = static_cast<GLenum>(c.format);
10487 Bucket* bucket = GetBucket(c.bucket_id);
10488 if (!bucket) {
10489 return error::kInvalidArguments;
10491 uint32 data_size = bucket->size();
10492 GLsizei image_size = data_size;
10493 const void* data = bucket->GetData(0, data_size);
10494 if (!data) {
10495 return error::kInvalidArguments;
10497 DoCompressedTexSubImage3D(
10498 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
10499 image_size, data);
10500 return error::kNoError;
10503 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
10504 const void* cmd_data) {
10505 const gles2::cmds::TexImage2D& c =
10506 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
10507 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
10508 "width", c.width, "height", c.height);
10509 // Set as failed for now, but if it successed, this will be set to not failed.
10510 texture_state_.tex_image_failed = true;
10511 GLenum target = static_cast<GLenum>(c.target);
10512 GLint level = static_cast<GLint>(c.level);
10513 // TODO(kloveless): Change TexImage2D command to use unsigned integer
10514 // for internalformat.
10515 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10516 GLsizei width = static_cast<GLsizei>(c.width);
10517 GLsizei height = static_cast<GLsizei>(c.height);
10518 GLint border = static_cast<GLint>(c.border);
10519 GLenum format = static_cast<GLenum>(c.format);
10520 GLenum type = static_cast<GLenum>(c.type);
10521 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10522 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10523 uint32 pixels_size;
10524 if (!GLES2Util::ComputeImageDataSizes(
10525 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10526 NULL, NULL)) {
10527 return error::kOutOfBounds;
10529 const void* pixels = NULL;
10530 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10531 pixels = GetSharedMemoryAs<const void*>(
10532 pixels_shm_id, pixels_shm_offset, pixels_size);
10533 if (!pixels) {
10534 return error::kOutOfBounds;
10538 // For testing only. Allows us to stress the ability to respond to OOM errors.
10539 if (workarounds().simulate_out_of_memory_on_large_textures &&
10540 (width * height >= 4096 * 4096)) {
10541 LOCAL_SET_GL_ERROR(
10542 GL_OUT_OF_MEMORY,
10543 "glTexImage2D", "synthetic out of memory");
10544 return error::kNoError;
10547 TextureManager::DoTexImageArguments args = {
10548 target, level, internal_format, width, height, 1, border, format, type,
10549 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
10550 texture_manager()->ValidateAndDoTexImage(
10551 &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
10553 // This may be a slow command. Exit command processing to allow for
10554 // context preemption and GPU watchdog checks.
10555 ExitCommandProcessingEarly();
10556 return error::kNoError;
10559 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
10560 const void* cmd_data) {
10561 if (!unsafe_es3_apis_enabled())
10562 return error::kUnknownCommand;
10564 const gles2::cmds::TexImage3D& c =
10565 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
10566 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
10567 "widthXheight", c.width * c.height, "depth", c.depth);
10568 // Set as failed for now, but if it successed, this will be set to not failed.
10569 texture_state_.tex_image_failed = true;
10570 GLenum target = static_cast<GLenum>(c.target);
10571 GLint level = static_cast<GLint>(c.level);
10572 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10573 GLsizei width = static_cast<GLsizei>(c.width);
10574 GLsizei height = static_cast<GLsizei>(c.height);
10575 GLsizei depth = static_cast<GLsizei>(c.depth);
10576 GLint border = static_cast<GLint>(c.border);
10577 GLenum format = static_cast<GLenum>(c.format);
10578 GLenum type = static_cast<GLenum>(c.type);
10579 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10580 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10581 uint32 pixels_size;
10582 if (!GLES2Util::ComputeImageDataSizes(
10583 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
10584 NULL, NULL)) {
10585 return error::kOutOfBounds;
10587 const void* pixels = NULL;
10588 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10589 pixels = GetSharedMemoryAs<const void*>(
10590 pixels_shm_id, pixels_shm_offset, pixels_size);
10591 if (!pixels) {
10592 return error::kOutOfBounds;
10596 // For testing only. Allows us to stress the ability to respond to OOM errors.
10597 if (workarounds().simulate_out_of_memory_on_large_textures &&
10598 (width * height * depth >= 4096 * 4096)) {
10599 LOCAL_SET_GL_ERROR(
10600 GL_OUT_OF_MEMORY,
10601 "glTexImage3D", "synthetic out of memory");
10602 return error::kNoError;
10605 TextureManager::DoTexImageArguments args = {
10606 target, level, internal_format, width, height, depth, border, format, type,
10607 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
10608 texture_manager()->ValidateAndDoTexImage(
10609 &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
10611 // This may be a slow command. Exit command processing to allow for
10612 // context preemption and GPU watchdog checks.
10613 ExitCommandProcessingEarly();
10614 return error::kNoError;
10617 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10618 GLenum target,
10619 GLint level,
10620 GLint xoffset,
10621 GLint yoffset,
10622 GLsizei width,
10623 GLsizei height,
10624 GLenum format,
10625 GLsizei image_size,
10626 const void * data) {
10627 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10628 &state_, target);
10629 if (!texture_ref) {
10630 LOCAL_SET_GL_ERROR(
10631 GL_INVALID_OPERATION,
10632 "glCompressedTexSubImage2D", "unknown texture for target");
10633 return;
10635 Texture* texture = texture_ref->texture();
10636 GLenum type = 0;
10637 GLenum internal_format = 0;
10638 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
10639 LOCAL_SET_GL_ERROR(
10640 GL_INVALID_OPERATION,
10641 "glCompressedTexSubImage2D", "level does not exist.");
10642 return;
10644 if (internal_format != format) {
10645 LOCAL_SET_GL_ERROR(
10646 GL_INVALID_OPERATION,
10647 "glCompressedTexSubImage2D", "format does not match internal format.");
10648 return;
10650 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
10651 height, 1)) {
10652 LOCAL_SET_GL_ERROR(
10653 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
10654 return;
10657 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10658 width, height, 1, format, image_size) ||
10659 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10660 target, level, xoffset, yoffset, 0,
10661 width, height, 1, format, texture)) {
10662 return;
10666 // Note: There is no need to deal with texture cleared tracking here
10667 // because the validation above means you can only get here if the level
10668 // is already a matching compressed format and in that case
10669 // CompressedTexImage2D already cleared the texture.
10670 glCompressedTexSubImage2D(
10671 target, level, xoffset, yoffset, width, height, format, image_size, data);
10673 // This may be a slow command. Exit command processing to allow for
10674 // context preemption and GPU watchdog checks.
10675 ExitCommandProcessingEarly();
10678 static void Clip(
10679 GLint start, GLint range, GLint sourceRange,
10680 GLint* out_start, GLint* out_range) {
10681 DCHECK(out_start);
10682 DCHECK(out_range);
10683 if (start < 0) {
10684 range += start;
10685 start = 0;
10687 GLint end = start + range;
10688 if (end > sourceRange) {
10689 range -= end - sourceRange;
10691 *out_start = start;
10692 *out_range = range;
10695 void GLES2DecoderImpl::DoCopyTexImage2D(
10696 GLenum target,
10697 GLint level,
10698 GLenum internal_format,
10699 GLint x,
10700 GLint y,
10701 GLsizei width,
10702 GLsizei height,
10703 GLint border) {
10704 DCHECK(!ShouldDeferReads());
10705 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10706 &state_, target);
10707 if (!texture_ref) {
10708 LOCAL_SET_GL_ERROR(
10709 GL_INVALID_OPERATION,
10710 "glCopyTexImage2D", "unknown texture for target");
10711 return;
10713 Texture* texture = texture_ref->texture();
10714 if (texture->IsImmutable()) {
10715 LOCAL_SET_GL_ERROR(
10716 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
10717 return;
10719 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
10720 border != 0) {
10721 LOCAL_SET_GL_ERROR(
10722 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
10723 return;
10725 if (!texture_manager()->ValidateFormatAndTypeCombination(
10726 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
10727 GL_UNSIGNED_BYTE)) {
10728 return;
10731 // Check we have compatible formats.
10732 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10733 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10734 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
10736 if ((channels_needed & channels_exist) != channels_needed) {
10737 LOCAL_SET_GL_ERROR(
10738 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
10739 return;
10742 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10743 LOCAL_SET_GL_ERROR(
10744 GL_INVALID_OPERATION,
10745 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10746 return;
10749 uint32 estimated_size = 0;
10750 if (!GLES2Util::ComputeImageDataSizes(
10751 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10752 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
10753 LOCAL_SET_GL_ERROR(
10754 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
10755 return;
10758 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10759 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
10760 return;
10763 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10764 return;
10767 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10768 LOCAL_SET_GL_ERROR(
10769 GL_INVALID_OPERATION,
10770 "glCopyTexImage2D", "source and destination textures are the same");
10771 return;
10774 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10775 return;
10778 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10779 ScopedResolvedFrameBufferBinder binder(this, false, true);
10780 gfx::Size size = GetBoundReadFrameBufferSize();
10782 if (texture->IsAttachedToFramebuffer()) {
10783 framebuffer_state_.clear_state_dirty = true;
10786 // Clip to size to source dimensions
10787 GLint copyX = 0;
10788 GLint copyY = 0;
10789 GLint copyWidth = 0;
10790 GLint copyHeight = 0;
10791 Clip(x, width, size.width(), &copyX, &copyWidth);
10792 Clip(y, height, size.height(), &copyY, &copyHeight);
10794 if (copyX != x ||
10795 copyY != y ||
10796 copyWidth != width ||
10797 copyHeight != height) {
10798 // some part was clipped so clear the rect.
10799 uint32 pixels_size = 0;
10800 if (!GLES2Util::ComputeImageDataSizes(
10801 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10802 state_.unpack_alignment, &pixels_size, NULL, NULL)) {
10803 LOCAL_SET_GL_ERROR(
10804 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
10805 return;
10807 scoped_ptr<char[]> zero(new char[pixels_size]);
10808 memset(zero.get(), 0, pixels_size);
10809 ScopedModifyPixels modify(texture_ref);
10810 glTexImage2D(target, level, internal_format, width, height, border,
10811 internal_format, GL_UNSIGNED_BYTE, zero.get());
10812 if (copyHeight > 0 && copyWidth > 0) {
10813 GLint dx = copyX - x;
10814 GLint dy = copyY - y;
10815 GLint destX = dx;
10816 GLint destY = dy;
10817 glCopyTexSubImage2D(target, level,
10818 destX, destY, copyX, copyY,
10819 copyWidth, copyHeight);
10821 } else {
10822 ScopedModifyPixels modify(texture_ref);
10823 glCopyTexImage2D(target, level, internal_format,
10824 copyX, copyY, copyWidth, copyHeight, border);
10826 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10827 if (error == GL_NO_ERROR) {
10828 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10829 width, height, 1, border, internal_format,
10830 GL_UNSIGNED_BYTE, gfx::Rect(width, height));
10833 // This may be a slow command. Exit command processing to allow for
10834 // context preemption and GPU watchdog checks.
10835 ExitCommandProcessingEarly();
10838 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10839 GLenum target,
10840 GLint level,
10841 GLint xoffset,
10842 GLint yoffset,
10843 GLint x,
10844 GLint y,
10845 GLsizei width,
10846 GLsizei height) {
10847 DCHECK(!ShouldDeferReads());
10848 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10849 &state_, target);
10850 if (!texture_ref) {
10851 LOCAL_SET_GL_ERROR(
10852 GL_INVALID_OPERATION,
10853 "glCopyTexSubImage2D", "unknown texture for target");
10854 return;
10856 Texture* texture = texture_ref->texture();
10857 GLenum type = 0;
10858 GLenum format = 0;
10859 if (!texture->GetLevelType(target, level, &type, &format) ||
10860 !texture->ValidForTexture(
10861 target, level, xoffset, yoffset, 0, width, height, 1)) {
10862 LOCAL_SET_GL_ERROR(
10863 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
10864 return;
10867 // Check we have compatible formats.
10868 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10869 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10870 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
10872 if (!channels_needed ||
10873 (channels_needed & channels_exist) != channels_needed) {
10874 LOCAL_SET_GL_ERROR(
10875 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
10876 return;
10879 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10880 LOCAL_SET_GL_ERROR(
10881 GL_INVALID_OPERATION,
10882 "glCopySubImage2D", "can not be used with depth or stencil textures");
10883 return;
10886 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10887 return;
10890 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10891 LOCAL_SET_GL_ERROR(
10892 GL_INVALID_OPERATION,
10893 "glCopyTexSubImage2D", "source and destination textures are the same");
10894 return;
10897 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10898 return;
10901 ScopedResolvedFrameBufferBinder binder(this, false, true);
10902 gfx::Size size = GetBoundReadFrameBufferSize();
10903 GLint copyX = 0;
10904 GLint copyY = 0;
10905 GLint copyWidth = 0;
10906 GLint copyHeight = 0;
10907 Clip(x, width, size.width(), &copyX, &copyWidth);
10908 Clip(y, height, size.height(), &copyY, &copyHeight);
10910 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
10911 height != size.height()) {
10912 gfx::Rect cleared_rect;
10913 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10914 gfx::Rect(xoffset, yoffset, width, height),
10915 &cleared_rect)) {
10916 DCHECK_GE(cleared_rect.size().GetArea(),
10917 texture->GetLevelClearedRect(target, level).size().GetArea());
10918 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10919 cleared_rect);
10920 } else {
10921 // Otherwise clear part of texture level that is not already cleared.
10922 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10923 level)) {
10924 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
10925 "dimensions too big");
10926 return;
10929 } else {
10930 // Write all pixels in below.
10931 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10934 if (copyX != x ||
10935 copyY != y ||
10936 copyWidth != width ||
10937 copyHeight != height) {
10938 // some part was clipped so clear the sub rect.
10939 uint32 pixels_size = 0;
10940 if (!GLES2Util::ComputeImageDataSizes(
10941 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10942 NULL, NULL)) {
10943 LOCAL_SET_GL_ERROR(
10944 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
10945 return;
10947 scoped_ptr<char[]> zero(new char[pixels_size]);
10948 memset(zero.get(), 0, pixels_size);
10949 ScopedModifyPixels modify(texture_ref);
10950 glTexSubImage2D(
10951 target, level, xoffset, yoffset, width, height,
10952 format, type, zero.get());
10955 if (copyHeight > 0 && copyWidth > 0) {
10956 GLint dx = copyX - x;
10957 GLint dy = copyY - y;
10958 GLint destX = xoffset + dx;
10959 GLint destY = yoffset + dy;
10960 ScopedModifyPixels modify(texture_ref);
10961 glCopyTexSubImage2D(target, level,
10962 destX, destY, copyX, copyY,
10963 copyWidth, copyHeight);
10966 // This may be a slow command. Exit command processing to allow for
10967 // context preemption and GPU watchdog checks.
10968 ExitCommandProcessingEarly();
10971 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10972 error::Error* error,
10973 const char* function_name,
10974 GLenum target,
10975 GLint level,
10976 GLint xoffset,
10977 GLint yoffset,
10978 GLsizei width,
10979 GLsizei height,
10980 GLenum format,
10981 GLenum type,
10982 const void * data) {
10983 (*error) = error::kNoError;
10984 if (!validators_->texture_target.IsValid(target)) {
10985 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10986 return false;
10988 if (width < 0) {
10989 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10990 return false;
10992 if (height < 0) {
10993 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10994 return false;
10996 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10997 &state_, target);
10998 if (!texture_ref) {
10999 LOCAL_SET_GL_ERROR(
11000 GL_INVALID_OPERATION,
11001 function_name, "unknown texture for target");
11002 return false;
11004 Texture* texture = texture_ref->texture();
11005 GLenum current_type = 0;
11006 GLenum internal_format = 0;
11007 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
11008 LOCAL_SET_GL_ERROR(
11009 GL_INVALID_OPERATION, function_name, "level does not exist.");
11010 return false;
11012 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
11013 function_name, format, type, internal_format, level)) {
11014 return false;
11016 if (type != current_type && !feature_info_->IsES3Enabled()) {
11017 LOCAL_SET_GL_ERROR(
11018 GL_INVALID_OPERATION,
11019 function_name, "type does not match type of texture.");
11020 return false;
11022 if (!texture->ValidForTexture(
11023 target, level, xoffset, yoffset, 0, width, height, 1)) {
11024 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
11025 return false;
11027 if ((GLES2Util::GetChannelsForFormat(format) &
11028 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0
11029 && !feature_info_->IsES3Enabled()) {
11030 LOCAL_SET_GL_ERROR(
11031 GL_INVALID_OPERATION,
11032 function_name, "can not supply data for depth or stencil textures");
11033 return false;
11035 if (data == NULL) {
11036 (*error) = error::kOutOfBounds;
11037 return false;
11039 return true;
11042 error::Error GLES2DecoderImpl::DoTexSubImage2D(
11043 GLenum target,
11044 GLint level,
11045 GLint xoffset,
11046 GLint yoffset,
11047 GLsizei width,
11048 GLsizei height,
11049 GLenum format,
11050 GLenum type,
11051 const void * data) {
11052 error::Error error = error::kNoError;
11053 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
11054 xoffset, yoffset, width, height, format, type, data)) {
11055 return error;
11057 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11058 &state_, target);
11059 Texture* texture = texture_ref->texture();
11060 GLsizei tex_width = 0;
11061 GLsizei tex_height = 0;
11062 bool ok = texture->GetLevelSize(
11063 target, level, &tex_width, &tex_height, nullptr);
11064 DCHECK(ok);
11065 if (xoffset != 0 || yoffset != 0 ||
11066 width != tex_width || height != tex_height) {
11067 gfx::Rect cleared_rect;
11068 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
11069 gfx::Rect(xoffset, yoffset, width, height),
11070 &cleared_rect)) {
11071 DCHECK_GE(cleared_rect.size().GetArea(),
11072 texture->GetLevelClearedRect(target, level).size().GetArea());
11073 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
11074 cleared_rect);
11075 } else {
11076 // Otherwise clear part of texture level that is not already cleared.
11077 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
11078 level)) {
11079 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D",
11080 "dimensions too big");
11081 return error::kNoError;
11084 ScopedTextureUploadTimer timer(&texture_state_);
11085 glTexSubImage2D(
11086 target, level, xoffset, yoffset, width, height, format, type, data);
11087 return error::kNoError;
11090 if (!texture_state_.texsubimage_faster_than_teximage &&
11091 !texture->IsImmutable() &&
11092 !texture->HasImages()) {
11093 ScopedTextureUploadTimer timer(&texture_state_);
11094 GLenum internal_format;
11095 GLenum tex_type;
11096 texture->GetLevelType(target, level, &tex_type, &internal_format);
11097 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
11098 // to look it up.
11099 glTexImage2D(
11100 target, level, internal_format, width, height, 0, format, type, data);
11101 } else {
11102 ScopedTextureUploadTimer timer(&texture_state_);
11103 glTexSubImage2D(
11104 target, level, xoffset, yoffset, width, height, format, type, data);
11106 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
11108 // This may be a slow command. Exit command processing to allow for
11109 // context preemption and GPU watchdog checks.
11110 ExitCommandProcessingEarly();
11111 return error::kNoError;
11114 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
11115 const void* cmd_data) {
11116 const gles2::cmds::TexSubImage2D& c =
11117 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
11118 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
11119 "width", c.width, "height", c.height);
11120 GLboolean internal = static_cast<GLboolean>(c.internal);
11121 if (internal == GL_TRUE && texture_state_.tex_image_failed)
11122 return error::kNoError;
11124 GLenum target = static_cast<GLenum>(c.target);
11125 GLint level = static_cast<GLint>(c.level);
11126 GLint xoffset = static_cast<GLint>(c.xoffset);
11127 GLint yoffset = static_cast<GLint>(c.yoffset);
11128 GLsizei width = static_cast<GLsizei>(c.width);
11129 GLsizei height = static_cast<GLsizei>(c.height);
11130 GLenum format = static_cast<GLenum>(c.format);
11131 GLenum type = static_cast<GLenum>(c.type);
11132 uint32 data_size;
11133 if (!GLES2Util::ComputeImageDataSizes(
11134 width, height, 1, format, type, state_.unpack_alignment, &data_size,
11135 NULL, NULL)) {
11136 return error::kOutOfBounds;
11138 const void* pixels = GetSharedMemoryAs<const void*>(
11139 c.pixels_shm_id, c.pixels_shm_offset, data_size);
11140 return DoTexSubImage2D(
11141 target, level, xoffset, yoffset, width, height, format, type, pixels);
11144 error::Error GLES2DecoderImpl::DoTexSubImage3D(
11145 GLenum target,
11146 GLint level,
11147 GLint xoffset,
11148 GLint yoffset,
11149 GLint zoffset,
11150 GLsizei width,
11151 GLsizei height,
11152 GLsizei depth,
11153 GLenum format,
11154 GLenum type,
11155 const void * data) {
11156 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11157 &state_, target);
11158 if (!texture_ref) {
11159 LOCAL_SET_GL_ERROR(
11160 GL_INVALID_ENUM, "glTexSubImage3D", "invalid target");
11163 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
11164 ScopedTextureUploadTimer timer(&texture_state_);
11165 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
11166 depth, format, type, data);
11167 GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
11168 if (error == GL_NO_ERROR) {
11169 // TODO(zmo): This is not 100% correct because only part of the level
11170 // image is cleared.
11171 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
11174 // This may be a slow command. Exit command processing to allow for
11175 // context preemption and GPU watchdog checks.
11176 ExitCommandProcessingEarly();
11177 return error::kNoError;
11180 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
11181 const void* cmd_data) {
11182 if (!unsafe_es3_apis_enabled())
11183 return error::kUnknownCommand;
11185 const gles2::cmds::TexSubImage3D& c =
11186 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
11187 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
11188 "widthXheight", c.width * c.height, "depth", c.depth);
11189 GLboolean internal = static_cast<GLboolean>(c.internal);
11190 if (internal == GL_TRUE && texture_state_.tex_image_failed)
11191 return error::kNoError;
11193 GLenum target = static_cast<GLenum>(c.target);
11194 GLint level = static_cast<GLint>(c.level);
11195 GLint xoffset = static_cast<GLint>(c.xoffset);
11196 GLint yoffset = static_cast<GLint>(c.yoffset);
11197 GLint zoffset = static_cast<GLint>(c.zoffset);
11198 GLsizei width = static_cast<GLsizei>(c.width);
11199 GLsizei height = static_cast<GLsizei>(c.height);
11200 GLsizei depth = static_cast<GLsizei>(c.depth);
11201 GLenum format = static_cast<GLenum>(c.format);
11202 GLenum type = static_cast<GLenum>(c.type);
11203 uint32 data_size;
11204 if (!GLES2Util::ComputeImageDataSizes(
11205 width, height, depth, format, type, state_.unpack_alignment, &data_size,
11206 NULL, NULL)) {
11207 return error::kOutOfBounds;
11209 const void* pixels = GetSharedMemoryAs<const void*>(
11210 c.pixels_shm_id, c.pixels_shm_offset, data_size);
11211 return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
11212 height, depth, format, type, pixels);
11215 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
11216 uint32 immediate_data_size,
11217 const void* cmd_data) {
11218 const gles2::cmds::GetVertexAttribPointerv& c =
11219 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
11220 GLuint index = static_cast<GLuint>(c.index);
11221 GLenum pname = static_cast<GLenum>(c.pname);
11222 typedef cmds::GetVertexAttribPointerv::Result Result;
11223 Result* result = GetSharedMemoryAs<Result*>(
11224 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
11225 if (!result) {
11226 return error::kOutOfBounds;
11228 // Check that the client initialized the result.
11229 if (result->size != 0) {
11230 return error::kInvalidArguments;
11232 if (!validators_->vertex_pointer.IsValid(pname)) {
11233 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11234 "glGetVertexAttribPointerv", pname, "pname");
11235 return error::kNoError;
11237 if (index >= group_->max_vertex_attribs()) {
11238 LOCAL_SET_GL_ERROR(
11239 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
11240 return error::kNoError;
11242 result->SetNumResults(1);
11243 *result->GetData() =
11244 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
11245 return error::kNoError;
11248 template <class T>
11249 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
11250 GLint fake_location,
11251 uint32 shm_id,
11252 uint32 shm_offset,
11253 error::Error* error,
11254 GLint* real_location,
11255 GLuint* service_id,
11256 SizedResult<T>** result_pointer,
11257 GLenum* result_type,
11258 GLsizei* result_size) {
11259 DCHECK(error);
11260 DCHECK(service_id);
11261 DCHECK(result_pointer);
11262 DCHECK(result_type);
11263 DCHECK(result_size);
11264 DCHECK(real_location);
11265 *error = error::kNoError;
11266 // Make sure we have enough room for the result on failure.
11267 SizedResult<T>* result;
11268 result = GetSharedMemoryAs<SizedResult<T>*>(
11269 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
11270 if (!result) {
11271 *error = error::kOutOfBounds;
11272 return false;
11274 *result_pointer = result;
11275 // Set the result size to 0 so the client does not have to check for success.
11276 result->SetNumResults(0);
11277 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
11278 if (!program) {
11279 return false;
11281 if (!program->IsValid()) {
11282 // Program was not linked successfully. (ie, glLinkProgram)
11283 LOCAL_SET_GL_ERROR(
11284 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
11285 return false;
11287 *service_id = program->service_id();
11288 GLint array_index = -1;
11289 const Program::UniformInfo* uniform_info =
11290 program->GetUniformInfoByFakeLocation(
11291 fake_location, real_location, &array_index);
11292 if (!uniform_info) {
11293 // No such location.
11294 LOCAL_SET_GL_ERROR(
11295 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
11296 return false;
11298 GLenum type = uniform_info->type;
11299 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
11300 if (num_elements == 0) {
11301 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
11302 return false;
11304 result = GetSharedMemoryAs<SizedResult<T>*>(
11305 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
11306 if (!result) {
11307 *error = error::kOutOfBounds;
11308 return false;
11310 result->SetNumResults(num_elements);
11311 *result_size = num_elements * sizeof(T);
11312 *result_type = type;
11313 return true;
11316 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
11317 const void* cmd_data) {
11318 const gles2::cmds::GetUniformiv& c =
11319 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
11320 GLuint program = c.program;
11321 GLint fake_location = c.location;
11322 GLuint service_id;
11323 GLenum result_type;
11324 GLsizei result_size;
11325 GLint real_location = -1;
11326 Error error;
11327 cmds::GetUniformiv::Result* result;
11328 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
11329 c.params_shm_offset, &error, &real_location,
11330 &service_id, &result, &result_type,
11331 &result_size)) {
11332 glGetUniformiv(
11333 service_id, real_location, result->GetData());
11335 return error;
11338 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
11339 const void* cmd_data) {
11340 if (!unsafe_es3_apis_enabled())
11341 return error::kUnknownCommand;
11343 const gles2::cmds::GetUniformuiv& c =
11344 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
11345 GLuint program = c.program;
11346 GLint fake_location = c.location;
11347 GLuint service_id;
11348 GLenum result_type;
11349 GLsizei result_size;
11350 GLint real_location = -1;
11351 Error error;
11352 cmds::GetUniformuiv::Result* result;
11353 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
11354 c.params_shm_offset, &error, &real_location,
11355 &service_id, &result, &result_type,
11356 &result_size)) {
11357 glGetUniformuiv(
11358 service_id, real_location, result->GetData());
11360 return error;
11363 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
11364 const void* cmd_data) {
11365 const gles2::cmds::GetUniformfv& c =
11366 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
11367 GLuint program = c.program;
11368 GLint fake_location = c.location;
11369 GLuint service_id;
11370 GLint real_location = -1;
11371 Error error;
11372 cmds::GetUniformfv::Result* result;
11373 GLenum result_type;
11374 GLsizei result_size;
11375 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
11376 c.params_shm_offset, &error, &real_location,
11377 &service_id, &result, &result_type,
11378 &result_size)) {
11379 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
11380 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
11381 GLsizei num_values = result_size / sizeof(GLfloat);
11382 scoped_ptr<GLint[]> temp(new GLint[num_values]);
11383 glGetUniformiv(service_id, real_location, temp.get());
11384 GLfloat* dst = result->GetData();
11385 for (GLsizei ii = 0; ii < num_values; ++ii) {
11386 dst[ii] = (temp[ii] != 0);
11388 } else {
11389 glGetUniformfv(service_id, real_location, result->GetData());
11392 return error;
11395 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
11396 uint32 immediate_data_size,
11397 const void* cmd_data) {
11398 const gles2::cmds::GetShaderPrecisionFormat& c =
11399 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
11400 GLenum shader_type = static_cast<GLenum>(c.shadertype);
11401 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
11402 typedef cmds::GetShaderPrecisionFormat::Result Result;
11403 Result* result = GetSharedMemoryAs<Result*>(
11404 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11405 if (!result) {
11406 return error::kOutOfBounds;
11408 // Check that the client initialized the result.
11409 if (result->success != 0) {
11410 return error::kInvalidArguments;
11412 if (!validators_->shader_type.IsValid(shader_type)) {
11413 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11414 "glGetShaderPrecisionFormat", shader_type, "shader_type");
11415 return error::kNoError;
11417 if (!validators_->shader_precision.IsValid(precision_type)) {
11418 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11419 "glGetShaderPrecisionFormat", precision_type, "precision_type");
11420 return error::kNoError;
11423 result->success = 1; // true
11425 GLint range[2] = { 0, 0 };
11426 GLint precision = 0;
11427 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
11429 result->min_range = range[0];
11430 result->max_range = range[1];
11431 result->precision = precision;
11433 return error::kNoError;
11436 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
11437 uint32 immediate_data_size,
11438 const void* cmd_data) {
11439 const gles2::cmds::GetAttachedShaders& c =
11440 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
11441 uint32 result_size = c.result_size;
11442 GLuint program_id = static_cast<GLuint>(c.program);
11443 Program* program = GetProgramInfoNotShader(
11444 program_id, "glGetAttachedShaders");
11445 if (!program) {
11446 return error::kNoError;
11448 typedef cmds::GetAttachedShaders::Result Result;
11449 uint32 max_count = Result::ComputeMaxResults(result_size);
11450 Result* result = GetSharedMemoryAs<Result*>(
11451 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
11452 if (!result) {
11453 return error::kOutOfBounds;
11455 // Check that the client initialized the result.
11456 if (result->size != 0) {
11457 return error::kInvalidArguments;
11459 GLsizei count = 0;
11460 glGetAttachedShaders(
11461 program->service_id(), max_count, &count, result->GetData());
11462 for (GLsizei ii = 0; ii < count; ++ii) {
11463 if (!shader_manager()->GetClientId(result->GetData()[ii],
11464 &result->GetData()[ii])) {
11465 NOTREACHED();
11466 return error::kGenericError;
11469 result->SetNumResults(count);
11470 return error::kNoError;
11473 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
11474 uint32 immediate_data_size,
11475 const void* cmd_data) {
11476 const gles2::cmds::GetActiveUniform& c =
11477 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
11478 GLuint program_id = c.program;
11479 GLuint index = c.index;
11480 uint32 name_bucket_id = c.name_bucket_id;
11481 typedef cmds::GetActiveUniform::Result Result;
11482 Result* result = GetSharedMemoryAs<Result*>(
11483 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11484 if (!result) {
11485 return error::kOutOfBounds;
11487 // Check that the client initialized the result.
11488 if (result->success != 0) {
11489 return error::kInvalidArguments;
11491 Program* program = GetProgramInfoNotShader(
11492 program_id, "glGetActiveUniform");
11493 if (!program) {
11494 return error::kNoError;
11496 const Program::UniformInfo* uniform_info =
11497 program->GetUniformInfo(index);
11498 if (!uniform_info) {
11499 LOCAL_SET_GL_ERROR(
11500 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
11501 return error::kNoError;
11503 result->success = 1; // true.
11504 result->size = uniform_info->size;
11505 result->type = uniform_info->type;
11506 Bucket* bucket = CreateBucket(name_bucket_id);
11507 bucket->SetFromString(uniform_info->name.c_str());
11508 return error::kNoError;
11511 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
11512 uint32 immediate_data_size, const void* cmd_data) {
11513 if (!unsafe_es3_apis_enabled())
11514 return error::kUnknownCommand;
11515 const gles2::cmds::GetActiveUniformBlockiv& c =
11516 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
11517 GLuint program_id = c.program;
11518 GLuint index = static_cast<GLuint>(c.index);
11519 GLenum pname = static_cast<GLenum>(c.pname);
11520 Program* program = GetProgramInfoNotShader(
11521 program_id, "glGetActiveUniformBlockiv");
11522 if (!program) {
11523 return error::kNoError;
11525 GLuint service_id = program->service_id();
11526 GLint link_status = GL_FALSE;
11527 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11528 if (link_status != GL_TRUE) {
11529 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11530 "glGetActiveActiveUniformBlockiv", "program not linked");
11531 return error::kNoError;
11533 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
11534 GLsizei num_values = 1;
11535 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
11536 GLint num = 0;
11537 glGetActiveUniformBlockiv(
11538 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
11539 GLenum error = glGetError();
11540 if (error != GL_NO_ERROR) {
11541 // Assume this will the same error if calling with pname.
11542 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
11543 return error::kNoError;
11545 num_values = static_cast<GLsizei>(num);
11547 typedef cmds::GetActiveUniformBlockiv::Result Result;
11548 Result* result = GetSharedMemoryAs<Result*>(
11549 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
11550 GLint* params = result ? result->GetData() : NULL;
11551 if (params == NULL) {
11552 return error::kOutOfBounds;
11554 // Check that the client initialized the result.
11555 if (result->size != 0) {
11556 return error::kInvalidArguments;
11558 glGetActiveUniformBlockiv(service_id, index, pname, params);
11559 GLenum error = glGetError();
11560 if (error == GL_NO_ERROR) {
11561 result->SetNumResults(num_values);
11562 } else {
11563 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
11565 return error::kNoError;
11568 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11569 uint32 immediate_data_size, const void* cmd_data) {
11570 if (!unsafe_es3_apis_enabled())
11571 return error::kUnknownCommand;
11572 const gles2::cmds::GetActiveUniformBlockName& c =
11573 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
11574 GLuint program_id = c.program;
11575 GLuint index = c.index;
11576 uint32 name_bucket_id = c.name_bucket_id;
11577 typedef cmds::GetActiveUniformBlockName::Result Result;
11578 Result* result = GetSharedMemoryAs<Result*>(
11579 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11580 if (!result) {
11581 return error::kOutOfBounds;
11583 // Check that the client initialized the result.
11584 if (*result != 0) {
11585 return error::kInvalidArguments;
11587 Program* program = GetProgramInfoNotShader(
11588 program_id, "glGetActiveUniformBlockName");
11589 if (!program) {
11590 return error::kNoError;
11592 GLuint service_id = program->service_id();
11593 GLint link_status = GL_FALSE;
11594 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11595 if (link_status != GL_TRUE) {
11596 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11597 "glGetActiveActiveUniformBlockName", "program not linked");
11598 return error::kNoError;
11600 GLint max_length = 0;
11601 glGetProgramiv(
11602 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
11603 // Increase one so &buffer[0] is always valid.
11604 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
11605 std::vector<char> buffer(buf_size);
11606 GLsizei length = 0;
11607 glGetActiveUniformBlockName(
11608 service_id, index, buf_size, &length, &buffer[0]);
11609 if (length == 0) {
11610 *result = 0;
11611 return error::kNoError;
11613 *result = 1;
11614 Bucket* bucket = CreateBucket(name_bucket_id);
11615 DCHECK_GT(buf_size, length);
11616 DCHECK_EQ(0, buffer[length]);
11617 bucket->SetFromString(&buffer[0]);
11618 return error::kNoError;
11621 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
11622 uint32 immediate_data_size, const void* cmd_data) {
11623 if (!unsafe_es3_apis_enabled())
11624 return error::kUnknownCommand;
11625 const gles2::cmds::GetActiveUniformsiv& c =
11626 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
11627 GLuint program_id = c.program;
11628 GLenum pname = static_cast<GLenum>(c.pname);
11629 Bucket* bucket = GetBucket(c.indices_bucket_id);
11630 if (!bucket) {
11631 return error::kInvalidArguments;
11633 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
11634 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
11635 typedef cmds::GetActiveUniformsiv::Result Result;
11636 Result* result = GetSharedMemoryAs<Result*>(
11637 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
11638 GLint* params = result ? result->GetData() : NULL;
11639 if (params == NULL) {
11640 return error::kOutOfBounds;
11642 // Check that the client initialized the result.
11643 if (result->size != 0) {
11644 return error::kInvalidArguments;
11646 Program* program = GetProgramInfoNotShader(
11647 program_id, "glGetActiveUniformsiv");
11648 if (!program) {
11649 return error::kNoError;
11651 GLuint service_id = program->service_id();
11652 GLint link_status = GL_FALSE;
11653 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11654 if (link_status != GL_TRUE) {
11655 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11656 "glGetActiveUniformsiv", "program not linked");
11657 return error::kNoError;
11659 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11660 glGetActiveUniformsiv(service_id, count, indices, pname, params);
11661 GLenum error = glGetError();
11662 if (error == GL_NO_ERROR) {
11663 result->SetNumResults(count);
11664 } else {
11665 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
11667 return error::kNoError;
11670 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
11671 const void* cmd_data) {
11672 const gles2::cmds::GetActiveAttrib& c =
11673 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
11674 GLuint program_id = c.program;
11675 GLuint index = c.index;
11676 uint32 name_bucket_id = c.name_bucket_id;
11677 typedef cmds::GetActiveAttrib::Result Result;
11678 Result* result = GetSharedMemoryAs<Result*>(
11679 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11680 if (!result) {
11681 return error::kOutOfBounds;
11683 // Check that the client initialized the result.
11684 if (result->success != 0) {
11685 return error::kInvalidArguments;
11687 Program* program = GetProgramInfoNotShader(
11688 program_id, "glGetActiveAttrib");
11689 if (!program) {
11690 return error::kNoError;
11692 const Program::VertexAttrib* attrib_info =
11693 program->GetAttribInfo(index);
11694 if (!attrib_info) {
11695 LOCAL_SET_GL_ERROR(
11696 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
11697 return error::kNoError;
11699 result->success = 1; // true.
11700 result->size = attrib_info->size;
11701 result->type = attrib_info->type;
11702 Bucket* bucket = CreateBucket(name_bucket_id);
11703 bucket->SetFromString(attrib_info->name.c_str());
11704 return error::kNoError;
11707 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
11708 const void* cmd_data) {
11709 #if 1 // No binary shader support.
11710 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
11711 return error::kNoError;
11712 #else
11713 GLsizei n = static_cast<GLsizei>(c.n);
11714 if (n < 0) {
11715 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
11716 return error::kNoError;
11718 GLsizei length = static_cast<GLsizei>(c.length);
11719 if (length < 0) {
11720 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
11721 return error::kNoError;
11723 uint32 data_size;
11724 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
11725 return error::kOutOfBounds;
11727 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
11728 c.shaders_shm_id, c.shaders_shm_offset, data_size);
11729 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
11730 const void* binary = GetSharedMemoryAs<const void*>(
11731 c.binary_shm_id, c.binary_shm_offset, length);
11732 if (shaders == NULL || binary == NULL) {
11733 return error::kOutOfBounds;
11735 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11736 for (GLsizei ii = 0; ii < n; ++ii) {
11737 Shader* shader = GetShader(shaders[ii]);
11738 if (!shader) {
11739 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
11740 return error::kNoError;
11742 service_ids[ii] = shader->service_id();
11744 // TODO(gman): call glShaderBinary
11745 return error::kNoError;
11746 #endif
11749 void GLES2DecoderImpl::DoSwapBuffers() {
11750 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
11752 int this_frame_number = frame_number_++;
11753 // TRACE_EVENT for gpu tests:
11754 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11755 TRACE_EVENT_SCOPE_THREAD,
11756 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11757 "width", (is_offscreen ? offscreen_size_.width() :
11758 surface_->GetSize().width()));
11759 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11760 "offscreen", is_offscreen,
11761 "frame", this_frame_number);
11763 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11766 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
11767 "GLES2Decoder", "SwapBuffer");
11769 bool is_tracing;
11770 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11771 &is_tracing);
11772 if (is_tracing) {
11773 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
11774 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
11775 is_offscreen ? offscreen_size_ : surface_->GetSize());
11778 // If offscreen then don't actually SwapBuffers to the display. Just copy
11779 // the rendered frame to another frame buffer.
11780 if (is_offscreen) {
11781 TRACE_EVENT2("gpu", "Offscreen",
11782 "width", offscreen_size_.width(), "height", offscreen_size_.height());
11783 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
11784 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11785 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11786 // fix this.
11787 if (workarounds().needs_offscreen_buffer_workaround) {
11788 offscreen_saved_frame_buffer_->Create();
11789 glFinish();
11792 // Allocate the offscreen saved color texture.
11793 DCHECK(offscreen_saved_color_format_);
11794 offscreen_saved_color_texture_->AllocateStorage(
11795 offscreen_size_, offscreen_saved_color_format_, false);
11797 offscreen_saved_frame_buffer_->AttachRenderTexture(
11798 offscreen_saved_color_texture_.get());
11799 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
11800 if (offscreen_saved_frame_buffer_->CheckStatus() !=
11801 GL_FRAMEBUFFER_COMPLETE) {
11802 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11803 << "because offscreen saved FBO was incomplete.";
11804 MarkContextLost(error::kUnknown);
11805 group_->LoseContexts(error::kUnknown);
11806 return;
11809 // Clear the offscreen color texture.
11810 // TODO(piman): Is this still necessary?
11812 ScopedFrameBufferBinder binder(this,
11813 offscreen_saved_frame_buffer_->id());
11814 glClearColor(0, 0, 0, 0);
11815 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
11816 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
11817 glClear(GL_COLOR_BUFFER_BIT);
11818 RestoreClearState();
11822 UpdateParentTextureInfo();
11825 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
11826 return;
11827 ScopedGLErrorSuppressor suppressor(
11828 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11830 if (IsOffscreenBufferMultisampled()) {
11831 // For multisampled buffers, resolve the frame buffer.
11832 ScopedResolvedFrameBufferBinder binder(this, true, false);
11833 } else {
11834 ScopedFrameBufferBinder binder(this,
11835 offscreen_target_frame_buffer_->id());
11837 if (offscreen_target_buffer_preserved_) {
11838 // Copy the target frame buffer to the saved offscreen texture.
11839 offscreen_saved_color_texture_->Copy(
11840 offscreen_saved_color_texture_->size(),
11841 offscreen_saved_color_format_);
11842 } else {
11843 // Flip the textures in the parent context via the texture manager.
11844 if (!!offscreen_saved_color_texture_info_.get())
11845 offscreen_saved_color_texture_info_->texture()->
11846 SetServiceId(offscreen_target_color_texture_->id());
11848 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
11849 offscreen_target_frame_buffer_->AttachRenderTexture(
11850 offscreen_target_color_texture_.get());
11853 // Ensure the side effects of the copy are visible to the parent
11854 // context. There is no need to do this for ANGLE because it uses a
11855 // single D3D device for all contexts.
11856 if (!feature_info_->gl_version_info().is_angle)
11857 glFlush();
11859 } else {
11860 if (surface_->SwapBuffers() == gfx::SwapResult::SWAP_FAILED) {
11861 LOG(ERROR) << "Context lost because SwapBuffers failed.";
11862 if (!CheckResetStatus()) {
11863 MarkContextLost(error::kUnknown);
11864 group_->LoseContexts(error::kUnknown);
11869 // This may be a slow command. Exit command processing to allow for
11870 // context preemption and GPU watchdog checks.
11871 ExitCommandProcessingEarly();
11874 void GLES2DecoderImpl::DoSwapInterval(int interval) {
11875 context_->SetSwapInterval(interval);
11878 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11879 uint32 immediate_data_size,
11880 const void* cmd_data) {
11881 const gles2::cmds::EnableFeatureCHROMIUM& c =
11882 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
11883 Bucket* bucket = GetBucket(c.bucket_id);
11884 if (!bucket || bucket->size() == 0) {
11885 return error::kInvalidArguments;
11887 typedef cmds::EnableFeatureCHROMIUM::Result Result;
11888 Result* result = GetSharedMemoryAs<Result*>(
11889 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11890 if (!result) {
11891 return error::kOutOfBounds;
11893 // Check that the client initialized the result.
11894 if (*result != 0) {
11895 return error::kInvalidArguments;
11897 std::string feature_str;
11898 if (!bucket->GetAsString(&feature_str)) {
11899 return error::kInvalidArguments;
11902 // TODO(gman): make this some kind of table to function pointer thingy.
11903 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11904 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11905 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
11906 buffer_manager()->set_allow_fixed_attribs(true);
11907 // TODO(gman): decide how to remove the need for this const_cast.
11908 // I could make validators_ non const but that seems bad as this is the only
11909 // place it is needed. I could make some special friend class of validators
11910 // just to allow this to set them. That seems silly. I could refactor this
11911 // code to use the extension mechanism or the initialization attributes to
11912 // turn this feature on. Given that the only real point of this is to make
11913 // the conformance tests pass and given that there is lots of real work that
11914 // needs to be done it seems like refactoring for one to one of those
11915 // methods is a very low priority.
11916 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
11917 } else {
11918 return error::kNoError;
11921 *result = 1; // true.
11922 return error::kNoError;
11925 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11926 uint32 immediate_data_size,
11927 const void* cmd_data) {
11928 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
11929 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
11930 cmd_data);
11931 Bucket* bucket = CreateBucket(c.bucket_id);
11932 scoped_refptr<FeatureInfo> info(new FeatureInfo());
11933 info->Initialize(disallowed_features_);
11934 bucket->SetFromString(info->extensions().c_str());
11935 return error::kNoError;
11938 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11939 uint32 immediate_data_size,
11940 const void* cmd_data) {
11941 const gles2::cmds::RequestExtensionCHROMIUM& c =
11942 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
11943 Bucket* bucket = GetBucket(c.bucket_id);
11944 if (!bucket || bucket->size() == 0) {
11945 return error::kInvalidArguments;
11947 std::string feature_str;
11948 if (!bucket->GetAsString(&feature_str)) {
11949 return error::kInvalidArguments;
11952 bool desire_standard_derivatives = false;
11953 bool desire_frag_depth = false;
11954 bool desire_draw_buffers = false;
11955 bool desire_shader_texture_lod = false;
11956 if (IsWebGLContext()) {
11957 desire_standard_derivatives =
11958 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
11959 desire_frag_depth =
11960 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
11961 desire_draw_buffers =
11962 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
11963 desire_shader_texture_lod =
11964 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
11967 if (desire_standard_derivatives != derivatives_explicitly_enabled_ ||
11968 desire_frag_depth != frag_depth_explicitly_enabled_ ||
11969 desire_draw_buffers != draw_buffers_explicitly_enabled_ ||
11970 desire_shader_texture_lod != shader_texture_lod_explicitly_enabled_) {
11971 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
11972 frag_depth_explicitly_enabled_ |= desire_frag_depth;
11973 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
11974 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
11975 InitializeShaderTranslator();
11978 UpdateCapabilities();
11980 return error::kNoError;
11983 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11984 uint32 immediate_data_size,
11985 const void* cmd_data) {
11986 const gles2::cmds::GetProgramInfoCHROMIUM& c =
11987 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
11988 GLuint program_id = static_cast<GLuint>(c.program);
11989 uint32 bucket_id = c.bucket_id;
11990 Bucket* bucket = CreateBucket(bucket_id);
11991 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
11992 Program* program = NULL;
11993 program = GetProgram(program_id);
11994 if (!program || !program->IsValid()) {
11995 return error::kNoError;
11997 program->GetProgramInfo(program_manager(), bucket);
11998 return error::kNoError;
12001 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
12002 uint32 immediate_data_size, const void* cmd_data) {
12003 if (!unsafe_es3_apis_enabled())
12004 return error::kUnknownCommand;
12005 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
12006 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
12007 GLuint program_id = static_cast<GLuint>(c.program);
12008 uint32 bucket_id = c.bucket_id;
12009 Bucket* bucket = CreateBucket(bucket_id);
12010 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
12011 Program* program = NULL;
12012 program = GetProgram(program_id);
12013 if (!program || !program->IsValid()) {
12014 return error::kNoError;
12016 program->GetUniformBlocks(bucket);
12017 return error::kNoError;
12020 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
12021 uint32 immediate_data_size, const void* cmd_data) {
12022 if (!unsafe_es3_apis_enabled())
12023 return error::kUnknownCommand;
12024 const gles2::cmds::GetUniformsES3CHROMIUM& c =
12025 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
12026 GLuint program_id = static_cast<GLuint>(c.program);
12027 uint32 bucket_id = c.bucket_id;
12028 Bucket* bucket = CreateBucket(bucket_id);
12029 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
12030 Program* program = NULL;
12031 program = GetProgram(program_id);
12032 if (!program || !program->IsValid()) {
12033 return error::kNoError;
12035 program->GetUniformsES3(bucket);
12036 return error::kNoError;
12039 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
12040 uint32 immediate_data_size,
12041 const void* cmd_data) {
12042 if (!unsafe_es3_apis_enabled())
12043 return error::kUnknownCommand;
12044 const gles2::cmds::GetTransformFeedbackVarying& c =
12045 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
12046 GLuint program_id = c.program;
12047 GLuint index = c.index;
12048 uint32 name_bucket_id = c.name_bucket_id;
12049 typedef cmds::GetTransformFeedbackVarying::Result Result;
12050 Result* result = GetSharedMemoryAs<Result*>(
12051 c.result_shm_id, c.result_shm_offset, sizeof(*result));
12052 if (!result) {
12053 return error::kOutOfBounds;
12055 // Check that the client initialized the result.
12056 if (result->success != 0) {
12057 return error::kInvalidArguments;
12059 Program* program = GetProgramInfoNotShader(
12060 program_id, "glGetTransformFeedbackVarying");
12061 if (!program) {
12062 return error::kNoError;
12064 GLuint service_id = program->service_id();
12065 GLint link_status = GL_FALSE;
12066 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
12067 if (link_status != GL_TRUE) {
12068 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12069 "glGetTransformFeedbackVarying", "program not linked");
12070 return error::kNoError;
12072 GLint max_length = 0;
12073 glGetProgramiv(
12074 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
12075 max_length = std::max(1, max_length);
12076 std::vector<char> buffer(max_length);
12077 GLsizei length = 0;
12078 GLsizei size = 0;
12079 GLenum type = 0;
12080 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
12081 glGetTransformFeedbackVarying(
12082 service_id, index, max_length, &length, &size, &type, &buffer[0]);
12083 GLenum error = glGetError();
12084 if (error != GL_NO_ERROR) {
12085 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
12086 return error::kNoError;
12088 result->success = 1; // true.
12089 result->size = static_cast<int32_t>(size);
12090 result->type = static_cast<uint32_t>(type);
12091 Bucket* bucket = CreateBucket(name_bucket_id);
12092 DCHECK(length >= 0 && length < max_length);
12093 buffer[length] = '\0'; // Just to be safe.
12094 bucket->SetFromString(&buffer[0]);
12095 return error::kNoError;
12098 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
12099 uint32 immediate_data_size, const void* cmd_data) {
12100 if (!unsafe_es3_apis_enabled())
12101 return error::kUnknownCommand;
12102 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
12103 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
12104 cmd_data);
12105 GLuint program_id = static_cast<GLuint>(c.program);
12106 uint32 bucket_id = c.bucket_id;
12107 Bucket* bucket = CreateBucket(bucket_id);
12108 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
12109 Program* program = NULL;
12110 program = GetProgram(program_id);
12111 if (!program || !program->IsValid()) {
12112 return error::kNoError;
12114 program->GetTransformFeedbackVaryings(bucket);
12115 return error::kNoError;
12118 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
12119 return context_lost_reason_;
12122 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
12123 GLenum reset_status) const {
12124 switch (reset_status) {
12125 case GL_NO_ERROR:
12126 // TODO(kbr): improve the precision of the error code in this case.
12127 // Consider delegating to context for error code if MakeCurrent fails.
12128 return error::kUnknown;
12129 case GL_GUILTY_CONTEXT_RESET_ARB:
12130 return error::kGuilty;
12131 case GL_INNOCENT_CONTEXT_RESET_ARB:
12132 return error::kInnocent;
12133 case GL_UNKNOWN_CONTEXT_RESET_ARB:
12134 return error::kUnknown;
12137 NOTREACHED();
12138 return error::kUnknown;
12141 bool GLES2DecoderImpl::WasContextLost() const {
12142 return context_was_lost_;
12145 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
12146 return WasContextLost() && reset_by_robustness_extension_;
12149 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
12150 // Only lose the context once.
12151 if (WasContextLost())
12152 return;
12154 // Don't make GL calls in here, the context might not be current.
12155 context_lost_reason_ = reason;
12156 current_decoder_error_ = error::kLostContext;
12157 context_was_lost_ = true;
12160 bool GLES2DecoderImpl::CheckResetStatus() {
12161 DCHECK(!WasContextLost());
12162 DCHECK(context_->IsCurrent(NULL));
12164 if (IsRobustnessSupported()) {
12165 // If the reason for the call was a GL error, we can try to determine the
12166 // reset status more accurately.
12167 GLenum driver_status = glGetGraphicsResetStatusARB();
12168 if (driver_status == GL_NO_ERROR)
12169 return false;
12171 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
12172 << " context lost via ARB/EXT_robustness. Reset status = "
12173 << GLES2Util::GetStringEnum(driver_status);
12175 // Don't pretend we know which client was responsible.
12176 if (workarounds().use_virtualized_gl_contexts)
12177 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
12179 switch (driver_status) {
12180 case GL_GUILTY_CONTEXT_RESET_ARB:
12181 MarkContextLost(error::kGuilty);
12182 break;
12183 case GL_INNOCENT_CONTEXT_RESET_ARB:
12184 MarkContextLost(error::kInnocent);
12185 break;
12186 case GL_UNKNOWN_CONTEXT_RESET_ARB:
12187 MarkContextLost(error::kUnknown);
12188 break;
12189 default:
12190 NOTREACHED();
12191 return false;
12193 reset_by_robustness_extension_ = true;
12194 return true;
12196 return false;
12199 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
12200 uint32 immediate_data_size,
12201 const void* cmd_data) {
12202 return error::kUnknownCommand;
12205 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
12206 uint32 immediate_data_size,
12207 const void* cmd_data) {
12208 const gles2::cmds::WaitSyncPointCHROMIUM& c =
12209 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
12210 uint32 sync_point = c.sync_point;
12211 if (wait_sync_point_callback_.is_null())
12212 return error::kNoError;
12214 return wait_sync_point_callback_.Run(sync_point) ?
12215 error::kNoError : error::kDeferCommandUntilLater;
12218 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
12219 uint32 immediate_data_size,
12220 const void* cmd_data) {
12221 if (surface_->DeferDraws())
12222 return error::kDeferCommandUntilLater;
12223 if (!surface_->SetBackbufferAllocation(false))
12224 return error::kLostContext;
12225 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
12226 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
12227 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
12228 return error::kNoError;
12231 bool GLES2DecoderImpl::GenQueriesEXTHelper(
12232 GLsizei n, const GLuint* client_ids) {
12233 for (GLsizei ii = 0; ii < n; ++ii) {
12234 if (query_manager_->GetQuery(client_ids[ii])) {
12235 return false;
12238 query_manager_->GenQueries(n, client_ids);
12239 return true;
12242 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
12243 GLsizei n, const GLuint* client_ids) {
12244 for (GLsizei ii = 0; ii < n; ++ii) {
12245 query_manager_->RemoveQuery(client_ids[ii]);
12249 bool GLES2DecoderImpl::HasPendingQueries() const {
12250 return query_manager_.get() && query_manager_->HavePendingQueries();
12253 void GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
12254 if (!query_manager_.get())
12255 return;
12256 if (!query_manager_->ProcessPendingQueries(did_finish))
12257 current_decoder_error_ = error::kOutOfBounds;
12260 // Note that if there are no pending readpixels right now,
12261 // this function will call the callback immediately.
12262 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
12263 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
12264 pending_readpixel_fences_.back()->callbacks.push_back(callback);
12265 } else {
12266 callback.Run();
12270 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish) {
12271 // Note: |did_finish| guarantees that the GPU has passed the fence but
12272 // we cannot assume that GLFence::HasCompleted() will return true yet as
12273 // that's not guaranteed by all GLFence implementations.
12274 while (!pending_readpixel_fences_.empty() &&
12275 (did_finish ||
12276 pending_readpixel_fences_.front()->fence->HasCompleted())) {
12277 std::vector<base::Closure> callbacks =
12278 pending_readpixel_fences_.front()->callbacks;
12279 pending_readpixel_fences_.pop();
12280 for (size_t i = 0; i < callbacks.size(); i++) {
12281 callbacks[i].Run();
12286 bool GLES2DecoderImpl::HasMoreIdleWork() const {
12287 return !pending_readpixel_fences_.empty() ||
12288 gpu_tracer_->HasTracesToProcess();
12291 void GLES2DecoderImpl::PerformIdleWork() {
12292 gpu_tracer_->ProcessTraces();
12293 ProcessPendingReadPixels(false);
12296 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
12297 const void* cmd_data) {
12298 const gles2::cmds::BeginQueryEXT& c =
12299 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
12300 GLenum target = static_cast<GLenum>(c.target);
12301 GLuint client_id = static_cast<GLuint>(c.id);
12302 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
12303 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12305 switch (target) {
12306 case GL_COMMANDS_ISSUED_CHROMIUM:
12307 case GL_LATENCY_QUERY_CHROMIUM:
12308 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
12309 case GL_GET_ERROR_QUERY_CHROMIUM:
12310 break;
12311 case GL_COMMANDS_COMPLETED_CHROMIUM:
12312 if (!features().chromium_sync_query) {
12313 LOCAL_SET_GL_ERROR(
12314 GL_INVALID_OPERATION, "glBeginQueryEXT",
12315 "not enabled for commands completed queries");
12316 return error::kNoError;
12318 break;
12319 case GL_SAMPLES_PASSED:
12320 case GL_ANY_SAMPLES_PASSED:
12321 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
12322 if (!features().occlusion_query_boolean) {
12323 LOCAL_SET_GL_ERROR(
12324 GL_INVALID_OPERATION, "glBeginQueryEXT",
12325 "not enabled for occlusion queries");
12326 return error::kNoError;
12328 break;
12329 case GL_TIME_ELAPSED:
12330 if (!query_manager_->GPUTimingAvailable()) {
12331 LOCAL_SET_GL_ERROR(
12332 GL_INVALID_OPERATION, "glBeginQueryEXT",
12333 "not enabled for timing queries");
12334 return error::kNoError;
12336 break;
12337 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
12338 if (feature_info_->IsES3Enabled()) {
12339 break;
12341 // Fall through.
12342 default:
12343 LOCAL_SET_GL_ERROR(
12344 GL_INVALID_ENUM, "glBeginQueryEXT",
12345 "unknown query target");
12346 return error::kNoError;
12349 if (query_manager_->GetActiveQuery(target)) {
12350 LOCAL_SET_GL_ERROR(
12351 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
12352 return error::kNoError;
12355 if (client_id == 0) {
12356 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
12357 return error::kNoError;
12360 QueryManager::Query* query = query_manager_->GetQuery(client_id);
12361 if (!query) {
12362 if (!query_manager_->IsValidQuery(client_id)) {
12363 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12364 "glBeginQueryEXT",
12365 "id not made by glGenQueriesEXT");
12366 return error::kNoError;
12368 query = query_manager_->CreateQuery(
12369 target, client_id, sync_shm_id, sync_shm_offset);
12372 if (query->target() != target) {
12373 LOCAL_SET_GL_ERROR(
12374 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
12375 return error::kNoError;
12376 } else if (query->shm_id() != sync_shm_id ||
12377 query->shm_offset() != sync_shm_offset) {
12378 DLOG(ERROR) << "Shared memory used by query not the same as before";
12379 return error::kInvalidArguments;
12382 if (!query_manager_->BeginQuery(query)) {
12383 return error::kOutOfBounds;
12386 return error::kNoError;
12389 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
12390 const void* cmd_data) {
12391 const gles2::cmds::EndQueryEXT& c =
12392 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
12393 GLenum target = static_cast<GLenum>(c.target);
12394 uint32 submit_count = static_cast<GLuint>(c.submit_count);
12396 QueryManager::Query* query = query_manager_->GetActiveQuery(target);
12397 if (!query) {
12398 LOCAL_SET_GL_ERROR(
12399 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
12400 return error::kNoError;
12403 if (!query_manager_->EndQuery(query, submit_count)) {
12404 return error::kOutOfBounds;
12407 query_manager_->ProcessPendingTransferQueries();
12409 return error::kNoError;
12412 error::Error GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size,
12413 const void* cmd_data) {
12414 const gles2::cmds::QueryCounterEXT& c =
12415 *static_cast<const gles2::cmds::QueryCounterEXT*>(cmd_data);
12416 GLuint client_id = static_cast<GLuint>(c.id);
12417 GLenum target = static_cast<GLenum>(c.target);
12418 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
12419 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12420 uint32 submit_count = static_cast<GLuint>(c.submit_count);
12422 switch (target) {
12423 case GL_TIMESTAMP:
12424 if (!query_manager_->GPUTimingAvailable()) {
12425 LOCAL_SET_GL_ERROR(
12426 GL_INVALID_OPERATION, "glQueryCounterEXT",
12427 "not enabled for timing queries");
12428 return error::kNoError;
12430 break;
12431 default:
12432 LOCAL_SET_GL_ERROR(
12433 GL_INVALID_ENUM, "glQueryCounterEXT",
12434 "unknown query target");
12435 return error::kNoError;
12438 QueryManager::Query* query = query_manager_->GetQuery(client_id);
12439 if (!query) {
12440 if (!query_manager_->IsValidQuery(client_id)) {
12441 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12442 "glQueryCounterEXT",
12443 "id not made by glGenQueriesEXT");
12444 return error::kNoError;
12446 query = query_manager_->CreateQuery(
12447 target, client_id, sync_shm_id, sync_shm_offset);
12449 if (!query_manager_->QueryCounter(query, submit_count)) {
12450 return error::kOutOfBounds;
12453 return error::kNoError;
12456 error::Error GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
12457 uint32 immediate_data_size, const void* cmd_data) {
12458 const gles2::cmds::SetDisjointValueSyncCHROMIUM& c =
12459 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM*>(cmd_data);
12460 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
12461 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12463 query_manager_->SetDisjointSync(sync_shm_id, sync_shm_offset);
12464 return error::kNoError;
12467 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
12468 GLsizei n, const GLuint* client_ids) {
12469 for (GLsizei ii = 0; ii < n; ++ii) {
12470 if (GetVertexAttribManager(client_ids[ii])) {
12471 return false;
12475 if (!features().native_vertex_array_object) {
12476 // Emulated VAO
12477 for (GLsizei ii = 0; ii < n; ++ii) {
12478 CreateVertexAttribManager(client_ids[ii], 0, true);
12480 } else {
12481 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
12483 glGenVertexArraysOES(n, service_ids.get());
12484 for (GLsizei ii = 0; ii < n; ++ii) {
12485 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
12489 return true;
12492 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
12493 GLsizei n, const GLuint* client_ids) {
12494 for (GLsizei ii = 0; ii < n; ++ii) {
12495 VertexAttribManager* vao =
12496 GetVertexAttribManager(client_ids[ii]);
12497 if (vao && !vao->IsDeleted()) {
12498 if (state_.vertex_attrib_manager.get() == vao) {
12499 DoBindVertexArrayOES(0);
12501 RemoveVertexAttribManager(client_ids[ii]);
12506 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
12507 VertexAttribManager* vao = NULL;
12508 if (client_id != 0) {
12509 vao = GetVertexAttribManager(client_id);
12510 if (!vao) {
12511 // Unlike most Bind* methods, the spec explicitly states that VertexArray
12512 // only allows names that have been previously generated. As such, we do
12513 // not generate new names here.
12514 LOCAL_SET_GL_ERROR(
12515 GL_INVALID_OPERATION,
12516 "glBindVertexArrayOES", "bad vertex array id.");
12517 current_decoder_error_ = error::kNoError;
12518 return;
12520 } else {
12521 vao = state_.default_vertex_attrib_manager.get();
12524 // Only set the VAO state if it's changed
12525 if (state_.vertex_attrib_manager.get() != vao) {
12526 state_.vertex_attrib_manager = vao;
12527 if (!features().native_vertex_array_object) {
12528 EmulateVertexArrayState();
12529 } else {
12530 GLuint service_id = vao->service_id();
12531 glBindVertexArrayOES(service_id);
12536 // Used when OES_vertex_array_object isn't natively supported
12537 void GLES2DecoderImpl::EmulateVertexArrayState() {
12538 // Setup the Vertex attribute state
12539 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
12540 RestoreStateForAttrib(vv, true);
12543 // Setup the element buffer
12544 Buffer* element_array_buffer =
12545 state_.vertex_attrib_manager->element_array_buffer();
12546 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
12547 element_array_buffer ? element_array_buffer->service_id() : 0);
12550 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
12551 const VertexAttribManager* vao =
12552 GetVertexAttribManager(client_id);
12553 return vao && vao->IsValid() && !vao->IsDeleted();
12556 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id) {
12557 GLuint service_id = 0;
12558 return path_manager()->GetPath(client_id, &service_id) &&
12559 glIsPathNV(service_id) == GL_TRUE;
12562 #if defined(OS_MACOSX)
12563 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
12564 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
12565 texture_id);
12566 if (it != texture_to_io_surface_map_.end()) {
12567 // Found a previous IOSurface bound to this texture; release it.
12568 IOSurfaceRef surface = it->second;
12569 CFRelease(surface);
12570 texture_to_io_surface_map_.erase(it);
12573 #endif
12575 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12576 GLenum target, GLsizei width, GLsizei height,
12577 GLuint io_surface_id, GLuint plane) {
12578 #if defined(OS_MACOSX)
12579 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
12580 LOCAL_SET_GL_ERROR(
12581 GL_INVALID_OPERATION,
12582 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12583 return;
12586 if (target != GL_TEXTURE_RECTANGLE_ARB) {
12587 // This might be supported in the future, and if we could require
12588 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12589 // could delete a lot of code. For now, perform strict validation so we
12590 // know what's going on.
12591 LOCAL_SET_GL_ERROR(
12592 GL_INVALID_OPERATION,
12593 "glTexImageIOSurface2DCHROMIUM",
12594 "requires TEXTURE_RECTANGLE_ARB target");
12595 return;
12598 // Default target might be conceptually valid, but disallow it to avoid
12599 // accidents.
12600 TextureRef* texture_ref =
12601 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12602 if (!texture_ref) {
12603 LOCAL_SET_GL_ERROR(
12604 GL_INVALID_OPERATION,
12605 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12606 return;
12609 // Look up the new IOSurface. Note that because of asynchrony
12610 // between processes this might fail; during live resizing the
12611 // plugin process might allocate and release an IOSurface before
12612 // this process gets a chance to look it up. Hold on to any old
12613 // IOSurface in this case.
12614 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
12615 if (!surface) {
12616 LOCAL_SET_GL_ERROR(
12617 GL_INVALID_OPERATION,
12618 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12619 return;
12622 // Release any IOSurface previously bound to this texture.
12623 ReleaseIOSurfaceForTexture(texture_ref->service_id());
12625 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12626 texture_to_io_surface_map_.insert(
12627 std::make_pair(texture_ref->service_id(), surface));
12629 CGLContextObj context =
12630 static_cast<CGLContextObj>(context_->GetHandle());
12632 CGLError err = CGLTexImageIOSurface2D(
12633 context,
12634 target,
12635 GL_RGBA,
12636 width,
12637 height,
12638 GL_BGRA,
12639 GL_UNSIGNED_INT_8_8_8_8_REV,
12640 surface,
12641 plane);
12643 if (err != kCGLNoError) {
12644 LOCAL_SET_GL_ERROR(
12645 GL_INVALID_OPERATION,
12646 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12647 return;
12650 texture_manager()->SetLevelInfo(
12651 texture_ref, target, 0, GL_RGBA, width, height, 1, 0, GL_BGRA,
12652 GL_UNSIGNED_INT_8_8_8_8_REV, gfx::Rect(width, height));
12654 #else
12655 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12656 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12657 #endif
12660 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
12661 switch (internalformat) {
12662 case GL_R8:
12663 case GL_R8_SNORM:
12664 case GL_R16F:
12665 case GL_R32F:
12666 return GL_RED;
12667 case GL_R8UI:
12668 case GL_R8I:
12669 case GL_R16UI:
12670 case GL_R16I:
12671 case GL_R32UI:
12672 case GL_R32I:
12673 return GL_RED_INTEGER;
12674 case GL_RG8:
12675 case GL_RG8_SNORM:
12676 case GL_RG16F:
12677 case GL_RG32F:
12678 return GL_RG;
12679 case GL_RG8UI:
12680 case GL_RG8I:
12681 case GL_RG16UI:
12682 case GL_RG16I:
12683 case GL_RG32UI:
12684 case GL_RG32I:
12685 return GL_RG_INTEGER;
12686 case GL_ATC_RGB_AMD:
12687 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
12688 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
12689 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
12690 case GL_ETC1_RGB8_OES:
12691 case GL_RGB8:
12692 case GL_R11F_G11F_B10F:
12693 case GL_RGB565:
12694 case GL_RGB8_SNORM:
12695 case GL_RGB9_E5:
12696 case GL_RGB16F:
12697 case GL_RGB32F:
12698 return GL_RGB;
12699 case GL_RGB8UI:
12700 case GL_RGB8I:
12701 case GL_RGB16UI:
12702 case GL_RGB16I:
12703 case GL_RGB32UI:
12704 case GL_RGB32I:
12705 return GL_RGB_INTEGER;
12706 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
12707 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
12708 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
12709 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
12710 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
12711 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
12712 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
12713 case GL_RGBA8:
12714 case GL_SRGB8_ALPHA8:
12715 case GL_RGBA8_SNORM:
12716 case GL_RGBA4:
12717 case GL_RGB5_A1:
12718 case GL_RGB10_A2:
12719 case GL_RGBA16F:
12720 case GL_RGBA32F:
12721 return GL_RGBA;
12722 case GL_RGBA8UI:
12723 case GL_RGBA8I:
12724 case GL_RGB10_A2UI:
12725 case GL_RGBA16UI:
12726 case GL_RGBA16I:
12727 case GL_RGBA32UI:
12728 case GL_RGBA32I:
12729 return GL_RGBA_INTEGER;
12730 case GL_DEPTH_COMPONENT16:
12731 case GL_DEPTH_COMPONENT24:
12732 case GL_DEPTH_COMPONENT32F:
12733 return GL_DEPTH_COMPONENT;
12734 case GL_DEPTH24_STENCIL8:
12735 case GL_DEPTH32F_STENCIL8:
12736 return GL_DEPTH_STENCIL;
12737 case GL_LUMINANCE8_ALPHA8_EXT:
12738 return GL_LUMINANCE_ALPHA;
12739 case GL_LUMINANCE8_EXT:
12740 return GL_LUMINANCE;
12741 case GL_ALPHA8_EXT:
12742 return GL_ALPHA;
12743 case GL_ALPHA32F_EXT:
12744 return GL_ALPHA;
12745 case GL_LUMINANCE32F_EXT:
12746 return GL_LUMINANCE;
12747 case GL_LUMINANCE_ALPHA32F_EXT:
12748 return GL_LUMINANCE_ALPHA;
12749 case GL_ALPHA16F_EXT:
12750 return GL_ALPHA;
12751 case GL_LUMINANCE16F_EXT:
12752 return GL_LUMINANCE;
12753 case GL_LUMINANCE_ALPHA16F_EXT:
12754 return GL_LUMINANCE_ALPHA;
12755 case GL_BGRA8_EXT:
12756 return GL_BGRA_EXT;
12757 default:
12758 return GL_NONE;
12762 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12763 const char* function_name,
12764 GLenum target,
12765 TextureRef* source_texture_ref,
12766 TextureRef* dest_texture_ref,
12767 GLenum dest_internal_format) {
12768 if (!source_texture_ref || !dest_texture_ref) {
12769 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12770 return false;
12773 if (GL_TEXTURE_2D != target) {
12774 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12775 "invalid texture target");
12776 return false;
12779 Texture* source_texture = source_texture_ref->texture();
12780 Texture* dest_texture = dest_texture_ref->texture();
12781 if (source_texture == dest_texture) {
12782 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12783 "source and destination textures are the same");
12784 return false;
12787 if (dest_texture->target() != GL_TEXTURE_2D ||
12788 (source_texture->target() != GL_TEXTURE_2D &&
12789 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12790 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12791 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12792 "invalid texture target binding");
12793 return false;
12796 GLenum source_type = 0;
12797 GLenum source_internal_format = 0;
12798 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12799 &source_internal_format);
12801 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12802 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12803 // renderable on some platforms.
12804 bool valid_dest_format = dest_internal_format == GL_RGB ||
12805 dest_internal_format == GL_RGBA ||
12806 dest_internal_format == GL_BGRA_EXT;
12807 bool valid_source_format =
12808 source_internal_format == GL_R8 || source_internal_format == GL_ALPHA ||
12809 source_internal_format == GL_RGB || source_internal_format == GL_RGBA ||
12810 source_internal_format == GL_LUMINANCE ||
12811 source_internal_format == GL_LUMINANCE_ALPHA ||
12812 source_internal_format == GL_BGRA_EXT ||
12813 source_internal_format == GL_RGB_YCBCR_422_CHROMIUM;
12814 if (!valid_source_format || !valid_dest_format) {
12815 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12816 "invalid internal format");
12817 return false;
12819 return true;
12822 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12823 const char* function_name,
12824 GLenum target,
12825 TextureRef* source_texture_ref,
12826 TextureRef* dest_texture_ref) {
12827 if (!source_texture_ref || !dest_texture_ref) {
12828 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12829 return false;
12832 if (GL_TEXTURE_2D != target) {
12833 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12834 "invalid texture target");
12835 return false;
12838 Texture* source_texture = source_texture_ref->texture();
12839 Texture* dest_texture = dest_texture_ref->texture();
12840 if (source_texture == dest_texture) {
12841 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12842 "source and destination textures are the same");
12843 return false;
12846 if (dest_texture->target() != GL_TEXTURE_2D ||
12847 (source_texture->target() != GL_TEXTURE_2D &&
12848 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12849 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12850 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12851 "invalid texture target binding");
12852 return false;
12855 GLenum source_type = 0;
12856 GLenum source_internal_format = 0;
12857 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12858 &source_internal_format);
12860 bool valid_format =
12861 source_internal_format == GL_ATC_RGB_AMD ||
12862 source_internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD ||
12863 source_internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
12864 source_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ||
12865 source_internal_format == GL_ETC1_RGB8_OES;
12867 if (!valid_format) {
12868 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12869 "invalid internal format");
12870 return false;
12873 return true;
12876 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12877 GLenum target,
12878 GLuint source_id,
12879 GLuint dest_id,
12880 GLenum internal_format,
12881 GLenum dest_type,
12882 GLboolean unpack_flip_y,
12883 GLboolean unpack_premultiply_alpha,
12884 GLboolean unpack_unmultiply_alpha) {
12885 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12887 TextureRef* source_texture_ref = GetTexture(source_id);
12888 TextureRef* dest_texture_ref = GetTexture(dest_id);
12889 Texture* source_texture = source_texture_ref->texture();
12890 Texture* dest_texture = dest_texture_ref->texture();
12891 int source_width = 0;
12892 int source_height = 0;
12893 gfx::GLImage* image =
12894 source_texture->GetLevelImage(source_texture->target(), 0);
12895 if (image) {
12896 gfx::Size size = image->GetSize();
12897 source_width = size.width();
12898 source_height = size.height();
12899 if (source_width <= 0 || source_height <= 0) {
12900 LOCAL_SET_GL_ERROR(
12901 GL_INVALID_VALUE,
12902 "glCopyTextureChromium", "invalid image size");
12903 return;
12905 } else {
12906 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12907 &source_width, &source_height, nullptr)) {
12908 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12909 "glCopyTextureChromium",
12910 "source texture has no level 0");
12911 return;
12914 // Check that this type of texture is allowed.
12915 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12916 source_width, source_height, 1)) {
12917 LOCAL_SET_GL_ERROR(
12918 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
12919 return;
12923 GLenum source_type = 0;
12924 GLenum source_internal_format = 0;
12925 source_texture->GetLevelType(
12926 source_texture->target(), 0, &source_type, &source_internal_format);
12928 if (dest_texture->IsImmutable()) {
12929 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
12930 "texture is immutable");
12931 return;
12934 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
12935 source_texture_ref, dest_texture_ref,
12936 internal_format)) {
12937 return;
12940 // Clear the source texture if necessary.
12941 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12942 source_texture->target(), 0)) {
12943 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
12944 "dimensions too big");
12945 return;
12948 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12949 // needed because it takes 10s of milliseconds to initialize.
12950 if (!copy_texture_CHROMIUM_.get()) {
12951 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12952 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12953 copy_texture_CHROMIUM_->Initialize(this);
12954 RestoreCurrentFramebufferBindings();
12955 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12956 return;
12959 GLenum dest_type_previous = dest_type;
12960 GLenum dest_internal_format = internal_format;
12961 int dest_width = 0;
12962 int dest_height = 0;
12963 bool dest_level_defined = dest_texture->GetLevelSize(
12964 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12966 if (dest_level_defined) {
12967 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
12968 &dest_internal_format);
12971 // Resize the destination texture to the dimensions of the source texture.
12972 if (!dest_level_defined || dest_width != source_width ||
12973 dest_height != source_height ||
12974 dest_internal_format != internal_format ||
12975 dest_type_previous != dest_type) {
12976 // Ensure that the glTexImage2D succeeds.
12977 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12978 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12979 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
12980 0, internal_format, dest_type, NULL);
12981 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12982 if (error != GL_NO_ERROR) {
12983 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12984 return;
12987 texture_manager()->SetLevelInfo(
12988 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
12989 source_height, 1, 0, internal_format, dest_type,
12990 gfx::Rect(source_width, source_height));
12991 } else {
12992 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12993 true);
12996 ScopedModifyPixels modify(dest_texture_ref);
12998 // Try using GLImage::CopyTexSubImage when possible.
12999 bool unpack_premultiply_alpha_change =
13000 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
13001 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
13002 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
13003 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
13004 gfx::Rect(0, 0, source_width, source_height))) {
13005 return;
13009 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
13011 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
13012 // before presenting.
13013 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
13014 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
13015 // instead of using kIdentityMatrix crbug.com/226218.
13016 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
13017 this, source_texture->target(), source_texture->service_id(),
13018 dest_texture->service_id(), source_width, source_height,
13019 unpack_flip_y == GL_TRUE,
13020 unpack_premultiply_alpha == GL_TRUE,
13021 unpack_unmultiply_alpha == GL_TRUE,
13022 kIdentityMatrix);
13023 } else {
13024 copy_texture_CHROMIUM_->DoCopyTexture(
13025 this, source_texture->target(), source_texture->service_id(),
13026 source_internal_format, dest_texture->service_id(), internal_format,
13027 source_width, source_height,
13028 unpack_flip_y == GL_TRUE,
13029 unpack_premultiply_alpha == GL_TRUE,
13030 unpack_unmultiply_alpha == GL_TRUE);
13033 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13036 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
13037 GLenum target,
13038 GLuint source_id,
13039 GLuint dest_id,
13040 GLint xoffset,
13041 GLint yoffset,
13042 GLint x,
13043 GLint y,
13044 GLsizei width,
13045 GLsizei height,
13046 GLboolean unpack_flip_y,
13047 GLboolean unpack_premultiply_alpha,
13048 GLboolean unpack_unmultiply_alpha) {
13049 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
13051 TextureRef* source_texture_ref = GetTexture(source_id);
13052 TextureRef* dest_texture_ref = GetTexture(dest_id);
13053 Texture* source_texture = source_texture_ref->texture();
13054 Texture* dest_texture = dest_texture_ref->texture();
13055 int source_width = 0;
13056 int source_height = 0;
13057 gfx::GLImage* image =
13058 source_texture->GetLevelImage(source_texture->target(), 0);
13059 if (image) {
13060 gfx::Size size = image->GetSize();
13061 source_width = size.width();
13062 source_height = size.height();
13063 if (source_width <= 0 || source_height <= 0) {
13064 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
13065 "invalid image size");
13066 return;
13068 } else {
13069 if (!source_texture->GetLevelSize(source_texture->target(), 0,
13070 &source_width, &source_height, nullptr)) {
13071 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
13072 "source texture has no level 0");
13073 return;
13076 // Check that this type of texture is allowed.
13077 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
13078 source_width, source_height, 1)) {
13079 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
13080 "source texture bad dimensions");
13081 return;
13085 GLenum source_type = 0;
13086 GLenum source_internal_format = 0;
13087 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
13088 &source_internal_format);
13089 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
13090 width, height, 1)) {
13091 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
13092 "source texture bad dimensions.");
13093 return;
13096 GLenum dest_type = 0;
13097 GLenum dest_internal_format = 0;
13098 bool dest_level_defined = dest_texture->GetLevelType(
13099 dest_texture->target(), 0, &dest_type, &dest_internal_format);
13100 if (!dest_level_defined) {
13101 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
13102 "destination texture is not defined");
13103 return;
13105 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
13106 yoffset, 0, width, height, 1)) {
13107 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
13108 "destination texture bad dimensions.");
13109 return;
13112 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
13113 source_texture_ref, dest_texture_ref,
13114 dest_internal_format)) {
13115 return;
13118 // Clear the source texture if necessary.
13119 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
13120 source_texture->target(), 0)) {
13121 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
13122 "source texture dimensions too big");
13123 return;
13126 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13127 // needed because it takes 10s of milliseconds to initialize.
13128 if (!copy_texture_CHROMIUM_.get()) {
13129 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
13130 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
13131 copy_texture_CHROMIUM_->Initialize(this);
13132 RestoreCurrentFramebufferBindings();
13133 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
13134 return;
13137 int dest_width = 0;
13138 int dest_height = 0;
13139 bool ok = dest_texture->GetLevelSize(
13140 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
13141 DCHECK(ok);
13142 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
13143 height != dest_height) {
13144 gfx::Rect cleared_rect;
13145 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
13146 gfx::Rect(xoffset, yoffset, width, height),
13147 &cleared_rect)) {
13148 DCHECK_GE(cleared_rect.size().GetArea(),
13149 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
13150 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
13151 cleared_rect);
13152 } else {
13153 // Otherwise clear part of texture level that is not already cleared.
13154 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
13155 0)) {
13156 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
13157 "destination texture dimensions too big");
13158 return;
13161 } else {
13162 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
13163 true);
13166 ScopedModifyPixels modify(dest_texture_ref);
13168 // Try using GLImage::CopyTexSubImage when possible.
13169 bool unpack_premultiply_alpha_change =
13170 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
13171 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
13172 ScopedTextureBinder binder(
13173 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
13174 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
13175 gfx::Rect(x, y, width, height))) {
13176 return;
13180 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
13182 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13183 // crbug.com/226218.
13184 copy_texture_CHROMIUM_->DoCopySubTexture(
13185 this, source_texture->target(), source_texture->service_id(),
13186 source_internal_format, dest_texture->service_id(), dest_internal_format,
13187 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
13188 source_width, source_height,
13189 unpack_flip_y == GL_TRUE,
13190 unpack_premultiply_alpha == GL_TRUE,
13191 unpack_unmultiply_alpha == GL_TRUE);
13193 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13196 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target,
13197 GLuint source_id,
13198 GLuint dest_id) {
13199 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
13201 TextureRef* source_texture_ref = GetTexture(source_id);
13202 TextureRef* dest_texture_ref = GetTexture(dest_id);
13203 Texture* source_texture = source_texture_ref->texture();
13204 Texture* dest_texture = dest_texture_ref->texture();
13205 int source_width = 0;
13206 int source_height = 0;
13207 gfx::GLImage* image =
13208 source_texture->GetLevelImage(source_texture->target(), 0);
13209 if (image) {
13210 gfx::Size size = image->GetSize();
13211 source_width = size.width();
13212 source_height = size.height();
13213 if (source_width <= 0 || source_height <= 0) {
13214 LOCAL_SET_GL_ERROR(
13215 GL_INVALID_VALUE,
13216 "glCompressedCopyTextureCHROMIUM", "invalid image size");
13217 return;
13219 } else {
13220 if (!source_texture->GetLevelSize(source_texture->target(), 0,
13221 &source_width, &source_height, nullptr)) {
13222 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
13223 "glCompressedCopyTextureCHROMIUM",
13224 "source texture has no level 0");
13225 return;
13228 // Check that this type of texture is allowed.
13229 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
13230 source_width, source_height, 1)) {
13231 LOCAL_SET_GL_ERROR(
13232 GL_INVALID_VALUE, "glCompressedCopyTextureCHROMIUM",
13233 "Bad dimensions");
13234 return;
13238 GLenum source_type = 0;
13239 GLenum source_internal_format = 0;
13240 source_texture->GetLevelType(
13241 source_texture->target(), 0, &source_type, &source_internal_format);
13243 if (dest_texture->IsImmutable()) {
13244 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13245 "glCompressedCopyTextureCHROMIUM",
13246 "texture is immutable");
13247 return;
13250 if (!ValidateCompressedCopyTextureCHROMIUM(
13251 "glCompressedCopyTextureCHROMIUM",
13252 target,
13253 source_texture_ref, dest_texture_ref)) {
13254 return;
13257 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13258 // needed because it takes 10s of milliseconds to initialize.
13259 if (!copy_texture_CHROMIUM_.get()) {
13260 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
13261 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
13262 copy_texture_CHROMIUM_->Initialize(this);
13263 RestoreCurrentFramebufferBindings();
13264 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
13265 return;
13268 // Clear the source texture if necessary.
13269 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
13270 source_texture->target(), 0)) {
13271 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopyTextureCHROMIUM",
13272 "dimensions too big");
13273 return;
13276 ScopedTextureBinder binder(
13277 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
13279 ScopedModifyPixels modify(dest_texture_ref);
13281 // Try using GLImage::CopyTexImage when possible.
13282 if (image) {
13283 GLenum dest_type = 0;
13284 GLenum dest_internal_format = 0;
13285 int dest_width = 0;
13286 int dest_height = 0;
13287 bool dest_level_defined = dest_texture->GetLevelSize(
13288 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
13290 if (dest_level_defined) {
13291 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
13292 &dest_internal_format);
13295 // Resize the destination texture to the dimensions of the source texture.
13296 if (!dest_level_defined || dest_width != source_width ||
13297 dest_height != source_height ||
13298 dest_internal_format != source_internal_format) {
13299 GLsizei source_size = 0;
13301 bool did_get_size = GetCompressedTexSizeInBytes(
13302 "glCompressedCopyTextureCHROMIUM", source_width, source_height,
13303 1, source_internal_format, &source_size);
13304 DCHECK(did_get_size);
13306 // Ensure that the glCompressedTexImage2D succeeds.
13307 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13308 glCompressedTexImage2D(GL_TEXTURE_2D, 0, source_internal_format,
13309 source_width, source_height, 0, source_size,
13310 NULL);
13311 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
13312 if (error != GL_NO_ERROR) {
13313 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
13314 return;
13317 texture_manager()->SetLevelInfo(
13318 dest_texture_ref, GL_TEXTURE_2D, 0, source_internal_format,
13319 source_width, source_height, 1, 0, source_internal_format,
13320 source_type, gfx::Rect(source_width, source_height));
13321 } else {
13322 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
13323 true);
13326 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
13327 gfx::Rect(0, 0, source_width, source_height))) {
13328 return;
13332 TRACE_EVENT0(
13333 "gpu",
13334 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
13336 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
13338 // As a fallback, copy into a non-compressed GL_RGBA texture.
13339 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13340 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height,
13341 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
13342 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
13343 if (error != GL_NO_ERROR) {
13344 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
13345 return;
13348 texture_manager()->SetLevelInfo(
13349 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, source_width,
13350 source_height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13351 gfx::Rect(source_width, source_height));
13353 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
13354 // before presenting.
13355 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
13356 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
13357 // instead of using kIdentityMatrix crbug.com/226218.
13358 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
13359 this, source_texture->target(), source_texture->service_id(),
13360 dest_texture->service_id(), source_width, source_height,
13361 false, false, false, kIdentityMatrix);
13362 } else {
13363 copy_texture_CHROMIUM_->DoCopyTexture(
13364 this, source_texture->target(), source_texture->service_id(),
13365 source_internal_format, dest_texture->service_id(), GL_RGBA,
13366 source_width, source_height, false, false, false);
13369 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13372 void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target,
13373 GLuint source_id,
13374 GLuint dest_id,
13375 GLint xoffset,
13376 GLint yoffset,
13377 GLint x,
13378 GLint y,
13379 GLsizei width,
13380 GLsizei height) {
13381 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM");
13383 TextureRef* source_texture_ref = GetTexture(source_id);
13384 TextureRef* dest_texture_ref = GetTexture(dest_id);
13385 Texture* source_texture = source_texture_ref->texture();
13386 Texture* dest_texture = dest_texture_ref->texture();
13387 int source_width = 0;
13388 int source_height = 0;
13389 gfx::GLImage* image =
13390 source_texture->GetLevelImage(source_texture->target(), 0);
13391 if (image) {
13392 gfx::Size size = image->GetSize();
13393 source_width = size.width();
13394 source_height = size.height();
13395 if (source_width <= 0 || source_height <= 0) {
13396 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
13397 "invalid image size");
13398 return;
13400 } else {
13401 if (!source_texture->GetLevelSize(source_texture->target(), 0,
13402 &source_width, &source_height, nullptr)) {
13403 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
13404 "source texture has no level 0");
13405 return;
13408 // Check that this type of texture is allowed.
13409 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
13410 source_width, source_height, 1)) {
13411 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
13412 "source texture bad dimensions");
13413 return;
13417 GLenum source_type = 0;
13418 GLenum source_internal_format = 0;
13419 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
13420 &source_internal_format);
13421 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
13422 width, height, 1)) {
13423 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
13424 "source texture bad dimensions.");
13425 return;
13428 GLenum dest_type = 0;
13429 GLenum dest_internal_format = 0;
13430 bool dest_level_defined = dest_texture->GetLevelType(
13431 dest_texture->target(), 0, &dest_type, &dest_internal_format);
13432 if (!dest_level_defined) {
13433 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13434 "glCompressedCopySubTextureCHROMIUM",
13435 "destination texture is not defined");
13436 return;
13438 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
13439 yoffset, 0, width, height, 1)) {
13440 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
13441 "destination texture bad dimensions.");
13442 return;
13445 if (!ValidateCompressedCopyTextureCHROMIUM(
13446 "glCompressedCopySubTextureCHROMIUM", target, source_texture_ref,
13447 dest_texture_ref)) {
13448 return;
13451 if (!ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
13452 source_texture->target(), 0, x, y, 0,
13453 width, height, 1,
13454 source_internal_format,
13455 source_texture) ||
13456 !ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
13457 dest_texture->target(), 0,
13458 xoffset, yoffset, 0, width, height, 1,
13459 dest_internal_format,
13460 dest_texture)) {
13461 return;
13464 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13465 // needed because it takes 10s of milliseconds to initialize.
13466 if (!copy_texture_CHROMIUM_.get()) {
13467 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopySubTextureCHROMIUM");
13468 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
13469 copy_texture_CHROMIUM_->Initialize(this);
13470 RestoreCurrentFramebufferBindings();
13471 if (LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM") !=
13472 GL_NO_ERROR) {
13473 return;
13477 // Clear the source texture if necessary.
13478 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
13479 source_texture->target(), 0)) {
13480 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopySubTextureCHROMIUM",
13481 "source texture dimensions too big");
13482 return;
13485 int dest_width = 0;
13486 int dest_height = 0;
13487 bool ok = dest_texture->GetLevelSize(
13488 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
13489 DCHECK(ok);
13490 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
13491 height != dest_height) {
13492 gfx::Rect cleared_rect;
13493 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
13494 gfx::Rect(xoffset, yoffset, width, height),
13495 &cleared_rect)) {
13496 DCHECK_GE(cleared_rect.size().GetArea(),
13497 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
13498 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
13499 cleared_rect);
13500 } else {
13501 // Otherwise clear part of texture level that is not already cleared.
13502 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
13503 0)) {
13504 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY,
13505 "glCompressedCopySubTextureCHROMIUM",
13506 "destination texture dimensions too big");
13507 return;
13510 } else {
13511 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
13512 true);
13515 ScopedTextureBinder binder(
13516 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
13518 ScopedModifyPixels modify(dest_texture_ref);
13520 // Try using GLImage::CopyTexSubImage when possible.
13521 if (image) {
13522 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
13523 gfx::Rect(x, y, width, height))) {
13524 return;
13528 TRACE_EVENT0(
13529 "gpu",
13530 "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback");
13532 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
13534 // As a fallback, copy into a non-compressed GL_RGBA texture.
13535 if (dest_internal_format != GL_RGBA) {
13536 // To preserve the contents of the original destination texture we must
13537 // first copy the original destination texture to a temporary storage, then
13538 // copy it back to the original destination texture.
13539 GLuint tmp_service_id;
13540 glGenTextures(1, &tmp_service_id);
13541 DCHECK_NE(0u, tmp_service_id);
13543 glBindTexture(GL_TEXTURE_2D, tmp_service_id);
13545 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13546 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA,
13547 GL_UNSIGNED_BYTE, NULL);
13548 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13549 if (error != GL_NO_ERROR)
13550 return;
13552 copy_texture_CHROMIUM_->DoCopyTexture(
13553 this, dest_texture->target(), dest_texture->service_id(),
13554 dest_internal_format, tmp_service_id, GL_RGBA,
13555 dest_width, dest_height, false, false, false);
13557 // Redefine destination texture to use RGBA.
13558 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
13559 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13560 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA,
13561 GL_UNSIGNED_BYTE, NULL);
13562 error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13563 if (error != GL_NO_ERROR)
13564 return;
13566 texture_manager()->SetLevelInfo(
13567 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height,
13568 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(dest_width, dest_height));
13570 copy_texture_CHROMIUM_->DoCopyTexture(
13571 this, GL_TEXTURE_2D, tmp_service_id, GL_RGBA,
13572 dest_texture->service_id(), GL_RGBA,
13573 dest_width, dest_height, false, false, false);
13575 glDeleteTextures(1, &tmp_service_id);
13578 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13579 // crbug.com/226218.
13580 copy_texture_CHROMIUM_->DoCopySubTexture(
13581 this, source_texture->target(), source_texture->service_id(),
13582 source_internal_format, dest_texture->service_id(), GL_RGBA,
13583 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
13584 source_width, source_height, false, false, false);
13586 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13589 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
13590 switch (internalformat) {
13591 case GL_R8:
13592 return GL_UNSIGNED_BYTE;
13593 case GL_R8_SNORM:
13594 return GL_BYTE;
13595 case GL_R16F:
13596 return GL_HALF_FLOAT;
13597 case GL_R32F:
13598 return GL_FLOAT;
13599 case GL_R8UI:
13600 return GL_UNSIGNED_BYTE;
13601 case GL_R8I:
13602 return GL_BYTE;
13603 case GL_R16UI:
13604 return GL_UNSIGNED_SHORT;
13605 case GL_R16I:
13606 return GL_SHORT;
13607 case GL_R32UI:
13608 return GL_UNSIGNED_INT;
13609 case GL_R32I:
13610 return GL_INT;
13611 case GL_RG8:
13612 return GL_UNSIGNED_BYTE;
13613 case GL_RG8_SNORM:
13614 return GL_BYTE;
13615 case GL_RG16F:
13616 return GL_HALF_FLOAT;
13617 case GL_RG32F:
13618 return GL_FLOAT;
13619 case GL_RG8UI:
13620 return GL_UNSIGNED_BYTE;
13621 case GL_RG8I:
13622 return GL_BYTE;
13623 case GL_RG16UI:
13624 return GL_UNSIGNED_SHORT;
13625 case GL_RG16I:
13626 return GL_SHORT;
13627 case GL_RG32UI:
13628 return GL_UNSIGNED_INT;
13629 case GL_RG32I:
13630 return GL_INT;
13631 case GL_RGB8:
13632 case GL_SRGB8:
13633 return GL_UNSIGNED_BYTE;
13634 case GL_R11F_G11F_B10F:
13635 return GL_UNSIGNED_INT_10F_11F_11F_REV;
13636 case GL_RGB565:
13637 return GL_UNSIGNED_SHORT_5_6_5;
13638 case GL_RGB8_SNORM:
13639 return GL_BYTE;
13640 case GL_RGB9_E5:
13641 return GL_UNSIGNED_INT_5_9_9_9_REV;
13642 case GL_RGB16F:
13643 return GL_HALF_FLOAT;
13644 case GL_RGB32F:
13645 return GL_FLOAT;
13646 case GL_RGB8UI:
13647 return GL_UNSIGNED_BYTE;
13648 case GL_RGB8I:
13649 return GL_BYTE;
13650 case GL_RGB16UI:
13651 return GL_UNSIGNED_SHORT;
13652 case GL_RGB16I:
13653 return GL_SHORT;
13654 case GL_RGB32UI:
13655 return GL_UNSIGNED_INT;
13656 case GL_RGB32I:
13657 return GL_INT;
13658 case GL_RGBA8:
13659 return GL_UNSIGNED_BYTE;
13660 case GL_SRGB8_ALPHA8:
13661 return GL_UNSIGNED_BYTE;
13662 case GL_RGBA8_SNORM:
13663 return GL_BYTE;
13664 case GL_RGBA4:
13665 return GL_UNSIGNED_SHORT_4_4_4_4;
13666 case GL_RGB10_A2:
13667 return GL_UNSIGNED_INT_2_10_10_10_REV;
13668 case GL_RGB5_A1:
13669 return GL_UNSIGNED_SHORT_5_5_5_1;
13670 case GL_RGBA16F:
13671 return GL_HALF_FLOAT;
13672 case GL_RGBA32F:
13673 return GL_FLOAT;
13674 case GL_RGBA8UI:
13675 return GL_UNSIGNED_BYTE;
13676 case GL_RGBA8I:
13677 return GL_BYTE;
13678 case GL_RGB10_A2UI:
13679 return GL_UNSIGNED_INT_2_10_10_10_REV;
13680 case GL_RGBA16UI:
13681 return GL_UNSIGNED_SHORT;
13682 case GL_RGBA16I:
13683 return GL_SHORT;
13684 case GL_RGBA32I:
13685 return GL_INT;
13686 case GL_RGBA32UI:
13687 return GL_UNSIGNED_INT;
13688 case GL_DEPTH_COMPONENT16:
13689 return GL_UNSIGNED_SHORT;
13690 case GL_DEPTH_COMPONENT24:
13691 return GL_UNSIGNED_INT;
13692 case GL_DEPTH_COMPONENT32F:
13693 return GL_FLOAT;
13694 case GL_DEPTH24_STENCIL8:
13695 return GL_UNSIGNED_INT_24_8;
13696 case GL_DEPTH32F_STENCIL8:
13697 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
13698 case GL_LUMINANCE8_ALPHA8_EXT:
13699 return GL_UNSIGNED_BYTE;
13700 case GL_LUMINANCE8_EXT:
13701 return GL_UNSIGNED_BYTE;
13702 case GL_ALPHA8_EXT:
13703 return GL_UNSIGNED_BYTE;
13704 case GL_ALPHA32F_EXT:
13705 return GL_FLOAT;
13706 case GL_LUMINANCE32F_EXT:
13707 return GL_FLOAT;
13708 case GL_LUMINANCE_ALPHA32F_EXT:
13709 return GL_FLOAT;
13710 case GL_ALPHA16F_EXT:
13711 return GL_HALF_FLOAT_OES;
13712 case GL_LUMINANCE16F_EXT:
13713 return GL_HALF_FLOAT_OES;
13714 case GL_LUMINANCE_ALPHA16F_EXT:
13715 return GL_HALF_FLOAT_OES;
13716 case GL_BGRA8_EXT:
13717 return GL_UNSIGNED_BYTE;
13718 default:
13719 return GL_NONE;
13723 void GLES2DecoderImpl::DoTexStorage2DEXT(
13724 GLenum target,
13725 GLint levels,
13726 GLenum internal_format,
13727 GLsizei width,
13728 GLsizei height) {
13729 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
13730 "width", width, "height", height);
13731 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
13732 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
13733 LOCAL_SET_GL_ERROR(
13734 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
13735 return;
13737 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13738 &state_, target);
13739 if (!texture_ref) {
13740 LOCAL_SET_GL_ERROR(
13741 GL_INVALID_OPERATION,
13742 "glTexStorage2DEXT", "unknown texture for target");
13743 return;
13745 Texture* texture = texture_ref->texture();
13746 if (texture->IsAttachedToFramebuffer()) {
13747 framebuffer_state_.clear_state_dirty = true;
13749 if (texture->IsImmutable()) {
13750 LOCAL_SET_GL_ERROR(
13751 GL_INVALID_OPERATION,
13752 "glTexStorage2DEXT", "texture is immutable");
13753 return;
13756 GLenum format = ExtractFormatFromStorageFormat(internal_format);
13757 GLenum type = ExtractTypeFromStorageFormat(internal_format);
13760 GLsizei level_width = width;
13761 GLsizei level_height = height;
13762 uint32 estimated_size = 0;
13763 for (int ii = 0; ii < levels; ++ii) {
13764 uint32 level_size = 0;
13765 if (!GLES2Util::ComputeImageDataSizes(
13766 level_width, level_height, 1, format, type, state_.unpack_alignment,
13767 &estimated_size, NULL, NULL) ||
13768 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
13769 LOCAL_SET_GL_ERROR(
13770 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
13771 return;
13773 level_width = std::max(1, level_width >> 1);
13774 level_height = std::max(1, level_height >> 1);
13776 if (!EnsureGPUMemoryAvailable(estimated_size)) {
13777 LOCAL_SET_GL_ERROR(
13778 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
13779 return;
13783 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13784 glTexStorage2DEXT(target, levels, internal_format, width, height);
13785 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13786 if (error == GL_NO_ERROR) {
13787 GLsizei level_width = width;
13788 GLsizei level_height = height;
13790 GLenum cur_format = feature_info_->IsES3Enabled() ?
13791 internal_format : format;
13792 for (int ii = 0; ii < levels; ++ii) {
13793 if (target == GL_TEXTURE_CUBE_MAP) {
13794 for (int jj = 0; jj < 6; ++jj) {
13795 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj;
13796 texture_manager()->SetLevelInfo(texture_ref, face, ii, cur_format,
13797 level_width, level_height, 1, 0,
13798 format, type, gfx::Rect());
13800 } else {
13801 texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format,
13802 level_width, level_height, 1, 0,
13803 format, type, gfx::Rect());
13805 level_width = std::max(1, level_width >> 1);
13806 level_height = std::max(1, level_height >> 1);
13808 texture->SetImmutable(true);
13812 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13813 uint32 immediate_data_size,
13814 const void* cmd_data) {
13815 return error::kUnknownCommand;
13818 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
13819 const GLbyte* data) {
13820 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13821 "context", logger_.GetLogPrefix(),
13822 "mailbox[0]", static_cast<unsigned char>(data[0]));
13824 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13825 &state_, target);
13826 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
13829 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
13830 GLenum target, const GLbyte* data) {
13831 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13832 "context", logger_.GetLogPrefix(),
13833 "mailbox[0]", static_cast<unsigned char>(data[0]));
13835 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
13836 target, data);
13839 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
13840 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
13841 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13842 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
13843 "mailbox that was not generated by "
13844 "GenMailboxCHROMIUM.";
13846 if (!texture_ref) {
13847 LOCAL_SET_GL_ERROR(
13848 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
13849 return;
13852 Texture* produced = texture_manager()->Produce(texture_ref);
13853 if (!produced) {
13854 LOCAL_SET_GL_ERROR(
13855 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
13856 return;
13859 if (produced->target() != target) {
13860 LOCAL_SET_GL_ERROR(
13861 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
13862 return;
13865 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
13868 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
13869 const GLbyte* data) {
13870 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13871 "context", logger_.GetLogPrefix(),
13872 "mailbox[0]", static_cast<unsigned char>(data[0]));
13873 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13874 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13875 "mailbox that was not generated by "
13876 "GenMailboxCHROMIUM.";
13878 scoped_refptr<TextureRef> texture_ref =
13879 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13880 if (!texture_ref.get()) {
13881 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13882 "glConsumeTextureCHROMIUM",
13883 "unknown texture for target");
13884 return;
13886 GLuint client_id = texture_ref->client_id();
13887 if (!client_id) {
13888 LOCAL_SET_GL_ERROR(
13889 GL_INVALID_OPERATION,
13890 "glConsumeTextureCHROMIUM", "unknown texture for target");
13891 return;
13893 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13894 if (!texture) {
13895 LOCAL_SET_GL_ERROR(
13896 GL_INVALID_OPERATION,
13897 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13898 return;
13900 if (texture->target() != target) {
13901 LOCAL_SET_GL_ERROR(
13902 GL_INVALID_OPERATION,
13903 "glConsumeTextureCHROMIUM", "invalid target");
13904 return;
13907 DeleteTexturesHelper(1, &client_id);
13908 texture_ref = texture_manager()->Consume(client_id, texture);
13909 glBindTexture(target, texture_ref->service_id());
13911 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
13912 unit.bind_target = target;
13913 switch (target) {
13914 case GL_TEXTURE_2D:
13915 unit.bound_texture_2d = texture_ref;
13916 break;
13917 case GL_TEXTURE_CUBE_MAP:
13918 unit.bound_texture_cube_map = texture_ref;
13919 break;
13920 case GL_TEXTURE_EXTERNAL_OES:
13921 unit.bound_texture_external_oes = texture_ref;
13922 break;
13923 case GL_TEXTURE_RECTANGLE_ARB:
13924 unit.bound_texture_rectangle_arb = texture_ref;
13925 break;
13926 default:
13927 NOTREACHED(); // Validation should prevent us getting here.
13928 break;
13932 void GLES2DecoderImpl::EnsureTextureForClientId(
13933 GLenum target,
13934 GLuint client_id) {
13935 TextureRef* texture_ref = GetTexture(client_id);
13936 if (!texture_ref) {
13937 GLuint service_id;
13938 glGenTextures(1, &service_id);
13939 DCHECK_NE(0u, service_id);
13940 texture_ref = CreateTexture(client_id, service_id);
13941 texture_manager()->SetTarget(texture_ref, target);
13942 glBindTexture(target, service_id);
13943 RestoreCurrentTextureBindings(&state_, target);
13947 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13948 // provided is associated with a service_id/TextureRef for consistency, even if
13949 // the resulting texture is incomplete.
13950 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13951 uint32_t immediate_data_size,
13952 const void* cmd_data) {
13953 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
13954 *static_cast<
13955 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
13956 cmd_data);
13957 GLenum target = static_cast<GLenum>(c.target);
13958 uint32_t data_size;
13959 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
13960 return error::kOutOfBounds;
13962 if (data_size > immediate_data_size) {
13963 return error::kOutOfBounds;
13965 const GLbyte* mailbox =
13966 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
13967 if (!validators_->texture_bind_target.IsValid(target)) {
13968 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13969 "glCreateAndConsumeTextureCHROMIUM", target, "target");
13970 return error::kNoError;
13972 if (mailbox == NULL) {
13973 return error::kOutOfBounds;
13975 uint32_t client_id = c.client_id;
13976 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
13977 return error::kNoError;
13980 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
13981 const GLbyte* data, GLuint client_id) {
13982 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13983 "context", logger_.GetLogPrefix(),
13984 "mailbox[0]", static_cast<unsigned char>(data[0]));
13985 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13986 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13987 "passed a mailbox that was not "
13988 "generated by GenMailboxCHROMIUM.";
13990 TextureRef* texture_ref = GetTexture(client_id);
13991 if (texture_ref) {
13992 // No need to call EnsureTextureForClientId here, the client_id already has
13993 // an associated texture.
13994 LOCAL_SET_GL_ERROR(
13995 GL_INVALID_OPERATION,
13996 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13997 return;
13999 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
14000 if (!texture) {
14001 EnsureTextureForClientId(target, client_id);
14002 LOCAL_SET_GL_ERROR(
14003 GL_INVALID_OPERATION,
14004 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
14005 return;
14008 if (texture->target() != target) {
14009 EnsureTextureForClientId(target, client_id);
14010 LOCAL_SET_GL_ERROR(
14011 GL_INVALID_OPERATION,
14012 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
14013 return;
14016 texture_ref = texture_manager()->Consume(client_id, texture);
14019 void GLES2DecoderImpl::DoApplyScreenSpaceAntialiasingCHROMIUM() {
14020 // Apply CMAA(Conservative Morphological Anti-Aliasing) algorithm to the
14021 // color attachments of currently bound draw framebuffer.
14022 // Reference GL_INTEL_framebuffer_CMAA for details.
14023 glApplyFramebufferAttachmentCMAAINTEL();
14026 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
14027 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
14028 return valuebuffer && valuebuffer->IsValid();
14031 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
14032 GLuint client_id) {
14033 Valuebuffer* valuebuffer = NULL;
14034 if (client_id != 0) {
14035 valuebuffer = GetValuebuffer(client_id);
14036 if (!valuebuffer) {
14037 if (!group_->bind_generates_resource()) {
14038 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
14039 "id not generated by glBindValuebufferCHROMIUM");
14040 return;
14043 // It's a new id so make a valuebuffer for it.
14044 CreateValuebuffer(client_id);
14045 valuebuffer = GetValuebuffer(client_id);
14047 valuebuffer->MarkAsValid();
14049 state_.bound_valuebuffer = valuebuffer;
14052 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
14053 GLenum subscription) {
14054 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
14055 return;
14057 state_.bound_valuebuffer.get()->AddSubscription(subscription);
14060 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
14061 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
14062 return;
14064 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
14067 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
14068 GLenum target,
14069 GLenum subscription) {
14070 if (!CheckCurrentValuebufferForSubscription(
14071 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
14072 return;
14074 if (!CheckSubscriptionTarget(location, subscription,
14075 "glPopulateSubscribedValuesCHROMIUM")) {
14076 return;
14078 const ValueState* state =
14079 state_.bound_valuebuffer.get()->GetState(subscription);
14080 if (state) {
14081 switch (subscription) {
14082 case GL_MOUSE_POSITION_CHROMIUM:
14083 DoUniform2iv(location, 1, state->int_value);
14084 break;
14085 default:
14086 NOTREACHED() << "Unhandled uniform subscription target "
14087 << subscription;
14088 break;
14093 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
14094 GLsizei length, const GLchar* marker) {
14095 if (!marker) {
14096 marker = "";
14098 debug_marker_manager_.SetMarker(
14099 length ? std::string(marker, length) : std::string(marker));
14102 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
14103 GLsizei /*length*/, const GLchar* /*marker*/) {
14106 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
14109 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
14110 GLenum target, GLint image_id) {
14111 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
14113 if (target == GL_TEXTURE_CUBE_MAP) {
14114 LOCAL_SET_GL_ERROR(
14115 GL_INVALID_ENUM,
14116 "glBindTexImage2DCHROMIUM", "invalid target");
14117 return;
14120 // Default target might be conceptually valid, but disallow it to avoid
14121 // accidents.
14122 TextureRef* texture_ref =
14123 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
14124 if (!texture_ref) {
14125 LOCAL_SET_GL_ERROR(
14126 GL_INVALID_OPERATION,
14127 "glBindTexImage2DCHROMIUM", "no texture bound");
14128 return;
14131 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
14132 if (!gl_image) {
14133 LOCAL_SET_GL_ERROR(
14134 GL_INVALID_OPERATION,
14135 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
14136 return;
14140 ScopedGLErrorSuppressor suppressor(
14141 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
14142 if (!gl_image->BindTexImage(target)) {
14143 LOCAL_SET_GL_ERROR(
14144 GL_INVALID_OPERATION,
14145 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
14146 return;
14150 gfx::Size size = gl_image->GetSize();
14151 texture_manager()->SetLevelInfo(
14152 texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(),
14153 size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE,
14154 gfx::Rect(size));
14155 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
14158 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
14159 GLenum target, GLint image_id) {
14160 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
14162 // Default target might be conceptually valid, but disallow it to avoid
14163 // accidents.
14164 TextureRef* texture_ref =
14165 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
14166 if (!texture_ref) {
14167 LOCAL_SET_GL_ERROR(
14168 GL_INVALID_OPERATION,
14169 "glReleaseTexImage2DCHROMIUM", "no texture bound");
14170 return;
14173 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
14174 if (!gl_image) {
14175 LOCAL_SET_GL_ERROR(
14176 GL_INVALID_OPERATION,
14177 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
14178 return;
14181 // Do nothing when image is not currently bound.
14182 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
14183 return;
14186 ScopedGLErrorSuppressor suppressor(
14187 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
14188 gl_image->ReleaseTexImage(target);
14191 texture_manager()->SetLevelInfo(
14192 texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0,
14193 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect());
14196 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
14197 uint32 immediate_data_size,
14198 const void* cmd_data) {
14199 const gles2::cmds::TraceBeginCHROMIUM& c =
14200 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
14201 Bucket* category_bucket = GetBucket(c.category_bucket_id);
14202 Bucket* name_bucket = GetBucket(c.name_bucket_id);
14203 if (!category_bucket || category_bucket->size() == 0 ||
14204 !name_bucket || name_bucket->size() == 0) {
14205 return error::kInvalidArguments;
14208 std::string category_name;
14209 std::string trace_name;
14210 if (!category_bucket->GetAsString(&category_name) ||
14211 !name_bucket->GetAsString(&trace_name)) {
14212 return error::kInvalidArguments;
14215 debug_marker_manager_.PushGroup(trace_name);
14216 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
14217 LOCAL_SET_GL_ERROR(
14218 GL_INVALID_OPERATION,
14219 "glTraceBeginCHROMIUM", "unable to create begin trace");
14220 return error::kNoError;
14222 return error::kNoError;
14225 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
14226 debug_marker_manager_.PopGroup();
14227 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
14228 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
14229 "glTraceEndCHROMIUM", "no trace begin found");
14230 return;
14234 void GLES2DecoderImpl::DoDrawBuffersEXT(
14235 GLsizei count, const GLenum* bufs) {
14236 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
14237 LOCAL_SET_GL_ERROR(
14238 GL_INVALID_VALUE,
14239 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
14240 return;
14243 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
14244 if (framebuffer) {
14245 for (GLsizei i = 0; i < count; ++i) {
14246 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
14247 bufs[i] != GL_NONE) {
14248 LOCAL_SET_GL_ERROR(
14249 GL_INVALID_OPERATION,
14250 "glDrawBuffersEXT",
14251 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
14252 return;
14255 glDrawBuffersARB(count, bufs);
14256 framebuffer->SetDrawBuffers(count, bufs);
14257 } else { // backbuffer
14258 if (count > 1 ||
14259 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
14260 LOCAL_SET_GL_ERROR(
14261 GL_INVALID_OPERATION,
14262 "glDrawBuffersEXT",
14263 "more than one buffer or bufs not GL_NONE or GL_BACK");
14264 return;
14266 GLenum mapped_buf = bufs[0];
14267 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
14268 bufs[0] == GL_BACK) {
14269 mapped_buf = GL_COLOR_ATTACHMENT0;
14271 glDrawBuffersARB(count, &mapped_buf);
14272 back_buffer_draw_buffer_ = bufs[0];
14276 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
14277 MarkContextLost(GetContextLostReasonFromResetStatus(current));
14278 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
14279 reset_by_robustness_extension_ = true;
14282 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
14283 // On Adreno Android devices we need to use a workaround to force caches to
14284 // clear.
14285 if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) {
14286 context_->ReleaseCurrent(nullptr);
14287 context_->MakeCurrent(surface_.get());
14291 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
14292 const GLfloat* matrix) {
14293 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
14294 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
14295 if (!features().chromium_path_rendering) {
14296 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
14297 "glMatrixLoadfCHROMIUM",
14298 "function not available");
14299 return;
14302 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
14303 ? state_.projection_matrix
14304 : state_.modelview_matrix;
14305 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
14306 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
14307 // since the values of the _NV and _CHROMIUM tokens match.
14308 glMatrixLoadfEXT(matrix_mode, matrix);
14311 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
14312 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
14313 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
14315 if (!features().chromium_path_rendering) {
14316 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
14317 "glMatrixLoadIdentityCHROMIUM",
14318 "function not available");
14319 return;
14322 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
14323 ? state_.projection_matrix
14324 : state_.modelview_matrix;
14325 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
14326 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
14327 // since the values of the _NV and _CHROMIUM tokens match.
14328 glMatrixLoadIdentityEXT(matrix_mode);
14331 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
14332 uint32_t immediate_data_size, const void* cmd_data) {
14333 if (!unsafe_es3_apis_enabled())
14334 return error::kUnknownCommand;
14335 const gles2::cmds::UniformBlockBinding& c =
14336 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
14337 GLuint client_id = c.program;
14338 GLuint index = static_cast<GLuint>(c.index);
14339 GLuint binding = static_cast<GLuint>(c.binding);
14340 Program* program = GetProgramInfoNotShader(
14341 client_id, "glUniformBlockBinding");
14342 if (!program) {
14343 return error::kNoError;
14345 GLuint service_id = program->service_id();
14346 glUniformBlockBinding(service_id, index, binding);
14347 return error::kNoError;
14350 error::Error GLES2DecoderImpl::HandleClientWaitSync(
14351 uint32_t immediate_data_size, const void* cmd_data) {
14352 if (!unsafe_es3_apis_enabled())
14353 return error::kUnknownCommand;
14354 const gles2::cmds::ClientWaitSync& c =
14355 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
14356 GLuint sync = static_cast<GLuint>(c.sync);
14357 GLbitfield flags = static_cast<GLbitfield>(c.flags);
14358 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
14359 typedef cmds::ClientWaitSync::Result Result;
14360 Result* result_dst = GetSharedMemoryAs<Result*>(
14361 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
14362 if (!result_dst) {
14363 return error::kOutOfBounds;
14365 if (*result_dst != GL_WAIT_FAILED) {
14366 return error::kInvalidArguments;
14368 GLsync service_sync = 0;
14369 if (!group_->GetSyncServiceId(sync, &service_sync)) {
14370 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
14371 return error::kNoError;
14373 *result_dst = glClientWaitSync(service_sync, flags, timeout);
14374 return error::kNoError;
14377 error::Error GLES2DecoderImpl::HandleWaitSync(
14378 uint32_t immediate_data_size, const void* cmd_data) {
14379 if (!unsafe_es3_apis_enabled())
14380 return error::kUnknownCommand;
14381 const gles2::cmds::WaitSync& c =
14382 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
14383 GLuint sync = static_cast<GLuint>(c.sync);
14384 GLbitfield flags = static_cast<GLbitfield>(c.flags);
14385 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
14386 GLsync service_sync = 0;
14387 if (!group_->GetSyncServiceId(sync, &service_sync)) {
14388 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
14389 return error::kNoError;
14391 glWaitSync(service_sync, flags, timeout);
14392 return error::kNoError;
14395 error::Error GLES2DecoderImpl::HandleGetInternalformativ(
14396 uint32_t immediate_data_size, const void* cmd_data) {
14397 if (!unsafe_es3_apis_enabled())
14398 return error::kUnknownCommand;
14399 const gles2::cmds::GetInternalformativ& c =
14400 *static_cast<const gles2::cmds::GetInternalformativ*>(cmd_data);
14401 GLenum target = static_cast<GLenum>(c.target);
14402 GLenum format = static_cast<GLenum>(c.format);
14403 GLenum pname = static_cast<GLenum>(c.pname);
14404 if (!validators_->render_buffer_target.IsValid(target)) {
14405 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target, "target");
14406 return error::kNoError;
14408 if (!validators_->render_buffer_format.IsValid(format)) {
14409 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format, "format");
14410 return error::kNoError;
14412 if (!validators_->internal_format_parameter.IsValid(pname)) {
14413 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname, "pname");
14414 return error::kNoError;
14416 typedef cmds::GetInternalformativ::Result Result;
14417 GLsizei num_values = 0;
14418 switch (pname) {
14419 case GL_NUM_SAMPLE_COUNTS:
14420 num_values = 1;
14421 break;
14422 case GL_SAMPLES:
14424 GLint value = 0;
14425 glGetInternalformativ(target, format, GL_NUM_SAMPLE_COUNTS, 1, &value);
14426 num_values = static_cast<GLsizei>(value);
14428 break;
14429 default:
14430 NOTREACHED();
14431 break;
14433 Result* result = GetSharedMemoryAs<Result*>(
14434 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
14435 GLint* params = result ? result->GetData() : NULL;
14436 if (params == NULL) {
14437 return error::kOutOfBounds;
14439 // Check that the client initialized the result.
14440 if (result->size != 0) {
14441 return error::kInvalidArguments;
14443 glGetInternalformativ(target, format, pname, num_values, params);
14444 result->SetNumResults(num_values);
14445 return error::kNoError;
14448 error::Error GLES2DecoderImpl::HandleMapBufferRange(
14449 uint32_t immediate_data_size, const void* cmd_data) {
14450 if (!unsafe_es3_apis_enabled()) {
14451 return error::kUnknownCommand;
14453 const gles2::cmds::MapBufferRange& c =
14454 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
14455 GLenum target = static_cast<GLenum>(c.target);
14456 GLbitfield access = static_cast<GLbitfield>(c.access);
14457 GLintptr offset = static_cast<GLintptr>(c.offset);
14458 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
14460 typedef cmds::MapBufferRange::Result Result;
14461 Result* result = GetSharedMemoryAs<Result*>(
14462 c.result_shm_id, c.result_shm_offset, sizeof(*result));
14463 if (!result) {
14464 return error::kOutOfBounds;
14466 if (*result != 0) {
14467 *result = 0;
14468 return error::kInvalidArguments;
14470 int8_t* mem =
14471 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
14472 if (!mem) {
14473 return error::kOutOfBounds;
14476 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
14477 if ((access & mask) == mask) {
14478 // TODO(zmo): To be on the safe side, always map
14479 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
14480 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
14481 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
14483 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14484 // undefined behaviors.
14485 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
14486 if ((access & mask) == mask) {
14487 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
14488 "incompatible access bits");
14489 return error::kNoError;
14491 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
14492 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
14493 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14494 access = (access | GL_MAP_READ_BIT);
14496 void* ptr = glMapBufferRange(target, offset, size, access);
14497 if (ptr == nullptr) {
14498 return error::kNoError;
14500 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14501 DCHECK(buffer);
14502 buffer->SetMappedRange(offset, size, access, ptr,
14503 GetSharedMemoryBuffer(c.data_shm_id));
14504 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14505 memcpy(mem, ptr, size);
14507 *result = 1;
14508 return error::kNoError;
14511 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
14512 uint32_t immediate_data_size, const void* cmd_data) {
14513 if (!unsafe_es3_apis_enabled()) {
14514 return error::kUnknownCommand;
14516 const gles2::cmds::UnmapBuffer& c =
14517 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
14518 GLenum target = static_cast<GLenum>(c.target);
14520 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14521 if (!buffer) {
14522 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
14523 return error::kNoError;
14525 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
14526 if (!mapped_range) {
14527 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
14528 "buffer is unmapped");
14529 return error::kNoError;
14531 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
14532 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
14533 GL_MAP_FLUSH_EXPLICIT_BIT) {
14534 // If we don't need to write back, or explict flush is required, no copying
14535 // back is needed.
14536 } else {
14537 void* mem = mapped_range->GetShmPointer();
14538 if (!mem) {
14539 return error::kOutOfBounds;
14541 DCHECK(mapped_range->pointer);
14542 memcpy(mapped_range->pointer, mem, mapped_range->size);
14544 buffer->RemoveMappedRange();
14545 GLboolean rt = glUnmapBuffer(target);
14546 if (rt == GL_FALSE) {
14547 // At this point, we have already done the necessary validation, so
14548 // GL_FALSE indicates data corruption.
14549 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14550 // the second unmap could still return GL_FALSE. For now, we simply lose
14551 // the contexts in the share group.
14552 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14553 // Need to lose current context before broadcasting!
14554 MarkContextLost(error::kGuilty);
14555 group_->LoseContexts(error::kInnocent);
14556 return error::kLostContext;
14558 return error::kNoError;
14561 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14562 TextureRef* texture_ref) {
14563 Texture* texture = texture_ref->texture();
14564 DoDidUseTexImageIfNeeded(texture, texture->target());
14567 // Note that GL_LOST_CONTEXT is specific to GLES.
14568 // For desktop GL we have to query the reset status proactively.
14569 void GLES2DecoderImpl::OnContextLostError() {
14570 if (!WasContextLost()) {
14571 // Need to lose current context before broadcasting!
14572 CheckResetStatus();
14573 group_->LoseContexts(error::kUnknown);
14574 reset_by_robustness_extension_ = true;
14578 void GLES2DecoderImpl::OnOutOfMemoryError() {
14579 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
14580 error::ContextLostReason other = error::kOutOfMemory;
14581 if (CheckResetStatus()) {
14582 other = error::kUnknown;
14583 } else {
14584 // Need to lose current context before broadcasting!
14585 MarkContextLost(error::kOutOfMemory);
14587 group_->LoseContexts(other);
14591 error::Error GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14592 uint32 immediate_data_size,
14593 const void* cmd_data) {
14594 static const char kFunctionName[] = "glGenPathsCHROMIUM";
14595 const gles2::cmds::GenPathsCHROMIUM& c =
14596 *static_cast<const gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
14597 if (!features().chromium_path_rendering) {
14598 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14599 "function not available");
14600 return error::kNoError;
14603 GLsizei range = static_cast<GLsizei>(c.range);
14604 if (range < 0) {
14605 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14606 return error::kNoError;
14609 GLuint first_client_id = static_cast<GLuint>(c.first_client_id);
14610 if (first_client_id == 0)
14611 return error::kInvalidArguments;
14613 if (range == 0)
14614 return error::kNoError;
14616 if (!GenPathsCHROMIUMHelper(first_client_id, range))
14617 return error::kInvalidArguments;
14619 return error::kNoError;
14621 error::Error GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14622 uint32_t immediate_data_size,
14623 const void* cmd_data) {
14624 static const char kFunctionName[] = "glDeletePathsCHROMIUM";
14625 const gles2::cmds::DeletePathsCHROMIUM& c =
14626 *static_cast<const gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
14627 if (!features().chromium_path_rendering) {
14628 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14629 "function not available");
14630 return error::kNoError;
14633 GLsizei range = static_cast<GLsizei>(c.range);
14634 if (range < 0) {
14635 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14636 return error::kNoError;
14639 if (range == 0)
14640 return error::kNoError;
14642 GLuint first_client_id = c.first_client_id;
14643 // first_client_id can be 0, because non-existing path ids are skipped.
14645 if (!DeletePathsCHROMIUMHelper(first_client_id, range))
14646 return error::kInvalidArguments;
14648 return error::kNoError;
14651 error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14652 uint32 immediate_data_size,
14653 const void* cmd_data) {
14654 static const char kFunctionName[] = "glPathCommandsCHROMIUM";
14655 const gles2::cmds::PathCommandsCHROMIUM& c =
14656 *static_cast<const gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
14657 if (!features().chromium_path_rendering) {
14658 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14659 "function not available");
14660 return error::kNoError;
14663 GLuint service_id = 0;
14664 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14665 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14666 "invalid path name");
14667 return error::kNoError;
14670 GLsizei num_commands = static_cast<GLsizei>(c.numCommands);
14671 if (num_commands < 0) {
14672 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCommands < 0");
14673 return error::kNoError;
14676 GLsizei num_coords = static_cast<uint32>(c.numCoords);
14677 if (num_coords < 0) {
14678 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCoords < 0");
14679 return error::kNoError;
14682 GLenum coord_type = static_cast<uint32>(c.coordType);
14683 if (!validators_->path_coord_type.IsValid(static_cast<GLint>(coord_type))) {
14684 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid coordType");
14685 return error::kNoError;
14688 const GLubyte* commands = NULL;
14689 base::CheckedNumeric<GLsizei> num_coords_expected = 0;
14691 if (num_commands > 0) {
14692 uint32 commands_shm_id = static_cast<uint32>(c.commands_shm_id);
14693 uint32 commands_shm_offset = static_cast<uint32>(c.commands_shm_offset);
14694 if (commands_shm_id != 0 || commands_shm_offset != 0)
14695 commands = GetSharedMemoryAs<const GLubyte*>(
14696 commands_shm_id, commands_shm_offset, num_commands);
14698 if (!commands)
14699 return error::kOutOfBounds;
14701 for (GLsizei i = 0; i < num_commands; ++i) {
14702 switch (commands[i]) {
14703 case GL_CLOSE_PATH_CHROMIUM:
14704 // Close has no coords.
14705 break;
14706 case GL_MOVE_TO_CHROMIUM:
14707 // Fallthrough.
14708 case GL_LINE_TO_CHROMIUM:
14709 num_coords_expected += 2;
14710 break;
14711 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
14712 num_coords_expected += 4;
14713 break;
14714 case GL_CUBIC_CURVE_TO_CHROMIUM:
14715 num_coords_expected += 6;
14716 break;
14717 case GL_CONIC_CURVE_TO_CHROMIUM:
14718 num_coords_expected += 5;
14719 break;
14720 default:
14721 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid command");
14722 return error::kNoError;
14727 if (!num_coords_expected.IsValid() ||
14728 num_coords != num_coords_expected.ValueOrDie()) {
14729 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14730 "numCoords does not match commands");
14731 return error::kNoError;
14734 const void* coords = NULL;
14736 if (num_coords > 0) {
14737 uint32 coords_size = 0;
14738 uint32 coord_type_size =
14739 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
14740 if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size))
14741 return error::kOutOfBounds;
14743 uint32 coords_shm_id = static_cast<uint32>(c.coords_shm_id);
14744 uint32 coords_shm_offset = static_cast<uint32>(c.coords_shm_offset);
14745 if (coords_shm_id != 0 || coords_shm_offset != 0)
14746 coords = GetSharedMemoryAs<const void*>(coords_shm_id, coords_shm_offset,
14747 coords_size);
14749 if (!coords)
14750 return error::kOutOfBounds;
14753 glPathCommandsNV(service_id, num_commands, commands, num_coords, coord_type,
14754 coords);
14756 return error::kNoError;
14759 error::Error GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14760 uint32 immediate_data_size,
14761 const void* cmd_data) {
14762 static const char kFunctionName[] = "glPathParameterfCHROMIUM";
14763 const gles2::cmds::PathParameterfCHROMIUM& c =
14764 *static_cast<const gles2::cmds::PathParameterfCHROMIUM*>(cmd_data);
14765 if (!features().chromium_path_rendering) {
14766 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14767 "function not available");
14768 return error::kNoError;
14770 GLuint service_id = 0;
14771 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14772 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14773 "invalid path name");
14774 return error::kNoError;
14777 GLenum pname = static_cast<GLenum>(c.pname);
14778 GLfloat value = static_cast<GLfloat>(c.value);
14779 bool hasValueError = false;
14781 switch (pname) {
14782 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14783 case GL_PATH_MITER_LIMIT_CHROMIUM:
14784 hasValueError = std::isnan(value) || !std::isfinite(value) || value < 0;
14785 break;
14786 case GL_PATH_STROKE_BOUND_CHROMIUM:
14787 value = std::max(std::min(1.0f, value), 0.0f);
14788 break;
14789 case GL_PATH_END_CAPS_CHROMIUM:
14790 hasValueError = !validators_->path_parameter_cap_values.IsValid(
14791 static_cast<GLint>(value));
14792 break;
14793 case GL_PATH_JOIN_STYLE_CHROMIUM:
14794 hasValueError = !validators_->path_parameter_join_values.IsValid(
14795 static_cast<GLint>(value));
14796 break;
14797 default:
14798 DCHECK(!validators_->path_parameter.IsValid(pname));
14799 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14800 return error::kNoError;
14802 DCHECK(validators_->path_parameter.IsValid(pname));
14804 if (hasValueError) {
14805 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14806 return error::kNoError;
14809 glPathParameterfNV(service_id, pname, value);
14810 return error::kNoError;
14813 error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14814 uint32 immediate_data_size,
14815 const void* cmd_data) {
14816 static const char kFunctionName[] = "glPathParameteriCHROMIUM";
14817 const gles2::cmds::PathParameteriCHROMIUM& c =
14818 *static_cast<const gles2::cmds::PathParameteriCHROMIUM*>(cmd_data);
14819 if (!features().chromium_path_rendering) {
14820 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14821 "function not available");
14822 return error::kNoError;
14824 GLuint service_id = 0;
14825 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14826 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14827 "invalid path name");
14828 return error::kNoError;
14831 GLenum pname = static_cast<GLenum>(c.pname);
14832 GLint value = static_cast<GLint>(c.value);
14833 bool hasValueError = false;
14835 switch (pname) {
14836 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14837 case GL_PATH_MITER_LIMIT_CHROMIUM:
14838 hasValueError = value < 0;
14839 break;
14840 case GL_PATH_STROKE_BOUND_CHROMIUM:
14841 value = std::max(std::min(1, value), 0);
14842 break;
14843 case GL_PATH_END_CAPS_CHROMIUM:
14844 hasValueError = !validators_->path_parameter_cap_values.IsValid(value);
14845 break;
14846 case GL_PATH_JOIN_STYLE_CHROMIUM:
14847 hasValueError = !validators_->path_parameter_join_values.IsValid(value);
14848 break;
14849 default:
14850 DCHECK(!validators_->path_parameter.IsValid(pname));
14851 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14852 return error::kNoError;
14854 DCHECK(validators_->path_parameter.IsValid(pname));
14856 if (hasValueError) {
14857 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14858 return error::kNoError;
14861 glPathParameteriNV(service_id, pname, value);
14862 return error::kNoError;
14865 error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14866 uint32 immediate_data_size,
14867 const void* cmd_data) {
14868 static const char kFunctionName[] = "glStencilFillPathCHROMIUM";
14869 const gles2::cmds::StencilFillPathCHROMIUM& c =
14870 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(cmd_data);
14871 if (!features().chromium_path_rendering) {
14872 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14873 "function not available");
14874 return error::kNoError;
14876 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14877 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14878 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14879 return error::kNoError;
14881 GLuint mask = static_cast<GLuint>(c.mask);
14882 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14883 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14884 GLES2Util::IsNPOT(mask + 1)) {
14885 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14886 "mask + 1 is not power of two");
14887 return error::kNoError;
14889 GLuint service_id = 0;
14890 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14891 // "If /path/ does not name an existing path object, the command does
14892 // nothing (and no error is generated)."
14893 // This holds for other rendering functions, too.
14894 return error::kNoError;
14896 ApplyDirtyState();
14897 glStencilFillPathNV(service_id, fill_mode, mask);
14898 return error::kNoError;
14901 error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14902 uint32 immediate_data_size,
14903 const void* cmd_data) {
14904 static const char kFunctionName[] = "glStencilStrokePathCHROMIUM";
14905 const gles2::cmds::StencilStrokePathCHROMIUM& c =
14906 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data);
14907 if (!features().chromium_path_rendering) {
14908 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14909 "function not available");
14910 return error::kNoError;
14912 GLuint service_id = 0;
14913 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14914 return error::kNoError;
14916 GLint reference = static_cast<GLint>(c.reference);
14917 GLuint mask = static_cast<GLuint>(c.mask);
14918 ApplyDirtyState();
14919 glStencilStrokePathNV(service_id, reference, mask);
14920 return error::kNoError;
14923 error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14924 uint32 immediate_data_size,
14925 const void* cmd_data) {
14926 static const char kFunctionName[] = "glCoverFillPathCHROMIUM";
14927 const gles2::cmds::CoverFillPathCHROMIUM& c =
14928 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data);
14929 if (!features().chromium_path_rendering) {
14930 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14931 "function not available");
14932 return error::kNoError;
14934 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14935 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14936 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14937 return error::kNoError;
14939 GLuint service_id = 0;
14940 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14941 return error::kNoError;
14943 ApplyDirtyState();
14944 glCoverFillPathNV(service_id, cover_mode);
14945 return error::kNoError;
14948 error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14949 uint32 immediate_data_size,
14950 const void* cmd_data) {
14951 static const char kFunctionName[] = "glCoverStrokePathCHROMIUM";
14952 const gles2::cmds::CoverStrokePathCHROMIUM& c =
14953 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data);
14954 if (!features().chromium_path_rendering) {
14955 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14956 "function not available");
14957 return error::kNoError;
14959 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14960 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14961 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14962 return error::kNoError;
14964 GLuint service_id = 0;
14965 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14966 return error::kNoError;
14968 ApplyDirtyState();
14969 glCoverStrokePathNV(service_id, cover_mode);
14970 return error::kNoError;
14973 error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14974 uint32 immediate_data_size,
14975 const void* cmd_data) {
14976 static const char kFunctionName[] = "glStencilThenCoverFillPathCHROMIUM";
14977 const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
14978 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
14979 cmd_data);
14980 if (!features().chromium_path_rendering) {
14981 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14982 "function not available");
14983 return error::kNoError;
14985 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14986 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14987 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14988 return error::kNoError;
14990 GLuint mask = static_cast<GLuint>(c.mask);
14991 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14992 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14993 GLES2Util::IsNPOT(mask + 1)) {
14994 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14995 "mask + 1 is not power of two");
14996 return error::kNoError;
14998 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14999 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
15000 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
15001 return error::kNoError;
15003 GLuint service_id = 0;
15004 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
15005 return error::kNoError;
15007 ApplyDirtyState();
15008 glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode);
15009 return error::kNoError;
15012 error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
15013 uint32 immediate_data_size,
15014 const void* cmd_data) {
15015 static const char kFunctionName[] = "glStencilThenCoverStrokePathCHROMIUM";
15016 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
15017 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
15018 cmd_data);
15019 if (!features().chromium_path_rendering) {
15020 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
15021 "function not available");
15022 return error::kNoError;
15024 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
15025 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
15026 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
15027 return error::kNoError;
15029 GLuint service_id = 0;
15030 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
15031 return error::kNoError;
15033 GLint reference = static_cast<GLint>(c.reference);
15034 GLuint mask = static_cast<GLuint>(c.mask);
15035 ApplyDirtyState();
15036 glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode);
15037 return error::kNoError;
15040 // Include the auto-generated part of this file. We split this because it means
15041 // we can easily edit the non-auto generated parts right here in this file
15042 // instead of having to edit some template or the code generator.
15043 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
15045 } // namespace gles2
15046 } // namespace gpu