Update CrOS OOBE throbber to MD throbber; delete old asset
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob82e9052c63b7cc621771c35f4c0442676194ed3a
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/async_pixel_transfer_delegate.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
34 #include "gpu/command_buffer/service/buffer_manager.h"
35 #include "gpu/command_buffer/service/context_group.h"
36 #include "gpu/command_buffer/service/context_state.h"
37 #include "gpu/command_buffer/service/error_state.h"
38 #include "gpu/command_buffer/service/feature_info.h"
39 #include "gpu/command_buffer/service/framebuffer_manager.h"
40 #include "gpu/command_buffer/service/gl_utils.h"
41 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
42 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
43 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
44 #include "gpu/command_buffer/service/gpu_state_tracer.h"
45 #include "gpu/command_buffer/service/gpu_switches.h"
46 #include "gpu/command_buffer/service/gpu_tracer.h"
47 #include "gpu/command_buffer/service/image_manager.h"
48 #include "gpu/command_buffer/service/logger.h"
49 #include "gpu/command_buffer/service/mailbox_manager.h"
50 #include "gpu/command_buffer/service/memory_tracking.h"
51 #include "gpu/command_buffer/service/path_manager.h"
52 #include "gpu/command_buffer/service/program_manager.h"
53 #include "gpu/command_buffer/service/query_manager.h"
54 #include "gpu/command_buffer/service/renderbuffer_manager.h"
55 #include "gpu/command_buffer/service/shader_manager.h"
56 #include "gpu/command_buffer/service/shader_translator.h"
57 #include "gpu/command_buffer/service/texture_manager.h"
58 #include "gpu/command_buffer/service/valuebuffer_manager.h"
59 #include "gpu/command_buffer/service/vertex_array_manager.h"
60 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
61 #include "third_party/smhasher/src/City.h"
62 #include "ui/gfx/geometry/point.h"
63 #include "ui/gfx/geometry/rect.h"
64 #include "ui/gfx/geometry/size.h"
65 #include "ui/gfx/overlay_transform.h"
66 #include "ui/gl/gl_bindings.h"
67 #include "ui/gl/gl_context.h"
68 #include "ui/gl/gl_fence.h"
69 #include "ui/gl/gl_image.h"
70 #include "ui/gl/gl_implementation.h"
71 #include "ui/gl/gl_surface.h"
72 #include "ui/gl/gl_version_info.h"
73 #include "ui/gl/gpu_timing.h"
75 #if defined(OS_MACOSX)
76 #include <IOSurface/IOSurface.h>
77 // Note that this must be included after gl_bindings.h to avoid conflicts.
78 #include <OpenGL/CGLIOSurface.h>
79 #endif
81 namespace gpu {
82 namespace gles2 {
84 namespace {
86 const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
87 const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
88 const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
89 const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
91 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
92 0.0f, 1.0f, 0.0f, 0.0f,
93 0.0f, 0.0f, 1.0f, 0.0f,
94 0.0f, 0.0f, 0.0f, 1.0f};
96 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
97 GLint rangeMax,
98 GLint precision) {
99 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
102 void GetShaderPrecisionFormatImpl(GLenum shader_type,
103 GLenum precision_type,
104 GLint* range, GLint* precision) {
105 switch (precision_type) {
106 case GL_LOW_INT:
107 case GL_MEDIUM_INT:
108 case GL_HIGH_INT:
109 // These values are for a 32-bit twos-complement integer format.
110 range[0] = 31;
111 range[1] = 30;
112 *precision = 0;
113 break;
114 case GL_LOW_FLOAT:
115 case GL_MEDIUM_FLOAT:
116 case GL_HIGH_FLOAT:
117 // These values are for an IEEE single-precision floating-point format.
118 range[0] = 127;
119 range[1] = 127;
120 *precision = 23;
121 break;
122 default:
123 NOTREACHED();
124 break;
127 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
128 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
129 // This function is sometimes defined even though it's really just
130 // a stub, so we need to set range and precision as if it weren't
131 // defined before calling it.
132 // On Mac OS with some GPUs, calling this generates a
133 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
134 // platforms.
135 glGetShaderPrecisionFormat(shader_type, precision_type,
136 range, precision);
138 // TODO(brianderson): Make the following official workarounds.
140 // Some drivers have bugs where they report the ranges as a negative number.
141 // Taking the absolute value here shouldn't hurt because negative numbers
142 // aren't expected anyway.
143 range[0] = abs(range[0]);
144 range[1] = abs(range[1]);
146 // If the driver reports a precision for highp float that isn't actually
147 // highp, don't pretend like it's supported because shader compilation will
148 // fail anyway.
149 if (precision_type == GL_HIGH_FLOAT &&
150 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
151 range[0] = 0;
152 range[1] = 0;
153 *precision = 0;
158 gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
159 switch (plane_transform) {
160 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
161 return gfx::OVERLAY_TRANSFORM_NONE;
162 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
163 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
164 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
165 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
166 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
168 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
170 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
171 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
172 default:
173 return gfx::OVERLAY_TRANSFORM_INVALID;
177 template <typename MANAGER_TYPE, typename OBJECT_TYPE>
178 GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) {
179 DCHECK(manager);
180 GLuint client_id = 0;
181 if (object) {
182 manager->GetClientId(object->service_id(), &client_id);
184 return client_id;
187 struct Vec4f {
188 explicit Vec4f(const Vec4& data) {
189 data.GetValues(v);
192 GLfloat v[4];
195 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
196 // contains the other rectangle or shares an edge with the other rectangle.
197 bool CombineAdjacentRects(const gfx::Rect& rect1,
198 const gfx::Rect& rect2,
199 gfx::Rect* result) {
200 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
201 if (rect1.IsEmpty() || rect2.Contains(rect1)) {
202 *result = rect2;
203 return true;
206 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
207 if (rect2.IsEmpty() || rect1.Contains(rect2)) {
208 *result = rect1;
209 return true;
212 // Return the union of |rect1| and |rect2| if they share an edge.
213 if (rect1.SharesEdgeWith(rect2)) {
214 *result = gfx::UnionRects(rect1, rect2);
215 return true;
218 // Return false if it's not possible to combine |rect1| and |rect2|.
219 return false;
222 } // namespace
224 class GLES2DecoderImpl;
226 // Local versions of the SET_GL_ERROR macros
227 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
228 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
229 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
230 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
231 function_name, value, label)
232 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
233 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
234 function_name, pname)
235 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
236 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
237 function_name)
238 #define LOCAL_PEEK_GL_ERROR(function_name) \
239 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
240 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
241 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
242 #define LOCAL_PERFORMANCE_WARNING(msg) \
243 PerformanceWarning(__FILE__, __LINE__, msg)
244 #define LOCAL_RENDER_WARNING(msg) \
245 RenderWarning(__FILE__, __LINE__, msg)
247 // Check that certain assumptions the code makes are true. There are places in
248 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
249 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
250 // a few others) are 32bits. If they are not 32bits the code will have to change
251 // to call those GL functions with service side memory and then copy the results
252 // to shared memory, converting the sizes.
253 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
254 "GLint should be the same size as uint32");
255 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
256 "GLsizei should be the same size as uint32");
257 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
258 "GLfloat should be the same size as float");
260 // TODO(kbr): the use of this anonymous namespace core dumps the
261 // linker on Mac OS X 10.6 when the symbol ordering file is used
262 // namespace {
264 // Returns the address of the first byte after a struct.
265 template <typename T>
266 const void* AddressAfterStruct(const T& pod) {
267 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
270 // Returns the address of the frst byte after the struct or NULL if size >
271 // immediate_data_size.
272 template <typename RETURN_TYPE, typename COMMAND_TYPE>
273 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
274 uint32 size,
275 uint32 immediate_data_size) {
276 return (size <= immediate_data_size) ?
277 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
278 NULL;
281 // Computes the data size for certain gl commands like glUniform.
282 bool ComputeDataSize(
283 GLuint count,
284 size_t size,
285 unsigned int elements_per_unit,
286 uint32* dst) {
287 uint32 value;
288 if (!SafeMultiplyUint32(count, size, &value)) {
289 return false;
291 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
292 return false;
294 *dst = value;
295 return true;
298 // Return true if a character belongs to the ASCII subset as defined in
299 // GLSL ES 1.0 spec section 3.1.
300 static bool CharacterIsValidForGLES(unsigned char c) {
301 // Printing characters are valid except " $ ` @ \ ' DEL.
302 if (c >= 32 && c <= 126 &&
303 c != '"' &&
304 c != '$' &&
305 c != '`' &&
306 c != '@' &&
307 c != '\\' &&
308 c != '\'') {
309 return true;
311 // Horizontal tab, line feed, vertical tab, form feed, carriage return
312 // are also valid.
313 if (c >= 9 && c <= 13) {
314 return true;
317 return false;
320 static bool StringIsValidForGLES(const char* str) {
321 for (; *str; ++str) {
322 if (!CharacterIsValidForGLES(*str)) {
323 return false;
326 return true;
329 // This class prevents any GL errors that occur when it is in scope from
330 // being reported to the client.
331 class ScopedGLErrorSuppressor {
332 public:
333 explicit ScopedGLErrorSuppressor(
334 const char* function_name, ErrorState* error_state);
335 ~ScopedGLErrorSuppressor();
336 private:
337 const char* function_name_;
338 ErrorState* error_state_;
339 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
342 // Temporarily changes a decoder's bound texture and restore it when this
343 // object goes out of scope. Also temporarily switches to using active texture
344 // unit zero in case the client has changed that to something invalid.
345 class ScopedTextureBinder {
346 public:
347 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
348 ~ScopedTextureBinder();
350 private:
351 ContextState* state_;
352 GLenum target_;
353 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
356 // Temporarily changes a decoder's bound render buffer and restore it when this
357 // object goes out of scope.
358 class ScopedRenderBufferBinder {
359 public:
360 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
361 ~ScopedRenderBufferBinder();
363 private:
364 ContextState* state_;
365 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
368 // Temporarily changes a decoder's bound frame buffer and restore it when this
369 // object goes out of scope.
370 class ScopedFrameBufferBinder {
371 public:
372 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
373 ~ScopedFrameBufferBinder();
375 private:
376 GLES2DecoderImpl* decoder_;
377 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
380 // Temporarily changes a decoder's bound frame buffer to a resolved version of
381 // the multisampled offscreen render buffer if that buffer is multisampled, and,
382 // if it is bound or enforce_internal_framebuffer is true. If internal is
383 // true, the resolved framebuffer is not visible to the parent.
384 class ScopedResolvedFrameBufferBinder {
385 public:
386 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
387 bool enforce_internal_framebuffer,
388 bool internal);
389 ~ScopedResolvedFrameBufferBinder();
391 private:
392 GLES2DecoderImpl* decoder_;
393 bool resolve_and_bind_;
394 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
397 class ScopedModifyPixels {
398 public:
399 explicit ScopedModifyPixels(TextureRef* ref);
400 ~ScopedModifyPixels();
402 private:
403 TextureRef* ref_;
406 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
407 if (ref_)
408 ref_->texture()->OnWillModifyPixels();
411 ScopedModifyPixels::~ScopedModifyPixels() {
412 if (ref_)
413 ref_->texture()->OnDidModifyPixels();
416 class ScopedRenderTo {
417 public:
418 explicit ScopedRenderTo(Framebuffer* framebuffer);
419 ~ScopedRenderTo();
421 private:
422 const Framebuffer* framebuffer_;
425 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
426 : framebuffer_(framebuffer) {
427 if (framebuffer)
428 framebuffer_->OnWillRenderTo();
431 ScopedRenderTo::~ScopedRenderTo() {
432 if (framebuffer_)
433 framebuffer_->OnDidRenderTo();
436 // Encapsulates an OpenGL texture.
437 class BackTexture {
438 public:
439 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
440 ~BackTexture();
442 // Create a new render texture.
443 void Create();
445 // Set the initial size and format of a render texture or resize it.
446 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
448 // Copy the contents of the currently bound frame buffer.
449 void Copy(const gfx::Size& size, GLenum format);
451 // Destroy the render texture. This must be explicitly called before
452 // destroying this object.
453 void Destroy();
455 // Invalidate the texture. This can be used when a context is lost and it is
456 // not possible to make it current in order to free the resource.
457 void Invalidate();
459 GLuint id() const {
460 return id_;
463 gfx::Size size() const {
464 return size_;
467 private:
468 MemoryTypeTracker memory_tracker_;
469 ContextState* state_;
470 size_t bytes_allocated_;
471 GLuint id_;
472 gfx::Size size_;
473 DISALLOW_COPY_AND_ASSIGN(BackTexture);
476 // Encapsulates an OpenGL render buffer of any format.
477 class BackRenderbuffer {
478 public:
479 explicit BackRenderbuffer(
480 RenderbufferManager* renderbuffer_manager,
481 MemoryTracker* memory_tracker,
482 ContextState* state);
483 ~BackRenderbuffer();
485 // Create a new render buffer.
486 void Create();
488 // Set the initial size and format of a render buffer or resize it.
489 bool AllocateStorage(const FeatureInfo* feature_info,
490 const gfx::Size& size,
491 GLenum format,
492 GLsizei samples);
494 // Destroy the render buffer. This must be explicitly called before destroying
495 // this object.
496 void Destroy();
498 // Invalidate the render buffer. This can be used when a context is lost and
499 // it is not possible to make it current in order to free the resource.
500 void Invalidate();
502 GLuint id() const {
503 return id_;
506 private:
507 RenderbufferManager* renderbuffer_manager_;
508 MemoryTypeTracker memory_tracker_;
509 ContextState* state_;
510 size_t bytes_allocated_;
511 GLuint id_;
512 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
515 // Encapsulates an OpenGL frame buffer.
516 class BackFramebuffer {
517 public:
518 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
519 ~BackFramebuffer();
521 // Create a new frame buffer.
522 void Create();
524 // Attach a color render buffer to a frame buffer.
525 void AttachRenderTexture(BackTexture* texture);
527 // Attach a render buffer to a frame buffer. Note that this unbinds any
528 // currently bound frame buffer.
529 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
531 // Destroy the frame buffer. This must be explicitly called before destroying
532 // this object.
533 void Destroy();
535 // Invalidate the frame buffer. This can be used when a context is lost and it
536 // is not possible to make it current in order to free the resource.
537 void Invalidate();
539 // See glCheckFramebufferStatusEXT.
540 GLenum CheckStatus();
542 GLuint id() const {
543 return id_;
546 private:
547 GLES2DecoderImpl* decoder_;
548 GLuint id_;
549 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
552 struct FenceCallback {
553 FenceCallback()
554 : fence(gfx::GLFence::Create()) {
555 DCHECK(fence);
557 std::vector<base::Closure> callbacks;
558 scoped_ptr<gfx::GLFence> fence;
561 class AsyncUploadTokenCompletionObserver
562 : public AsyncPixelTransferCompletionObserver {
563 public:
564 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
565 : async_upload_token_(async_upload_token) {
568 void DidComplete(const AsyncMemoryParams& mem_params) override {
569 DCHECK(mem_params.buffer().get());
570 void* data = mem_params.GetDataAddress();
571 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
572 sync->SetAsyncUploadToken(async_upload_token_);
575 private:
576 ~AsyncUploadTokenCompletionObserver() override {}
578 uint32 async_upload_token_;
580 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
583 // } // anonymous namespace.
585 // static
586 const unsigned int GLES2Decoder::kDefaultStencilMask =
587 static_cast<unsigned int>(-1);
589 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
590 uint32* service_texture_id) {
591 return false;
594 GLES2Decoder::GLES2Decoder()
595 : initialized_(false),
596 debug_(false),
597 log_commands_(false),
598 unsafe_es3_apis_enabled_(false) {
601 GLES2Decoder::~GLES2Decoder() {
604 void GLES2Decoder::BeginDecoding() {}
606 void GLES2Decoder::EndDecoding() {}
608 // This class implements GLES2Decoder so we don't have to expose all the GLES2
609 // cmd stuff to outside this class.
610 class GLES2DecoderImpl : public GLES2Decoder,
611 public FramebufferManager::TextureDetachObserver,
612 public ErrorStateClient {
613 public:
614 explicit GLES2DecoderImpl(ContextGroup* group);
615 ~GLES2DecoderImpl() override;
617 // Overridden from AsyncAPIInterface.
618 Error DoCommand(unsigned int command,
619 unsigned int arg_count,
620 const void* args) override;
622 error::Error DoCommands(unsigned int num_commands,
623 const void* buffer,
624 int num_entries,
625 int* entries_processed) override;
627 template <bool DebugImpl>
628 error::Error DoCommandsImpl(unsigned int num_commands,
629 const void* buffer,
630 int num_entries,
631 int* entries_processed);
633 // Overridden from AsyncAPIInterface.
634 const char* GetCommandName(unsigned int command_id) const override;
636 // Overridden from GLES2Decoder.
637 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
638 const scoped_refptr<gfx::GLContext>& context,
639 bool offscreen,
640 const gfx::Size& offscreen_size,
641 const DisallowedFeatures& disallowed_features,
642 const std::vector<int32>& attribs) override;
643 void Destroy(bool have_context) override;
644 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
645 void ProduceFrontBuffer(const Mailbox& mailbox) override;
646 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
647 void UpdateParentTextureInfo();
648 bool MakeCurrent() override;
649 GLES2Util* GetGLES2Util() override { return &util_; }
650 gfx::GLContext* GetGLContext() override { return context_.get(); }
651 ContextGroup* GetContextGroup() override { return group_.get(); }
652 Capabilities GetCapabilities() override;
653 void RestoreState(const ContextState* prev_state) override;
655 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
656 void RestoreAllTextureUnitBindings(
657 const ContextState* prev_state) const override {
658 state_.RestoreAllTextureUnitBindings(prev_state);
660 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
661 state_.RestoreActiveTextureUnitBinding(target);
663 void RestoreBufferBindings() const override {
664 state_.RestoreBufferBindings();
666 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
667 void RestoreProgramBindings() const override {
668 state_.RestoreProgramBindings();
670 void RestoreTextureUnitBindings(unsigned unit) const override {
671 state_.RestoreTextureUnitBindings(unit, NULL);
673 void RestoreFramebufferBindings() const override;
674 void RestoreRenderbufferBindings() override;
675 void RestoreTextureState(unsigned service_id) const override;
677 void ClearAllAttributes() const override;
678 void RestoreAllAttributes() const override;
680 QueryManager* GetQueryManager() override { return query_manager_.get(); }
681 VertexArrayManager* GetVertexArrayManager() override {
682 return vertex_array_manager_.get();
684 ImageManager* GetImageManager() override { return image_manager_.get(); }
686 ValuebufferManager* GetValuebufferManager() override {
687 return valuebuffer_manager();
690 bool ProcessPendingQueries(bool did_finish) override;
692 bool HasMoreIdleWork() override;
693 void PerformIdleWork() override;
695 void WaitForReadPixels(base::Closure callback) override;
697 void SetResizeCallback(
698 const base::Callback<void(gfx::Size, float)>& callback) override;
700 Logger* GetLogger() override;
702 void BeginDecoding() override;
703 void EndDecoding() override;
705 ErrorState* GetErrorState() override;
706 const ContextState* GetContextState() override { return &state_; }
708 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
709 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
711 AsyncPixelTransferManager* GetAsyncPixelTransferManager() override;
712 void ResetAsyncPixelTransferManagerForTest() override;
713 void SetAsyncPixelTransferManagerForTest(
714 AsyncPixelTransferManager* manager) override;
715 void SetIgnoreCachedStateForTest(bool ignore) override;
716 void ProcessFinishedAsyncTransfers();
718 bool GetServiceTextureId(uint32 client_texture_id,
719 uint32* service_texture_id) override;
721 uint32 GetTextureUploadCount() override;
722 base::TimeDelta GetTotalTextureUploadTime() override;
723 base::TimeDelta GetTotalProcessingCommandsTime() override;
724 void AddProcessingCommandsTime(base::TimeDelta) override;
726 // Restores the current state to the user's settings.
727 void RestoreCurrentFramebufferBindings();
729 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
730 void ApplyDirtyState();
732 // These check the state of the currently bound framebuffer or the
733 // backbuffer if no framebuffer is bound.
734 // Check with all attached and enabled color attachments.
735 bool BoundFramebufferHasColorAttachmentWithAlpha();
736 bool BoundFramebufferHasDepthAttachment();
737 bool BoundFramebufferHasStencilAttachment();
739 error::ContextLostReason GetContextLostReason() override;
741 // Overridden from FramebufferManager::TextureDetachObserver:
742 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
744 // Overriden from ErrorStateClient.
745 void OnContextLostError() override;
746 void OnOutOfMemoryError() override;
748 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
749 void EnsureRenderbufferBound();
751 // Helpers to facilitate calling into compatible extensions.
752 static void RenderbufferStorageMultisampleHelper(
753 const FeatureInfo* feature_info,
754 GLenum target,
755 GLsizei samples,
756 GLenum internal_format,
757 GLsizei width,
758 GLsizei height);
760 void BlitFramebufferHelper(GLint srcX0,
761 GLint srcY0,
762 GLint srcX1,
763 GLint srcY1,
764 GLint dstX0,
765 GLint dstY0,
766 GLint dstX1,
767 GLint dstY1,
768 GLbitfield mask,
769 GLenum filter);
771 private:
772 friend class ScopedFrameBufferBinder;
773 friend class ScopedResolvedFrameBufferBinder;
774 friend class BackFramebuffer;
776 // Initialize or re-initialize the shader translator.
777 bool InitializeShaderTranslator();
779 void UpdateCapabilities();
781 // Helpers for the glGen and glDelete functions.
782 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
783 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
784 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
785 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
786 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
787 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
788 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
789 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
790 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
791 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
792 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
793 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
794 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
795 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
796 bool GenPathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
797 bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
799 // Helper for async upload token completion notification callback.
800 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
801 uint32 sync_data_shm_id,
802 uint32 sync_data_shm_offset);
806 // Workarounds
807 void OnFboChanged() const;
808 void OnUseFramebuffer() const;
810 error::ContextLostReason GetContextLostReasonFromResetStatus(
811 GLenum reset_status) const;
813 // TODO(gman): Cache these pointers?
814 BufferManager* buffer_manager() {
815 return group_->buffer_manager();
818 RenderbufferManager* renderbuffer_manager() {
819 return group_->renderbuffer_manager();
822 FramebufferManager* framebuffer_manager() {
823 return group_->framebuffer_manager();
826 ValuebufferManager* valuebuffer_manager() {
827 return group_->valuebuffer_manager();
830 PathManager* path_manager() { return group_->path_manager(); }
832 ProgramManager* program_manager() {
833 return group_->program_manager();
836 ShaderManager* shader_manager() {
837 return group_->shader_manager();
840 ShaderTranslatorCache* shader_translator_cache() {
841 return group_->shader_translator_cache();
844 const TextureManager* texture_manager() const {
845 return group_->texture_manager();
848 TextureManager* texture_manager() {
849 return group_->texture_manager();
852 MailboxManager* mailbox_manager() {
853 return group_->mailbox_manager();
856 ImageManager* image_manager() { return image_manager_.get(); }
858 VertexArrayManager* vertex_array_manager() {
859 return vertex_array_manager_.get();
862 MemoryTracker* memory_tracker() {
863 return group_->memory_tracker();
866 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
867 MemoryTracker* tracker = memory_tracker();
868 if (tracker) {
869 return tracker->EnsureGPUMemoryAvailable(estimated_size);
871 return true;
874 bool IsWebGLContext() const {
875 return webgl_version_ == 1 || webgl_version_ == 2;
878 bool IsOffscreenBufferMultisampled() const {
879 return offscreen_target_samples_ > 1;
882 // Creates a Texture for the given texture.
883 TextureRef* CreateTexture(
884 GLuint client_id, GLuint service_id) {
885 return texture_manager()->CreateTexture(client_id, service_id);
888 // Gets the texture info for the given texture. Returns NULL if none exists.
889 TextureRef* GetTexture(GLuint client_id) const {
890 return texture_manager()->GetTexture(client_id);
893 // Deletes the texture info for the given texture.
894 void RemoveTexture(GLuint client_id) {
895 texture_manager()->RemoveTexture(client_id);
898 // Get the size (in pixels) of the currently bound frame buffer (either FBO
899 // or regular back buffer).
900 gfx::Size GetBoundReadFrameBufferSize();
902 // Get the format/type of the currently bound frame buffer (either FBO or
903 // regular back buffer).
904 // If the color image is a renderbuffer, returns 0 for type.
905 GLenum GetBoundReadFrameBufferTextureType();
906 GLenum GetBoundReadFrameBufferInternalFormat();
908 // Wrapper for CompressedTexImage2D commands.
909 error::Error DoCompressedTexImage2D(
910 GLenum target,
911 GLint level,
912 GLenum internal_format,
913 GLsizei width,
914 GLsizei height,
915 GLint border,
916 GLsizei image_size,
917 const void* data);
919 // Wrapper for CompressedTexImage3D commands.
920 error::Error DoCompressedTexImage3D(
921 GLenum target,
922 GLint level,
923 GLenum internal_format,
924 GLsizei width,
925 GLsizei height,
926 GLsizei depth,
927 GLint border,
928 GLsizei image_size,
929 const void* data);
931 // Wrapper for CompressedTexSubImage2D.
932 void DoCompressedTexSubImage2D(
933 GLenum target,
934 GLint level,
935 GLint xoffset,
936 GLint yoffset,
937 GLsizei width,
938 GLsizei height,
939 GLenum format,
940 GLsizei imageSize,
941 const void * data);
943 // Wrapper for CompressedTexSubImage3D.
944 void DoCompressedTexSubImage3D(
945 GLenum target,
946 GLint level,
947 GLint xoffset,
948 GLint yoffset,
949 GLint zoffset,
950 GLsizei width,
951 GLsizei height,
952 GLsizei depth,
953 GLenum format,
954 GLsizei image_size,
955 const void* data);
957 // Wrapper for CopyTexImage2D.
958 void DoCopyTexImage2D(
959 GLenum target,
960 GLint level,
961 GLenum internal_format,
962 GLint x,
963 GLint y,
964 GLsizei width,
965 GLsizei height,
966 GLint border);
968 // Wrapper for SwapBuffers.
969 void DoSwapBuffers();
971 // Wrapper for SwapInterval.
972 void DoSwapInterval(int interval);
974 // Wrapper for CopyTexSubImage2D.
975 void DoCopyTexSubImage2D(
976 GLenum target,
977 GLint level,
978 GLint xoffset,
979 GLint yoffset,
980 GLint x,
981 GLint y,
982 GLsizei width,
983 GLsizei height);
985 // Validation for TexSubImage2D.
986 bool ValidateTexSubImage2D(
987 error::Error* error,
988 const char* function_name,
989 GLenum target,
990 GLint level,
991 GLint xoffset,
992 GLint yoffset,
993 GLsizei width,
994 GLsizei height,
995 GLenum format,
996 GLenum type,
997 const void * data);
999 // Wrapper for TexSubImage2D.
1000 error::Error DoTexSubImage2D(
1001 GLenum target,
1002 GLint level,
1003 GLint xoffset,
1004 GLint yoffset,
1005 GLsizei width,
1006 GLsizei height,
1007 GLenum format,
1008 GLenum type,
1009 const void * data);
1011 // Wrapper for TexSubImage3D.
1012 error::Error DoTexSubImage3D(
1013 GLenum target,
1014 GLint level,
1015 GLint xoffset,
1016 GLint yoffset,
1017 GLint zoffset,
1018 GLsizei width,
1019 GLsizei height,
1020 GLsizei depth,
1021 GLenum format,
1022 GLenum type,
1023 const void * data);
1025 // Extra validation for async tex(Sub)Image2D.
1026 bool ValidateAsyncTransfer(
1027 const char* function_name,
1028 TextureRef* texture_ref,
1029 GLenum target,
1030 GLint level,
1031 const void * data);
1033 // Wrapper for TexImageIOSurface2DCHROMIUM.
1034 void DoTexImageIOSurface2DCHROMIUM(
1035 GLenum target,
1036 GLsizei width,
1037 GLsizei height,
1038 GLuint io_surface_id,
1039 GLuint plane);
1041 void DoCopyTextureCHROMIUM(GLenum target,
1042 GLuint source_id,
1043 GLuint dest_id,
1044 GLenum internal_format,
1045 GLenum dest_type,
1046 GLboolean unpack_flip_y,
1047 GLboolean unpack_premultiply_alpha,
1048 GLboolean unpack_unmultiply_alpha);
1050 void DoCopySubTextureCHROMIUM(GLenum target,
1051 GLuint source_id,
1052 GLuint dest_id,
1053 GLint xoffset,
1054 GLint yoffset,
1055 GLint x,
1056 GLint y,
1057 GLsizei width,
1058 GLsizei height,
1059 GLboolean unpack_flip_y,
1060 GLboolean unpack_premultiply_alpha,
1061 GLboolean unpack_unmultiply_alpha);
1063 void DoCompressedCopyTextureCHROMIUM(GLenum target,
1064 GLuint source_id,
1065 GLuint dest_id);
1067 void DoCompressedCopySubTextureCHROMIUM(GLenum target,
1068 GLuint source_id,
1069 GLuint dest_id,
1070 GLint xoffset,
1071 GLint yoffset,
1072 GLint x,
1073 GLint y,
1074 GLsizei width,
1075 GLsizei height);
1077 // Wrapper for TexStorage2DEXT.
1078 void DoTexStorage2DEXT(
1079 GLenum target,
1080 GLint levels,
1081 GLenum internal_format,
1082 GLsizei width,
1083 GLsizei height);
1085 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
1086 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
1087 const GLbyte* key);
1088 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
1089 GLenum target, const GLbyte* data);
1091 void EnsureTextureForClientId(GLenum target, GLuint client_id);
1092 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
1093 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
1094 GLuint client_id);
1096 bool DoIsValuebufferCHROMIUM(GLuint client_id);
1097 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
1098 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
1099 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
1100 void DoUniformValueBufferCHROMIUM(GLint location,
1101 GLenum target,
1102 GLenum subscription);
1104 void DoBindTexImage2DCHROMIUM(
1105 GLenum target,
1106 GLint image_id);
1107 void DoReleaseTexImage2DCHROMIUM(
1108 GLenum target,
1109 GLint image_id);
1111 void DoTraceEndCHROMIUM(void);
1113 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1115 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1117 void DoFlushDriverCachesCHROMIUM(void);
1119 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1120 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1122 // Creates a Program for the given program.
1123 Program* CreateProgram(
1124 GLuint client_id, GLuint service_id) {
1125 return program_manager()->CreateProgram(client_id, service_id);
1128 // Gets the program info for the given program. Returns NULL if none exists.
1129 Program* GetProgram(GLuint client_id) {
1130 return program_manager()->GetProgram(client_id);
1133 #if defined(NDEBUG)
1134 void LogClientServiceMapping(
1135 const char* /* function_name */,
1136 GLuint /* client_id */,
1137 GLuint /* service_id */) {
1139 template<typename T>
1140 void LogClientServiceForInfo(
1141 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1143 #else
1144 void LogClientServiceMapping(
1145 const char* function_name, GLuint client_id, GLuint service_id) {
1146 if (service_logging_) {
1147 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1148 << ": client_id = " << client_id
1149 << ", service_id = " << service_id;
1152 template<typename T>
1153 void LogClientServiceForInfo(
1154 T* info, GLuint client_id, const char* function_name) {
1155 if (info) {
1156 LogClientServiceMapping(function_name, client_id, info->service_id());
1159 #endif
1161 // Gets the program info for the given program. If it's not a program
1162 // generates a GL error. Returns NULL if not program.
1163 Program* GetProgramInfoNotShader(
1164 GLuint client_id, const char* function_name) {
1165 Program* program = GetProgram(client_id);
1166 if (!program) {
1167 if (GetShader(client_id)) {
1168 LOCAL_SET_GL_ERROR(
1169 GL_INVALID_OPERATION, function_name, "shader passed for program");
1170 } else {
1171 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1174 LogClientServiceForInfo(program, client_id, function_name);
1175 return program;
1179 // Creates a Shader for the given shader.
1180 Shader* CreateShader(
1181 GLuint client_id,
1182 GLuint service_id,
1183 GLenum shader_type) {
1184 return shader_manager()->CreateShader(
1185 client_id, service_id, shader_type);
1188 // Gets the shader info for the given shader. Returns NULL if none exists.
1189 Shader* GetShader(GLuint client_id) {
1190 return shader_manager()->GetShader(client_id);
1193 // Gets the shader info for the given shader. If it's not a shader generates a
1194 // GL error. Returns NULL if not shader.
1195 Shader* GetShaderInfoNotProgram(
1196 GLuint client_id, const char* function_name) {
1197 Shader* shader = GetShader(client_id);
1198 if (!shader) {
1199 if (GetProgram(client_id)) {
1200 LOCAL_SET_GL_ERROR(
1201 GL_INVALID_OPERATION, function_name, "program passed for shader");
1202 } else {
1203 LOCAL_SET_GL_ERROR(
1204 GL_INVALID_VALUE, function_name, "unknown shader");
1207 LogClientServiceForInfo(shader, client_id, function_name);
1208 return shader;
1211 // Creates a buffer info for the given buffer.
1212 void CreateBuffer(GLuint client_id, GLuint service_id) {
1213 return buffer_manager()->CreateBuffer(client_id, service_id);
1216 // Gets the buffer info for the given buffer.
1217 Buffer* GetBuffer(GLuint client_id) {
1218 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1219 return buffer;
1222 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1223 // on glDeleteBuffers so we can make sure the user does not try to render
1224 // with deleted buffers.
1225 void RemoveBuffer(GLuint client_id);
1227 // Creates a framebuffer info for the given framebuffer.
1228 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1229 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1232 // Gets the framebuffer info for the given framebuffer.
1233 Framebuffer* GetFramebuffer(GLuint client_id) {
1234 return framebuffer_manager()->GetFramebuffer(client_id);
1237 // Removes the framebuffer info for the given framebuffer.
1238 void RemoveFramebuffer(GLuint client_id) {
1239 framebuffer_manager()->RemoveFramebuffer(client_id);
1242 // Creates a renderbuffer info for the given renderbuffer.
1243 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1244 return renderbuffer_manager()->CreateRenderbuffer(
1245 client_id, service_id);
1248 // Gets the renderbuffer info for the given renderbuffer.
1249 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1250 return renderbuffer_manager()->GetRenderbuffer(client_id);
1253 // Removes the renderbuffer info for the given renderbuffer.
1254 void RemoveRenderbuffer(GLuint client_id) {
1255 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1258 // Creates a valuebuffer info for the given valuebuffer.
1259 void CreateValuebuffer(GLuint client_id) {
1260 return valuebuffer_manager()->CreateValuebuffer(client_id);
1263 // Gets the valuebuffer info for a given valuebuffer.
1264 Valuebuffer* GetValuebuffer(GLuint client_id) {
1265 return valuebuffer_manager()->GetValuebuffer(client_id);
1268 // Removes the valuebuffer info for the given valuebuffer.
1269 void RemoveValuebuffer(GLuint client_id) {
1270 valuebuffer_manager()->RemoveValuebuffer(client_id);
1273 // Gets the vertex attrib manager for the given vertex array.
1274 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1275 VertexAttribManager* info =
1276 vertex_array_manager()->GetVertexAttribManager(client_id);
1277 return info;
1280 // Removes the vertex attrib manager for the given vertex array.
1281 void RemoveVertexAttribManager(GLuint client_id) {
1282 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1285 // Creates a vertex attrib manager for the given vertex array.
1286 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1287 GLuint client_id,
1288 GLuint service_id,
1289 bool client_visible) {
1290 return vertex_array_manager()->CreateVertexAttribManager(
1291 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1294 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1295 void DoBindUniformLocationCHROMIUM(
1296 GLuint client_id, GLint location, const char* name);
1298 error::Error GetAttribLocationHelper(
1299 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1300 const std::string& name_str);
1302 error::Error GetUniformLocationHelper(
1303 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1304 const std::string& name_str);
1306 error::Error GetFragDataLocationHelper(
1307 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1308 const std::string& name_str);
1310 // Wrapper for glShaderSource.
1311 void DoShaderSource(
1312 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1314 // Wrapper for glTransformFeedbackVaryings.
1315 void DoTransformFeedbackVaryings(
1316 GLuint client_program_id, GLsizei count, const char* const* varyings,
1317 GLenum buffer_mode);
1319 // Clear any textures used by the current program.
1320 bool ClearUnclearedTextures();
1322 // Clears any uncleared attachments attached to the given frame buffer.
1323 // Returns false if there was a generated GL error.
1324 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1326 // overridden from GLES2Decoder
1327 bool ClearLevel(Texture* texture,
1328 unsigned target,
1329 int level,
1330 unsigned format,
1331 unsigned type,
1332 int xoffset,
1333 int yoffset,
1334 int width,
1335 int height) override;
1337 // Restore all GL state that affects clearing.
1338 void RestoreClearState();
1340 // Remembers the state of some capabilities.
1341 // Returns: true if glEnable/glDisable should actually be called.
1342 bool SetCapabilityState(GLenum cap, bool enabled);
1344 // Check that the currently bound framebuffers are valid.
1345 // Generates GL error if not.
1346 bool CheckBoundFramebuffersValid(const char* func_name);
1348 // Check that the currently bound read framebuffer has a color image
1349 // attached. Generates GL error if not.
1350 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1352 // Check that the currently bound read framebuffer's color image
1353 // isn't the target texture of the glCopyTex{Sub}Image2D.
1354 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1356 // Check if a framebuffer meets our requirements.
1357 bool CheckFramebufferValid(
1358 Framebuffer* framebuffer,
1359 GLenum target,
1360 const char* func_name);
1362 // Check if the current valuebuffer exists and is valid. If not generates
1363 // the appropriate GL error. Returns true if the current valuebuffer is in
1364 // a usable state.
1365 bool CheckCurrentValuebuffer(const char* function_name);
1367 // Check if the current valuebuffer exists and is valiud and that the
1368 // value buffer is actually subscribed to the given subscription
1369 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1370 const char* function_name);
1372 // Check if the location can be used for the given subscription target. If not
1373 // generates the appropriate GL error. Returns true if the location is usable
1374 bool CheckSubscriptionTarget(GLint location,
1375 GLenum subscription,
1376 const char* function_name);
1378 // Checks if the current program exists and is valid. If not generates the
1379 // appropriate GL error. Returns true if the current program is in a usable
1380 // state.
1381 bool CheckCurrentProgram(const char* function_name);
1383 // Checks if the current program exists and is valid and that location is not
1384 // -1. If the current program is not valid generates the appropriate GL
1385 // error. Returns true if the current program is in a usable state and
1386 // location is not -1.
1387 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1389 // Checks if the current program samples a texture that is also the color
1390 // image of the current bound framebuffer, i.e., the source and destination
1391 // of the draw operation are the same.
1392 bool CheckDrawingFeedbackLoops();
1394 // Checks if |api_type| is valid for the given uniform
1395 // If the api type is not valid generates the appropriate GL
1396 // error. Returns true if |api_type| is valid for the uniform
1397 bool CheckUniformForApiType(const Program::UniformInfo* info,
1398 const char* function_name,
1399 Program::UniformApiType api_type);
1401 // Gets the type of a uniform for a location in the current program. Sets GL
1402 // errors if the current program is not valid. Returns true if the current
1403 // program is valid and the location exists. Adjusts count so it
1404 // does not overflow the uniform.
1405 bool PrepForSetUniformByLocation(GLint fake_location,
1406 const char* function_name,
1407 Program::UniformApiType api_type,
1408 GLint* real_location,
1409 GLenum* type,
1410 GLsizei* count);
1412 // Gets the service id for any simulated backbuffer fbo.
1413 GLuint GetBackbufferServiceId() const;
1415 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1416 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1418 // Helper for glGetVertexAttrib
1419 void GetVertexAttribHelper(
1420 const VertexAttrib* attrib, GLenum pname, GLint* param);
1422 // Wrapper for glActiveTexture
1423 void DoActiveTexture(GLenum texture_unit);
1425 // Wrapper for glAttachShader
1426 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1428 // Wrapper for glBindBuffer since we need to track the current targets.
1429 void DoBindBuffer(GLenum target, GLuint buffer);
1431 // Wrapper for glBindFramebuffer since we need to track the current targets.
1432 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1434 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1435 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1437 // Wrapper for glBindTexture since we need to track the current targets.
1438 void DoBindTexture(GLenum target, GLuint texture);
1440 // Wrapper for glBindVertexArrayOES
1441 void DoBindVertexArrayOES(GLuint array);
1442 void EmulateVertexArrayState();
1444 // Wrapper for glBlitFramebufferCHROMIUM.
1445 void DoBlitFramebufferCHROMIUM(
1446 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1447 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1448 GLbitfield mask, GLenum filter);
1450 // Wrapper for glBufferSubData.
1451 void DoBufferSubData(
1452 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1454 // Wrapper for glCheckFramebufferStatus
1455 GLenum DoCheckFramebufferStatus(GLenum target);
1457 // Wrapper for glClear
1458 error::Error DoClear(GLbitfield mask);
1460 // Wrappers for various state.
1461 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1462 void DoSampleCoverage(GLclampf value, GLboolean invert);
1464 // Wrapper for glCompileShader.
1465 void DoCompileShader(GLuint shader);
1467 // Wrapper for glDetachShader
1468 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1470 // Wrapper for glDisable
1471 void DoDisable(GLenum cap);
1473 // Wrapper for glDisableVertexAttribArray.
1474 void DoDisableVertexAttribArray(GLuint index);
1476 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1477 // attachments.
1478 void DoDiscardFramebufferEXT(GLenum target,
1479 GLsizei numAttachments,
1480 const GLenum* attachments);
1482 // Wrapper for glEnable
1483 void DoEnable(GLenum cap);
1485 // Wrapper for glEnableVertexAttribArray.
1486 void DoEnableVertexAttribArray(GLuint index);
1488 // Wrapper for glFinish.
1489 void DoFinish();
1491 // Wrapper for glFlush.
1492 void DoFlush();
1494 // Wrapper for glFramebufferRenderbufffer.
1495 void DoFramebufferRenderbuffer(
1496 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1497 GLuint renderbuffer);
1499 // Wrapper for glFramebufferTexture2D.
1500 void DoFramebufferTexture2D(
1501 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1502 GLint level);
1504 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1505 void DoFramebufferTexture2DMultisample(
1506 GLenum target, GLenum attachment, GLenum textarget,
1507 GLuint texture, GLint level, GLsizei samples);
1509 // Common implementation for both DoFramebufferTexture2D wrappers.
1510 void DoFramebufferTexture2DCommon(const char* name,
1511 GLenum target, GLenum attachment, GLenum textarget,
1512 GLuint texture, GLint level, GLsizei samples);
1514 // Wrapper for glFramebufferTextureLayer.
1515 void DoFramebufferTextureLayer(
1516 GLenum target, GLenum attachment, GLuint texture, GLint level,
1517 GLint layer);
1519 // Wrapper for glGenerateMipmap
1520 void DoGenerateMipmap(GLenum target);
1522 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1523 // to account for different pname values defined in different extension
1524 // variants.
1525 GLenum AdjustGetPname(GLenum pname);
1527 // Wrapper for DoGetBooleanv.
1528 void DoGetBooleanv(GLenum pname, GLboolean* params);
1530 // Wrapper for DoGetFloatv.
1531 void DoGetFloatv(GLenum pname, GLfloat* params);
1533 // Wrapper for glGetFramebufferAttachmentParameteriv.
1534 void DoGetFramebufferAttachmentParameteriv(
1535 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1537 // Wrapper for glGetInteger64v.
1538 void DoGetInteger64v(GLenum pname, GLint64* params);
1540 // Wrapper for glGetIntegerv.
1541 void DoGetIntegerv(GLenum pname, GLint* params);
1543 // Gets the max value in a range in a buffer.
1544 GLuint DoGetMaxValueInBufferCHROMIUM(
1545 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1547 // Wrapper for glGetBufferParameteri64v.
1548 void DoGetBufferParameteri64v(
1549 GLenum target, GLenum pname, GLint64* params);
1551 // Wrapper for glGetBufferParameteriv.
1552 void DoGetBufferParameteriv(
1553 GLenum target, GLenum pname, GLint* params);
1555 // Wrapper for glGetProgramiv.
1556 void DoGetProgramiv(
1557 GLuint program_id, GLenum pname, GLint* params);
1559 // Wrapper for glRenderbufferParameteriv.
1560 void DoGetRenderbufferParameteriv(
1561 GLenum target, GLenum pname, GLint* params);
1563 // Wrapper for glGetShaderiv
1564 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1566 // Wrappers for glGetTexParameter.
1567 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1568 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1569 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1571 // Wrappers for glGetVertexAttrib.
1572 template <typename T>
1573 void DoGetVertexAttribImpl(GLuint index, GLenum pname, T* params);
1574 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
1575 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
1576 void DoGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
1577 void DoGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
1579 // Wrappers for glIsXXX functions.
1580 bool DoIsEnabled(GLenum cap);
1581 bool DoIsBuffer(GLuint client_id);
1582 bool DoIsFramebuffer(GLuint client_id);
1583 bool DoIsProgram(GLuint client_id);
1584 bool DoIsRenderbuffer(GLuint client_id);
1585 bool DoIsShader(GLuint client_id);
1586 bool DoIsTexture(GLuint client_id);
1587 bool DoIsVertexArrayOES(GLuint client_id);
1588 bool DoIsPathCHROMIUM(GLuint client_id);
1590 // Wrapper for glLinkProgram
1591 void DoLinkProgram(GLuint program);
1593 // Wrapper for glReadBuffer
1594 void DoReadBuffer(GLenum src);
1596 // Wrapper for glRenderbufferStorage.
1597 void DoRenderbufferStorage(
1598 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1600 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1601 void DoRenderbufferStorageMultisampleCHROMIUM(
1602 GLenum target, GLsizei samples, GLenum internalformat,
1603 GLsizei width, GLsizei height);
1605 // Handler for glRenderbufferStorageMultisampleEXT
1606 // (multisampled_render_to_texture).
1607 void DoRenderbufferStorageMultisampleEXT(
1608 GLenum target, GLsizei samples, GLenum internalformat,
1609 GLsizei width, GLsizei height);
1611 // Common validation for multisample extensions.
1612 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1613 GLenum internalformat,
1614 GLsizei width,
1615 GLsizei height);
1617 // Verifies that the currently bound multisample renderbuffer is valid
1618 // Very slow! Only done on platforms with driver bugs that return invalid
1619 // buffers under memory pressure
1620 bool VerifyMultisampleRenderbufferIntegrity(
1621 GLuint renderbuffer, GLenum format);
1623 // Wrapper for glReleaseShaderCompiler.
1624 void DoReleaseShaderCompiler() { }
1626 // Wrappers for glSamplerParameter*v functions.
1627 void DoSamplerParameterfv(
1628 GLuint sampler, GLenum pname, const GLfloat* params);
1629 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1631 // Wrappers for glTexParameter functions.
1632 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1633 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1634 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1635 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1637 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1638 // spec only these 2 functions can be used to set sampler uniforms.
1639 void DoUniform1i(GLint fake_location, GLint v0);
1640 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1641 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1642 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1643 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1645 // Wrappers for glUniformfv because some drivers don't correctly accept
1646 // bool uniforms.
1647 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1648 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1649 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1650 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1652 void DoUniformMatrix2fv(
1653 GLint fake_location, GLsizei count, GLboolean transpose,
1654 const GLfloat* value);
1655 void DoUniformMatrix3fv(
1656 GLint fake_location, GLsizei count, GLboolean transpose,
1657 const GLfloat* value);
1658 void DoUniformMatrix4fv(
1659 GLint fake_location, GLsizei count, GLboolean transpose,
1660 const GLfloat* value);
1662 template <typename T>
1663 bool SetVertexAttribValue(
1664 const char* function_name, GLuint index, const T* value);
1666 // Wrappers for glVertexAttrib??
1667 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1668 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1669 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1670 void DoVertexAttrib4f(
1671 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1672 void DoVertexAttrib1fv(GLuint index, const GLfloat* v);
1673 void DoVertexAttrib2fv(GLuint index, const GLfloat* v);
1674 void DoVertexAttrib3fv(GLuint index, const GLfloat* v);
1675 void DoVertexAttrib4fv(GLuint index, const GLfloat* v);
1676 void DoVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
1677 void DoVertexAttribI4iv(GLuint index, const GLint* v);
1678 void DoVertexAttribI4ui(
1679 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
1680 void DoVertexAttribI4uiv(GLuint index, const GLuint* v);
1682 // Wrapper for glViewport
1683 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1685 // Wrapper for glUseProgram
1686 void DoUseProgram(GLuint program);
1688 // Wrapper for glValidateProgram.
1689 void DoValidateProgram(GLuint program_client_id);
1691 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1692 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1693 void DoPopGroupMarkerEXT(void);
1695 // Gets the number of values that will be returned by glGetXXX. Returns
1696 // false if pname is unknown.
1697 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1699 // Checks if the current program and vertex attributes are valid for drawing.
1700 bool IsDrawValid(
1701 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1702 GLsizei primcount);
1704 // Returns true if successful, simulated will be true if attrib0 was
1705 // simulated.
1706 bool SimulateAttrib0(
1707 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1708 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1710 // If an image is bound to texture, this will call Will/DidUseTexImage
1711 // if needed.
1712 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1713 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1715 // Returns false if textures were replaced.
1716 bool PrepareTexturesForRender();
1717 void RestoreStateForTextures();
1719 // Returns true if GL_FIXED attribs were simulated.
1720 bool SimulateFixedAttribs(
1721 const char* function_name,
1722 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1723 void RestoreStateForSimulatedFixedAttribs();
1725 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1726 // cases (primcount is always 1 for non-instanced).
1727 error::Error DoDrawArrays(
1728 const char* function_name,
1729 bool instanced, GLenum mode, GLint first, GLsizei count,
1730 GLsizei primcount);
1731 error::Error DoDrawElements(
1732 const char* function_name,
1733 bool instanced, GLenum mode, GLsizei count, GLenum type,
1734 int32 offset, GLsizei primcount);
1736 GLenum GetBindTargetForSamplerType(GLenum type) {
1737 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1738 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1739 switch (type) {
1740 case GL_SAMPLER_2D:
1741 return GL_TEXTURE_2D;
1742 case GL_SAMPLER_CUBE:
1743 return GL_TEXTURE_CUBE_MAP;
1744 case GL_SAMPLER_EXTERNAL_OES:
1745 return GL_TEXTURE_EXTERNAL_OES;
1746 case GL_SAMPLER_2D_RECT_ARB:
1747 return GL_TEXTURE_RECTANGLE_ARB;
1750 NOTREACHED();
1751 return 0;
1754 // Gets the framebuffer info for a particular target.
1755 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1756 Framebuffer* framebuffer = NULL;
1757 switch (target) {
1758 case GL_FRAMEBUFFER:
1759 case GL_DRAW_FRAMEBUFFER_EXT:
1760 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1761 break;
1762 case GL_READ_FRAMEBUFFER_EXT:
1763 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1764 break;
1765 default:
1766 NOTREACHED();
1767 break;
1769 return framebuffer;
1772 Renderbuffer* GetRenderbufferInfoForTarget(
1773 GLenum target) {
1774 Renderbuffer* renderbuffer = NULL;
1775 switch (target) {
1776 case GL_RENDERBUFFER:
1777 renderbuffer = state_.bound_renderbuffer.get();
1778 break;
1779 default:
1780 NOTREACHED();
1781 break;
1783 return renderbuffer;
1786 // Validates the program and location for a glGetUniform call and returns
1787 // a SizeResult setup to receive the result. Returns true if glGetUniform
1788 // should be called.
1789 template <class T>
1790 bool GetUniformSetup(GLuint program,
1791 GLint fake_location,
1792 uint32 shm_id,
1793 uint32 shm_offset,
1794 error::Error* error,
1795 GLint* real_location,
1796 GLuint* service_id,
1797 SizedResult<T>** result,
1798 GLenum* result_type,
1799 GLsizei* result_size);
1801 bool WasContextLost() const override;
1802 bool WasContextLostByRobustnessExtension() const override;
1803 void MarkContextLost(error::ContextLostReason reason) override;
1804 bool CheckResetStatus();
1806 #if defined(OS_MACOSX)
1807 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1808 #endif
1810 bool GetCompressedTexSizeInBytes(
1811 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1812 GLenum format, GLsizei* size_in_bytes);
1814 bool ValidateCompressedTexDimensions(
1815 const char* function_name, GLenum target, GLint level,
1816 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1817 bool ValidateCompressedTexFuncData(
1818 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1819 GLenum format, GLsizei size);
1820 bool ValidateCompressedTexSubDimensions(
1821 const char* function_name,
1822 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1823 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1824 Texture* texture);
1825 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1826 GLenum target,
1827 TextureRef* source_texture_ref,
1828 TextureRef* dest_texture_ref,
1829 GLenum dest_internal_format);
1830 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name,
1831 GLenum target,
1832 TextureRef* source_texture_ref,
1833 TextureRef* dest_texture_ref);
1835 void RenderWarning(const char* filename, int line, const std::string& msg);
1836 void PerformanceWarning(
1837 const char* filename, int line, const std::string& msg);
1839 const FeatureInfo::FeatureFlags& features() const {
1840 return feature_info_->feature_flags();
1843 const FeatureInfo::Workarounds& workarounds() const {
1844 return feature_info_->workarounds();
1847 bool ShouldDeferDraws() {
1848 return !offscreen_target_frame_buffer_.get() &&
1849 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1850 surface_->DeferDraws();
1853 bool ShouldDeferReads() {
1854 return !offscreen_target_frame_buffer_.get() &&
1855 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1856 surface_->DeferDraws();
1859 bool IsRobustnessSupported() {
1860 return has_robustness_extension_ &&
1861 context_->WasAllocatedUsingRobustnessExtension();
1864 error::Error WillAccessBoundFramebufferForDraw() {
1865 if (ShouldDeferDraws())
1866 return error::kDeferCommandUntilLater;
1867 if (!offscreen_target_frame_buffer_.get() &&
1868 !framebuffer_state_.bound_draw_framebuffer.get() &&
1869 !surface_->SetBackbufferAllocation(true))
1870 return error::kLostContext;
1871 return error::kNoError;
1874 error::Error WillAccessBoundFramebufferForRead() {
1875 if (ShouldDeferReads())
1876 return error::kDeferCommandUntilLater;
1877 if (!offscreen_target_frame_buffer_.get() &&
1878 !framebuffer_state_.bound_read_framebuffer.get() &&
1879 !surface_->SetBackbufferAllocation(true))
1880 return error::kLostContext;
1881 return error::kNoError;
1884 bool BackBufferHasAlpha() const {
1885 if (back_buffer_draw_buffer_ == GL_NONE)
1886 return false;
1887 if (offscreen_target_frame_buffer_.get()) {
1888 return (offscreen_target_color_format_ == GL_RGBA ||
1889 offscreen_target_color_format_ == GL_RGBA8);
1891 return (back_buffer_color_format_ == GL_RGBA ||
1892 back_buffer_color_format_ == GL_RGBA8);
1895 // Set remaining commands to process to 0 to force DoCommands to return
1896 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1897 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1899 void ProcessPendingReadPixels(bool did_finish);
1900 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1902 // Generate a member function prototype for each command in an automated and
1903 // typesafe way.
1904 #define GLES2_CMD_OP(name) \
1905 Error Handle##name(uint32 immediate_data_size, const void* data);
1907 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1909 #undef GLES2_CMD_OP
1911 // The GL context this decoder renders to on behalf of the client.
1912 scoped_refptr<gfx::GLSurface> surface_;
1913 scoped_refptr<gfx::GLContext> context_;
1915 // The ContextGroup for this decoder uses to track resources.
1916 scoped_refptr<ContextGroup> group_;
1918 DebugMarkerManager debug_marker_manager_;
1919 Logger logger_;
1921 // All the state for this context.
1922 ContextState state_;
1924 // Current width and height of the offscreen frame buffer.
1925 gfx::Size offscreen_size_;
1927 // Util to help with GL.
1928 GLES2Util util_;
1930 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1931 GLuint attrib_0_buffer_id_;
1933 // The value currently in attrib_0.
1934 Vec4 attrib_0_value_;
1936 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1937 bool attrib_0_buffer_matches_value_;
1939 // The size of attrib 0.
1940 GLsizei attrib_0_size_;
1942 // The buffer used to simulate GL_FIXED attribs.
1943 GLuint fixed_attrib_buffer_id_;
1945 // The size of fiixed attrib buffer.
1946 GLsizei fixed_attrib_buffer_size_;
1948 // The offscreen frame buffer that the client renders to. With EGL, the
1949 // depth and stencil buffers are separate. With regular GL there is a single
1950 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1951 // offscreen_target_stencil_render_buffer_ is unused.
1952 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1953 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1954 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1955 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1956 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1957 GLenum offscreen_target_color_format_;
1958 GLenum offscreen_target_depth_format_;
1959 GLenum offscreen_target_stencil_format_;
1960 GLsizei offscreen_target_samples_;
1961 GLboolean offscreen_target_buffer_preserved_;
1963 // The copy that is saved when SwapBuffers is called.
1964 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1965 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1966 scoped_refptr<TextureRef>
1967 offscreen_saved_color_texture_info_;
1969 // The copy that is used as the destination for multi-sample resolves.
1970 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1971 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1972 GLenum offscreen_saved_color_format_;
1974 scoped_ptr<QueryManager> query_manager_;
1976 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1978 scoped_ptr<ImageManager> image_manager_;
1980 base::Callback<void(gfx::Size, float)> resize_callback_;
1982 WaitSyncPointCallback wait_sync_point_callback_;
1984 ShaderCacheCallback shader_cache_callback_;
1986 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1988 // The format of the back buffer_
1989 GLenum back_buffer_color_format_;
1990 bool back_buffer_has_depth_;
1991 bool back_buffer_has_stencil_;
1993 // Tracks read buffer and draw buffer for backbuffer, whether it's onscreen
1994 // or offscreen.
1995 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
1996 // setting is set correctly when SwapBuffers().
1997 GLenum back_buffer_read_buffer_;
1998 GLenum back_buffer_draw_buffer_;
2000 bool surfaceless_;
2002 // Backbuffer attachments that are currently undefined.
2003 uint32 backbuffer_needs_clear_bits_;
2005 // The current decoder error communicates the decoder error through command
2006 // processing functions that do not return the error value. Should be set only
2007 // if not returning an error.
2008 error::Error current_decoder_error_;
2010 bool use_shader_translator_;
2011 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
2012 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
2014 DisallowedFeatures disallowed_features_;
2016 // Cached from ContextGroup
2017 const Validators* validators_;
2018 scoped_refptr<FeatureInfo> feature_info_;
2020 int frame_number_;
2022 // Number of commands remaining to be processed in DoCommands().
2023 int commands_to_process_;
2025 bool has_robustness_extension_;
2026 error::ContextLostReason context_lost_reason_;
2027 bool context_was_lost_;
2028 bool reset_by_robustness_extension_;
2029 bool supports_post_sub_buffer_;
2031 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2032 // 0: other types
2033 // 1: WebGL 1
2034 // 2: WebGL 2
2035 unsigned webgl_version_;
2037 // These flags are used to override the state of the shared feature_info_
2038 // member. Because the same FeatureInfo instance may be shared among many
2039 // contexts, the assumptions on the availablity of extensions in WebGL
2040 // contexts may be broken. These flags override the shared state to preserve
2041 // WebGL semantics.
2042 bool derivatives_explicitly_enabled_;
2043 bool frag_depth_explicitly_enabled_;
2044 bool draw_buffers_explicitly_enabled_;
2045 bool shader_texture_lod_explicitly_enabled_;
2047 bool compile_shader_always_succeeds_;
2049 // An optional behaviour to lose the context and group when OOM.
2050 bool lose_context_when_out_of_memory_;
2052 // Log extra info.
2053 bool service_logging_;
2055 #if defined(OS_MACOSX)
2056 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
2057 TextureToIOSurfaceMap texture_to_io_surface_map_;
2058 #endif
2060 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
2061 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
2063 // Cached values of the currently assigned viewport dimensions.
2064 GLsizei viewport_max_width_;
2065 GLsizei viewport_max_height_;
2067 // Command buffer stats.
2068 base::TimeDelta total_processing_commands_time_;
2070 // States related to each manager.
2071 DecoderTextureState texture_state_;
2072 DecoderFramebufferState framebuffer_state_;
2074 scoped_ptr<GPUTracer> gpu_tracer_;
2075 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
2076 const unsigned char* cb_command_trace_category_;
2077 const unsigned char* gpu_decoder_category_;
2078 int gpu_trace_level_;
2079 bool gpu_trace_commands_;
2080 bool gpu_debug_commands_;
2082 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
2084 // Used to validate multisample renderbuffers if needed
2085 GLuint validation_texture_;
2086 GLuint validation_fbo_multisample_;
2087 GLuint validation_fbo_;
2089 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
2090 uint32 immediate_data_size,
2091 const void* data);
2093 // A struct to hold info about each command.
2094 struct CommandInfo {
2095 CmdHandler cmd_handler;
2096 uint8 arg_flags; // How to handle the arguments for this command
2097 uint8 cmd_flags; // How to handle this command
2098 uint16 arg_count; // How many arguments are expected for this command.
2101 // A table of CommandInfo for all the commands.
2102 static const CommandInfo command_info[kNumCommands - kStartPoint];
2104 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
2107 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
2108 #define GLES2_CMD_OP(name) \
2110 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2111 cmds::name::cmd_flags, \
2112 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2114 , /* NOLINT */
2115 GLES2_COMMAND_LIST(GLES2_CMD_OP)
2116 #undef GLES2_CMD_OP
2119 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2120 const char* function_name, ErrorState* error_state)
2121 : function_name_(function_name),
2122 error_state_(error_state) {
2123 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
2126 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2127 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
2130 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
2131 TextureUnit& info = state->texture_units[0];
2132 GLuint last_id;
2133 scoped_refptr<TextureRef> texture_ref;
2134 switch (target) {
2135 case GL_TEXTURE_2D:
2136 texture_ref = info.bound_texture_2d;
2137 break;
2138 case GL_TEXTURE_CUBE_MAP:
2139 texture_ref = info.bound_texture_cube_map;
2140 break;
2141 case GL_TEXTURE_EXTERNAL_OES:
2142 texture_ref = info.bound_texture_external_oes;
2143 break;
2144 case GL_TEXTURE_RECTANGLE_ARB:
2145 texture_ref = info.bound_texture_rectangle_arb;
2146 break;
2147 default:
2148 NOTREACHED();
2149 break;
2151 if (texture_ref.get()) {
2152 last_id = texture_ref->service_id();
2153 } else {
2154 last_id = 0;
2157 glBindTexture(target, last_id);
2158 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2161 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2162 GLuint id,
2163 GLenum target)
2164 : state_(state),
2165 target_(target) {
2166 ScopedGLErrorSuppressor suppressor(
2167 "ScopedTextureBinder::ctor", state_->GetErrorState());
2169 // TODO(apatrick): Check if there are any other states that need to be reset
2170 // before binding a new texture.
2171 glActiveTexture(GL_TEXTURE0);
2172 glBindTexture(target, id);
2175 ScopedTextureBinder::~ScopedTextureBinder() {
2176 ScopedGLErrorSuppressor suppressor(
2177 "ScopedTextureBinder::dtor", state_->GetErrorState());
2178 RestoreCurrentTextureBindings(state_, target_);
2181 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2182 GLuint id)
2183 : state_(state) {
2184 ScopedGLErrorSuppressor suppressor(
2185 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2186 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2189 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2190 ScopedGLErrorSuppressor suppressor(
2191 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2192 state_->RestoreRenderbufferBindings();
2195 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2196 GLuint id)
2197 : decoder_(decoder) {
2198 ScopedGLErrorSuppressor suppressor(
2199 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2200 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2201 decoder->OnFboChanged();
2204 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2205 ScopedGLErrorSuppressor suppressor(
2206 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2207 decoder_->RestoreCurrentFramebufferBindings();
2210 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2211 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2212 : decoder_(decoder) {
2213 resolve_and_bind_ = (
2214 decoder_->offscreen_target_frame_buffer_.get() &&
2215 decoder_->IsOffscreenBufferMultisampled() &&
2216 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2217 enforce_internal_framebuffer));
2218 if (!resolve_and_bind_)
2219 return;
2221 ScopedGLErrorSuppressor suppressor(
2222 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2223 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2224 decoder_->offscreen_target_frame_buffer_->id());
2225 GLuint targetid;
2226 if (internal) {
2227 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2228 decoder_->offscreen_resolved_frame_buffer_.reset(
2229 new BackFramebuffer(decoder_));
2230 decoder_->offscreen_resolved_frame_buffer_->Create();
2231 decoder_->offscreen_resolved_color_texture_.reset(
2232 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2233 decoder_->offscreen_resolved_color_texture_->Create();
2235 DCHECK(decoder_->offscreen_saved_color_format_);
2236 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2237 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2238 false);
2239 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2240 decoder_->offscreen_resolved_color_texture_.get());
2241 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2242 GL_FRAMEBUFFER_COMPLETE) {
2243 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2244 << "because offscreen resolved FBO was incomplete.";
2245 return;
2248 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2249 } else {
2250 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2252 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2253 const int width = decoder_->offscreen_size_.width();
2254 const int height = decoder_->offscreen_size_.height();
2255 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2256 decoder->BlitFramebufferHelper(0,
2258 width,
2259 height,
2262 width,
2263 height,
2264 GL_COLOR_BUFFER_BIT,
2265 GL_NEAREST);
2266 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2269 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2270 if (!resolve_and_bind_)
2271 return;
2273 ScopedGLErrorSuppressor suppressor(
2274 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2275 decoder_->RestoreCurrentFramebufferBindings();
2276 if (decoder_->state_.enable_flags.scissor_test) {
2277 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2281 BackTexture::BackTexture(
2282 MemoryTracker* memory_tracker,
2283 ContextState* state)
2284 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2285 state_(state),
2286 bytes_allocated_(0),
2287 id_(0) {
2290 BackTexture::~BackTexture() {
2291 // This does not destroy the render texture because that would require that
2292 // the associated GL context was current. Just check that it was explicitly
2293 // destroyed.
2294 DCHECK_EQ(id_, 0u);
2297 void BackTexture::Create() {
2298 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2299 state_->GetErrorState());
2300 Destroy();
2301 glGenTextures(1, &id_);
2302 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2304 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2305 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2306 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2308 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2309 // never called on an offscreen context, no data will ever be uploaded to the
2310 // saved offscreen color texture (it is deferred until to when SwapBuffers
2311 // is called). My idea is that some nvidia drivers might have a bug where
2312 // deleting a texture that has never been populated might cause a
2313 // crash.
2314 glTexImage2D(
2315 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2317 bytes_allocated_ = 16u * 16u * 4u;
2318 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2321 bool BackTexture::AllocateStorage(
2322 const gfx::Size& size, GLenum format, bool zero) {
2323 DCHECK_NE(id_, 0u);
2324 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2325 state_->GetErrorState());
2326 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2327 uint32 image_size = 0;
2328 GLES2Util::ComputeImageDataSizes(
2329 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2330 NULL, NULL);
2332 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2333 return false;
2336 scoped_ptr<char[]> zero_data;
2337 if (zero) {
2338 zero_data.reset(new char[image_size]);
2339 memset(zero_data.get(), 0, image_size);
2342 glTexImage2D(GL_TEXTURE_2D,
2343 0, // mip level
2344 format,
2345 size.width(),
2346 size.height(),
2347 0, // border
2348 format,
2349 GL_UNSIGNED_BYTE,
2350 zero_data.get());
2352 size_ = size;
2354 bool success = glGetError() == GL_NO_ERROR;
2355 if (success) {
2356 memory_tracker_.TrackMemFree(bytes_allocated_);
2357 bytes_allocated_ = image_size;
2358 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2360 return success;
2363 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2364 DCHECK_NE(id_, 0u);
2365 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2366 state_->GetErrorState());
2367 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2368 glCopyTexImage2D(GL_TEXTURE_2D,
2369 0, // level
2370 format,
2371 0, 0,
2372 size.width(),
2373 size.height(),
2374 0); // border
2377 void BackTexture::Destroy() {
2378 if (id_ != 0) {
2379 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2380 state_->GetErrorState());
2381 glDeleteTextures(1, &id_);
2382 id_ = 0;
2384 memory_tracker_.TrackMemFree(bytes_allocated_);
2385 bytes_allocated_ = 0;
2388 void BackTexture::Invalidate() {
2389 id_ = 0;
2392 BackRenderbuffer::BackRenderbuffer(
2393 RenderbufferManager* renderbuffer_manager,
2394 MemoryTracker* memory_tracker,
2395 ContextState* state)
2396 : renderbuffer_manager_(renderbuffer_manager),
2397 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2398 state_(state),
2399 bytes_allocated_(0),
2400 id_(0) {
2403 BackRenderbuffer::~BackRenderbuffer() {
2404 // This does not destroy the render buffer because that would require that
2405 // the associated GL context was current. Just check that it was explicitly
2406 // destroyed.
2407 DCHECK_EQ(id_, 0u);
2410 void BackRenderbuffer::Create() {
2411 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2412 state_->GetErrorState());
2413 Destroy();
2414 glGenRenderbuffersEXT(1, &id_);
2417 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2418 const gfx::Size& size,
2419 GLenum format,
2420 GLsizei samples) {
2421 ScopedGLErrorSuppressor suppressor(
2422 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2423 ScopedRenderBufferBinder binder(state_, id_);
2425 uint32 estimated_size = 0;
2426 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2427 size.width(), size.height(), samples, format, &estimated_size)) {
2428 return false;
2431 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2432 return false;
2435 if (samples <= 1) {
2436 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2437 format,
2438 size.width(),
2439 size.height());
2440 } else {
2441 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2442 GL_RENDERBUFFER,
2443 samples,
2444 format,
2445 size.width(),
2446 size.height());
2448 bool success = glGetError() == GL_NO_ERROR;
2449 if (success) {
2450 // Mark the previously allocated bytes as free.
2451 memory_tracker_.TrackMemFree(bytes_allocated_);
2452 bytes_allocated_ = estimated_size;
2453 // Track the newly allocated bytes.
2454 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2456 return success;
2459 void BackRenderbuffer::Destroy() {
2460 if (id_ != 0) {
2461 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2462 state_->GetErrorState());
2463 glDeleteRenderbuffersEXT(1, &id_);
2464 id_ = 0;
2466 memory_tracker_.TrackMemFree(bytes_allocated_);
2467 bytes_allocated_ = 0;
2470 void BackRenderbuffer::Invalidate() {
2471 id_ = 0;
2474 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2475 : decoder_(decoder),
2476 id_(0) {
2479 BackFramebuffer::~BackFramebuffer() {
2480 // This does not destroy the frame buffer because that would require that
2481 // the associated GL context was current. Just check that it was explicitly
2482 // destroyed.
2483 DCHECK_EQ(id_, 0u);
2486 void BackFramebuffer::Create() {
2487 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2488 decoder_->GetErrorState());
2489 Destroy();
2490 glGenFramebuffersEXT(1, &id_);
2493 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2494 DCHECK_NE(id_, 0u);
2495 ScopedGLErrorSuppressor suppressor(
2496 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2497 ScopedFrameBufferBinder binder(decoder_, id_);
2498 GLuint attach_id = texture ? texture->id() : 0;
2499 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2500 GL_COLOR_ATTACHMENT0,
2501 GL_TEXTURE_2D,
2502 attach_id,
2506 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2507 BackRenderbuffer* render_buffer) {
2508 DCHECK_NE(id_, 0u);
2509 ScopedGLErrorSuppressor suppressor(
2510 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2511 ScopedFrameBufferBinder binder(decoder_, id_);
2512 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2513 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2514 target,
2515 GL_RENDERBUFFER,
2516 attach_id);
2519 void BackFramebuffer::Destroy() {
2520 if (id_ != 0) {
2521 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2522 decoder_->GetErrorState());
2523 glDeleteFramebuffersEXT(1, &id_);
2524 id_ = 0;
2528 void BackFramebuffer::Invalidate() {
2529 id_ = 0;
2532 GLenum BackFramebuffer::CheckStatus() {
2533 DCHECK_NE(id_, 0u);
2534 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2535 decoder_->GetErrorState());
2536 ScopedFrameBufferBinder binder(decoder_, id_);
2537 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2540 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2541 return new GLES2DecoderImpl(group);
2544 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2545 : GLES2Decoder(),
2546 group_(group),
2547 logger_(&debug_marker_manager_),
2548 state_(group_->feature_info(), this, &logger_),
2549 attrib_0_buffer_id_(0),
2550 attrib_0_buffer_matches_value_(true),
2551 attrib_0_size_(0),
2552 fixed_attrib_buffer_id_(0),
2553 fixed_attrib_buffer_size_(0),
2554 offscreen_target_color_format_(0),
2555 offscreen_target_depth_format_(0),
2556 offscreen_target_stencil_format_(0),
2557 offscreen_target_samples_(0),
2558 offscreen_target_buffer_preserved_(true),
2559 offscreen_saved_color_format_(0),
2560 back_buffer_color_format_(0),
2561 back_buffer_has_depth_(false),
2562 back_buffer_has_stencil_(false),
2563 back_buffer_read_buffer_(GL_BACK),
2564 back_buffer_draw_buffer_(GL_BACK),
2565 surfaceless_(false),
2566 backbuffer_needs_clear_bits_(0),
2567 current_decoder_error_(error::kNoError),
2568 use_shader_translator_(true),
2569 validators_(group_->feature_info()->validators()),
2570 feature_info_(group_->feature_info()),
2571 frame_number_(0),
2572 has_robustness_extension_(false),
2573 context_lost_reason_(error::kUnknown),
2574 context_was_lost_(false),
2575 reset_by_robustness_extension_(false),
2576 supports_post_sub_buffer_(false),
2577 webgl_version_(0),
2578 derivatives_explicitly_enabled_(false),
2579 frag_depth_explicitly_enabled_(false),
2580 draw_buffers_explicitly_enabled_(false),
2581 shader_texture_lod_explicitly_enabled_(false),
2582 compile_shader_always_succeeds_(false),
2583 lose_context_when_out_of_memory_(false),
2584 service_logging_(base::CommandLine::InitializedForCurrentProcess()
2585 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2586 switches::kEnableGPUServiceLoggingGPU)
2587 : false),
2588 viewport_max_width_(0),
2589 viewport_max_height_(0),
2590 texture_state_(group_->feature_info()
2591 ->workarounds()
2592 .texsubimage_faster_than_teximage),
2593 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2594 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2595 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2596 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2597 gpu_trace_level_(2),
2598 gpu_trace_commands_(false),
2599 gpu_debug_commands_(false),
2600 validation_texture_(0),
2601 validation_fbo_multisample_(0),
2602 validation_fbo_(0) {
2603 DCHECK(group);
2605 // The shader translator is used for WebGL even when running on EGL
2606 // because additional restrictions are needed (like only enabling
2607 // GL_OES_standard_derivatives on demand). It is used for the unit
2608 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2609 // the empty string to CompileShader and this is not a valid shader.
2610 bool disable_translator =
2611 base::CommandLine::InitializedForCurrentProcess()
2612 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2613 switches::kDisableGLSLTranslator)
2614 : false;
2615 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2616 disable_translator) {
2617 use_shader_translator_ = false;
2621 GLES2DecoderImpl::~GLES2DecoderImpl() {
2624 bool GLES2DecoderImpl::Initialize(
2625 const scoped_refptr<gfx::GLSurface>& surface,
2626 const scoped_refptr<gfx::GLContext>& context,
2627 bool offscreen,
2628 const gfx::Size& offscreen_size,
2629 const DisallowedFeatures& disallowed_features,
2630 const std::vector<int32>& attribs) {
2631 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2632 DCHECK(context->IsCurrent(surface.get()));
2633 DCHECK(!context_.get());
2634 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2636 ContextCreationAttribHelper attrib_parser;
2637 if (!attrib_parser.Parse(attribs))
2638 return false;
2639 webgl_version_ = attrib_parser.webgl_version;
2641 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2643 set_initialized();
2644 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2646 if (base::CommandLine::InitializedForCurrentProcess()) {
2647 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2648 switches::kEnableGPUDebugging)) {
2649 set_debug(true);
2652 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2653 switches::kEnableGPUCommandLogging)) {
2654 set_log_commands(true);
2657 compile_shader_always_succeeds_ =
2658 base::CommandLine::ForCurrentProcess()->HasSwitch(
2659 switches::kCompileShaderAlwaysSucceeds);
2662 // Take ownership of the context and surface. The surface can be replaced with
2663 // SetSurface.
2664 context_ = context;
2665 surface_ = surface;
2667 // Create GPU Tracer for timing values.
2668 gpu_tracer_.reset(new GPUTracer(this));
2670 if (feature_info_->workarounds().disable_timestamp_queries) {
2671 // Forcing time elapsed query for any GPU Timing Client forces it for all
2672 // clients in the context.
2673 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2676 // Save the loseContextWhenOutOfMemory context creation attribute.
2677 lose_context_when_out_of_memory_ =
2678 attrib_parser.lose_context_when_out_of_memory;
2680 // If the failIfMajorPerformanceCaveat context creation attribute was true
2681 // and we are using a software renderer, fail.
2682 if (attrib_parser.fail_if_major_perf_caveat &&
2683 feature_info_->feature_flags().is_swiftshader) {
2684 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2685 Destroy(true);
2686 return false;
2689 disallowed_features_ = disallowed_features;
2690 if (webgl_version_ == 1) {
2691 disallowed_features_.npot_support = true;
2694 if (!group_->Initialize(this,
2695 ContextGroup::GetContextType(webgl_version_),
2696 disallowed_features_)) {
2697 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2698 Destroy(true);
2699 return false;
2701 CHECK_GL_ERROR();
2703 if (webgl_version_ == 2) {
2704 if (!feature_info_->IsES3Capable()) {
2705 LOG(ERROR) << "Underlying driver does not support ES3.";
2706 Destroy(true);
2707 return false;
2709 feature_info_->EnableES3Validators();
2710 set_unsafe_es3_apis_enabled(true);
2713 state_.attrib_values.resize(group_->max_vertex_attribs());
2714 vertex_array_manager_.reset(new VertexArrayManager());
2716 GLuint default_vertex_attrib_service_id = 0;
2717 if (features().native_vertex_array_object) {
2718 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2719 glBindVertexArrayOES(default_vertex_attrib_service_id);
2722 state_.default_vertex_attrib_manager =
2723 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2725 state_.default_vertex_attrib_manager->Initialize(
2726 group_->max_vertex_attribs(),
2727 feature_info_->workarounds().init_vertex_attributes);
2729 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2730 DoBindVertexArrayOES(0);
2732 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2734 image_manager_.reset(new ImageManager);
2736 util_.set_num_compressed_texture_formats(
2737 validators_->compressed_texture_format.GetValues().size());
2739 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2740 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2741 // OpenGL ES 2.0 does not have this issue.
2742 glEnableVertexAttribArray(0);
2744 glGenBuffersARB(1, &attrib_0_buffer_id_);
2745 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2746 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2747 glBindBuffer(GL_ARRAY_BUFFER, 0);
2748 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2750 state_.texture_units.resize(group_->max_texture_units());
2751 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2752 glActiveTexture(GL_TEXTURE0 + tt);
2753 // We want the last bind to be 2D.
2754 TextureRef* ref;
2755 if (features().oes_egl_image_external) {
2756 ref = texture_manager()->GetDefaultTextureInfo(
2757 GL_TEXTURE_EXTERNAL_OES);
2758 state_.texture_units[tt].bound_texture_external_oes = ref;
2759 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2761 if (features().arb_texture_rectangle) {
2762 ref = texture_manager()->GetDefaultTextureInfo(
2763 GL_TEXTURE_RECTANGLE_ARB);
2764 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2765 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2767 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2768 state_.texture_units[tt].bound_texture_cube_map = ref;
2769 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2770 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2771 state_.texture_units[tt].bound_texture_2d = ref;
2772 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2774 glActiveTexture(GL_TEXTURE0);
2775 CHECK_GL_ERROR();
2777 // cache ALPHA_BITS result for re-use with clear behaviour
2778 GLint alpha_bits = 0;
2780 if (offscreen) {
2781 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2782 features().chromium_framebuffer_multisample) {
2783 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2784 // max_sample_count must be initialized to a sane value. If
2785 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2786 GLint max_sample_count = 1;
2787 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2788 offscreen_target_samples_ = std::min(attrib_parser.samples,
2789 max_sample_count);
2790 } else {
2791 offscreen_target_samples_ = 1;
2793 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2795 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2796 const bool rgb8_supported =
2797 context_->HasExtension("GL_OES_rgb8_rgba8");
2798 // The only available default render buffer formats in GLES2 have very
2799 // little precision. Don't enable multisampling unless 8-bit render
2800 // buffer formats are available--instead fall back to 8-bit textures.
2801 if (rgb8_supported && offscreen_target_samples_ > 1) {
2802 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2803 GL_RGBA8 : GL_RGB8;
2804 } else {
2805 offscreen_target_samples_ = 1;
2806 offscreen_target_color_format_ =
2807 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2808 ? GL_RGBA
2809 : GL_RGB;
2812 // ANGLE only supports packed depth/stencil formats, so use it if it is
2813 // available.
2814 const bool depth24_stencil8_supported =
2815 feature_info_->feature_flags().packed_depth24_stencil8;
2816 VLOG(1) << "GL_OES_packed_depth_stencil "
2817 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2818 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2819 depth24_stencil8_supported) {
2820 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2821 offscreen_target_stencil_format_ = 0;
2822 } else {
2823 // It may be the case that this depth/stencil combination is not
2824 // supported, but this will be checked later by CheckFramebufferStatus.
2825 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2826 GL_DEPTH_COMPONENT16 : 0;
2827 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2828 GL_STENCIL_INDEX8 : 0;
2830 } else {
2831 offscreen_target_color_format_ =
2832 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2833 ? GL_RGBA
2834 : GL_RGB;
2836 // If depth is requested at all, use the packed depth stencil format if
2837 // it's available, as some desktop GL drivers don't support any non-packed
2838 // formats for depth attachments.
2839 const bool depth24_stencil8_supported =
2840 feature_info_->feature_flags().packed_depth24_stencil8;
2841 VLOG(1) << "GL_EXT_packed_depth_stencil "
2842 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2844 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2845 depth24_stencil8_supported) {
2846 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2847 offscreen_target_stencil_format_ = 0;
2848 } else {
2849 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2850 GL_DEPTH_COMPONENT : 0;
2851 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2852 GL_STENCIL_INDEX : 0;
2856 offscreen_saved_color_format_ =
2857 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2858 ? GL_RGBA
2859 : GL_RGB;
2861 // Create the target frame buffer. This is the one that the client renders
2862 // directly to.
2863 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2864 offscreen_target_frame_buffer_->Create();
2865 // Due to GLES2 format limitations, either the color texture (for
2866 // non-multisampling) or the color render buffer (for multisampling) will be
2867 // attached to the offscreen frame buffer. The render buffer has more
2868 // limited formats available to it, but the texture can't do multisampling.
2869 if (IsOffscreenBufferMultisampled()) {
2870 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2871 renderbuffer_manager(), memory_tracker(), &state_));
2872 offscreen_target_color_render_buffer_->Create();
2873 } else {
2874 offscreen_target_color_texture_.reset(new BackTexture(
2875 memory_tracker(), &state_));
2876 offscreen_target_color_texture_->Create();
2878 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2879 renderbuffer_manager(), memory_tracker(), &state_));
2880 offscreen_target_depth_render_buffer_->Create();
2881 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2882 renderbuffer_manager(), memory_tracker(), &state_));
2883 offscreen_target_stencil_render_buffer_->Create();
2885 // Create the saved offscreen texture. The target frame buffer is copied
2886 // here when SwapBuffers is called.
2887 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2888 offscreen_saved_frame_buffer_->Create();
2890 offscreen_saved_color_texture_.reset(new BackTexture(
2891 memory_tracker(), &state_));
2892 offscreen_saved_color_texture_->Create();
2894 // Allocate the render buffers at their initial size and check the status
2895 // of the frame buffers is okay.
2896 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2897 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2898 Destroy(true);
2899 return false;
2902 state_.viewport_width = offscreen_size.width();
2903 state_.viewport_height = offscreen_size.height();
2905 // Allocate the offscreen saved color texture.
2906 DCHECK(offscreen_saved_color_format_);
2907 offscreen_saved_color_texture_->AllocateStorage(
2908 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2910 offscreen_saved_frame_buffer_->AttachRenderTexture(
2911 offscreen_saved_color_texture_.get());
2912 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2913 GL_FRAMEBUFFER_COMPLETE) {
2914 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2915 Destroy(true);
2916 return false;
2919 // Bind to the new default frame buffer (the offscreen target frame buffer).
2920 // This should now be associated with ID zero.
2921 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2922 } else {
2923 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2924 // These are NOT if the back buffer has these proprorties. They are
2925 // if we want the command buffer to enforce them regardless of what
2926 // the real backbuffer is assuming the real back buffer gives us more than
2927 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2928 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2929 // can't do anything about that.
2931 if (!surfaceless_) {
2932 GLint depth_bits = 0;
2933 GLint stencil_bits = 0;
2935 bool default_fb = (GetBackbufferServiceId() == 0);
2937 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2938 glGetFramebufferAttachmentParameterivEXT(
2939 GL_FRAMEBUFFER,
2940 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2941 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2942 glGetFramebufferAttachmentParameterivEXT(
2943 GL_FRAMEBUFFER,
2944 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2945 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2946 glGetFramebufferAttachmentParameterivEXT(
2947 GL_FRAMEBUFFER,
2948 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2949 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2950 } else {
2951 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2952 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2953 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2956 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2957 // the user requested RGB then RGB. If the user did not specify a
2958 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2959 back_buffer_color_format_ =
2960 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2961 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2962 back_buffer_has_stencil_ =
2963 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2966 state_.viewport_width = surface->GetSize().width();
2967 state_.viewport_height = surface->GetSize().height();
2970 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2971 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2972 // isn't well documented; it was discovered in the Khronos OpenGL ES
2973 // mailing list archives. It also implicitly enables the desktop GL
2974 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2975 // variable in fragment shaders.
2976 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2977 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2978 glEnable(GL_POINT_SPRITE);
2981 has_robustness_extension_ =
2982 context->HasExtension("GL_ARB_robustness") ||
2983 context->HasExtension("GL_KHR_robustness") ||
2984 context->HasExtension("GL_EXT_robustness");
2986 if (!InitializeShaderTranslator()) {
2987 return false;
2990 GLint viewport_params[4] = { 0 };
2991 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2992 viewport_max_width_ = viewport_params[0];
2993 viewport_max_height_ = viewport_params[1];
2995 state_.scissor_width = state_.viewport_width;
2996 state_.scissor_height = state_.viewport_height;
2998 // Set all the default state because some GL drivers get it wrong.
2999 state_.InitCapabilities(NULL);
3000 state_.InitState(NULL);
3001 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
3003 DoBindBuffer(GL_ARRAY_BUFFER, 0);
3004 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3005 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
3006 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
3007 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
3009 bool call_gl_clear = !surfaceless_;
3010 #if defined(OS_ANDROID)
3011 // Temporary workaround for Android WebView because this clear ignores the
3012 // clip and corrupts that external UI of the App. Not calling glClear is ok
3013 // because the system already clears the buffer before each draw. Proper
3014 // fix might be setting the scissor clip properly before initialize. See
3015 // crbug.com/259023 for details.
3016 call_gl_clear = surface_->GetHandle();
3017 #endif
3018 if (call_gl_clear) {
3019 // On configs where we report no alpha, if the underlying surface has
3020 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
3021 bool clear_alpha = back_buffer_color_format_ == GL_RGB && alpha_bits > 0;
3022 if (clear_alpha) {
3023 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3026 // Clear the backbuffer.
3027 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3029 // Restore alpha clear value if we changed it.
3030 if (clear_alpha) {
3031 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3035 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
3036 if (feature_info_->workarounds()
3037 .disable_post_sub_buffers_for_onscreen_surfaces &&
3038 !surface->IsOffscreen())
3039 supports_post_sub_buffer_ = false;
3041 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
3042 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
3045 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
3046 context_->SetUnbindFboOnMakeCurrent();
3049 // Only compositor contexts are known to use only the subset of GL
3050 // that can be safely migrated between the iGPU and the dGPU. Mark
3051 // those contexts as safe to forcibly transition between the GPUs.
3052 // http://crbug.com/180876, http://crbug.com/227228
3053 if (!offscreen)
3054 context_->SetSafeToForceGpuSwitch();
3056 async_pixel_transfer_manager_.reset(
3057 AsyncPixelTransferManager::Create(context.get()));
3058 async_pixel_transfer_manager_->Initialize(texture_manager());
3060 if (workarounds().gl_clear_broken) {
3061 DCHECK(!clear_framebuffer_blit_.get());
3062 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3063 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
3064 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
3065 return false;
3068 framebuffer_manager()->AddObserver(this);
3070 return true;
3073 Capabilities GLES2DecoderImpl::GetCapabilities() {
3074 DCHECK(initialized());
3075 Capabilities caps;
3076 caps.VisitPrecisions([](GLenum shader, GLenum type,
3077 Capabilities::ShaderPrecision* shader_precision) {
3078 GLint range[2] = {0, 0};
3079 GLint precision = 0;
3080 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
3081 shader_precision->min_range = range[0];
3082 shader_precision->max_range = range[1];
3083 shader_precision->precision = precision;
3085 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
3086 &caps.max_combined_texture_image_units);
3087 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
3088 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
3089 &caps.max_fragment_uniform_vectors);
3090 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
3091 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
3092 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
3093 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
3094 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
3095 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
3096 &caps.max_vertex_texture_image_units);
3097 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
3098 &caps.max_vertex_uniform_vectors);
3099 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
3100 &caps.num_compressed_texture_formats);
3101 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
3102 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
3103 &caps.bind_generates_resource_chromium);
3104 if (unsafe_es3_apis_enabled()) {
3105 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3106 // but for now we clamp them to 32-bit max.
3107 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
3108 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
3109 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
3110 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
3111 &caps.max_combined_fragment_uniform_components);
3112 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
3113 &caps.max_combined_uniform_blocks);
3114 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
3115 &caps.max_combined_vertex_uniform_components);
3116 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
3117 DoGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
3118 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
3119 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
3120 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
3121 &caps.max_fragment_input_components);
3122 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
3123 &caps.max_fragment_uniform_blocks);
3124 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
3125 &caps.max_fragment_uniform_components);
3126 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
3127 &caps.max_program_texel_offset);
3128 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
3129 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3130 // returned.
3131 if (caps.max_server_wait_timeout < 0)
3132 caps.max_server_wait_timeout = 0;
3133 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps.max_texture_lod_bias);
3134 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
3135 &caps.max_transform_feedback_interleaved_components);
3136 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
3137 &caps.max_transform_feedback_separate_attribs);
3138 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
3139 &caps.max_transform_feedback_separate_components);
3140 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
3141 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
3142 &caps.max_uniform_buffer_bindings);
3143 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
3144 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
3145 &caps.max_vertex_output_components);
3146 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
3147 &caps.max_vertex_uniform_blocks);
3148 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
3149 &caps.max_vertex_uniform_components);
3150 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
3151 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
3152 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
3153 &caps.num_program_binary_formats);
3154 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
3155 &caps.uniform_buffer_offset_alignment);
3156 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3157 caps.major_version = 3;
3158 caps.minor_version = 0;
3160 if (feature_info_->feature_flags().multisampled_render_to_texture ||
3161 feature_info_->feature_flags().chromium_framebuffer_multisample ||
3162 unsafe_es3_apis_enabled()) {
3163 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
3166 caps.egl_image_external =
3167 feature_info_->feature_flags().oes_egl_image_external;
3168 caps.texture_format_atc =
3169 feature_info_->feature_flags().ext_texture_format_atc;
3170 caps.texture_format_bgra8888 =
3171 feature_info_->feature_flags().ext_texture_format_bgra8888;
3172 caps.texture_format_dxt1 =
3173 feature_info_->feature_flags().ext_texture_format_dxt1;
3174 caps.texture_format_dxt5 =
3175 feature_info_->feature_flags().ext_texture_format_dxt5;
3176 caps.texture_format_etc1 =
3177 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
3178 caps.texture_format_etc1_npot =
3179 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
3180 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
3181 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
3182 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
3183 caps.discard_framebuffer =
3184 feature_info_->feature_flags().ext_discard_framebuffer;
3185 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3187 #if defined(OS_MACOSX)
3188 // This is unconditionally true on mac, no need to test for it at runtime.
3189 caps.iosurface = true;
3190 #endif
3192 caps.post_sub_buffer = supports_post_sub_buffer_;
3193 caps.image = true;
3194 caps.surfaceless = surfaceless_;
3196 caps.blend_equation_advanced =
3197 feature_info_->feature_flags().blend_equation_advanced;
3198 caps.blend_equation_advanced_coherent =
3199 feature_info_->feature_flags().blend_equation_advanced_coherent;
3200 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3201 caps.max_copy_texture_chromium_size =
3202 feature_info_->workarounds().max_copy_texture_chromium_size;
3203 caps.render_buffer_format_bgra8888 =
3204 feature_info_->feature_flags().ext_render_buffer_format_bgra8888;
3205 caps.occlusion_query_boolean =
3206 feature_info_->feature_flags().occlusion_query_boolean;
3207 caps.timer_queries =
3208 query_manager_->GPUTimingAvailable();
3209 return caps;
3212 void GLES2DecoderImpl::UpdateCapabilities() {
3213 util_.set_num_compressed_texture_formats(
3214 validators_->compressed_texture_format.GetValues().size());
3215 util_.set_num_shader_binary_formats(
3216 validators_->shader_binary_format.GetValues().size());
3219 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3220 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3222 if (!use_shader_translator_) {
3223 return true;
3225 ShBuiltInResources resources;
3226 ShInitBuiltInResources(&resources);
3227 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3228 resources.MaxVertexUniformVectors =
3229 group_->max_vertex_uniform_vectors();
3230 resources.MaxVaryingVectors = group_->max_varying_vectors();
3231 resources.MaxVertexTextureImageUnits =
3232 group_->max_vertex_texture_image_units();
3233 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3234 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3235 resources.MaxFragmentUniformVectors =
3236 group_->max_fragment_uniform_vectors();
3237 resources.MaxDrawBuffers = group_->max_draw_buffers();
3238 resources.MaxExpressionComplexity = 256;
3239 resources.MaxCallStackDepth = 256;
3241 GLint range[2] = { 0, 0 };
3242 GLint precision = 0;
3243 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3244 range, &precision);
3245 resources.FragmentPrecisionHigh =
3246 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3248 if (IsWebGLContext()) {
3249 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3250 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3251 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3252 if (!draw_buffers_explicitly_enabled_)
3253 resources.MaxDrawBuffers = 1;
3254 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3255 resources.NV_draw_buffers =
3256 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3257 } else {
3258 resources.OES_standard_derivatives =
3259 features().oes_standard_derivatives ? 1 : 0;
3260 resources.ARB_texture_rectangle =
3261 features().arb_texture_rectangle ? 1 : 0;
3262 resources.OES_EGL_image_external =
3263 features().oes_egl_image_external ? 1 : 0;
3264 resources.EXT_draw_buffers =
3265 features().ext_draw_buffers ? 1 : 0;
3266 resources.EXT_frag_depth =
3267 features().ext_frag_depth ? 1 : 0;
3268 resources.EXT_shader_texture_lod =
3269 features().ext_shader_texture_lod ? 1 : 0;
3270 resources.NV_draw_buffers =
3271 features().nv_draw_buffers ? 1 : 0;
3274 ShShaderSpec shader_spec;
3275 if (IsWebGLContext()) {
3276 shader_spec = webgl_version_ == 2 ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3277 } else {
3278 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3281 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3282 features().enable_shader_name_hashing)
3283 resources.HashFunction = &CityHash64;
3284 else
3285 resources.HashFunction = NULL;
3287 int driver_bug_workarounds = 0;
3288 if (workarounds().needs_glsl_built_in_function_emulation)
3289 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3290 if (workarounds().init_gl_position_in_vertex_shader)
3291 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3292 if (workarounds().unfold_short_circuit_as_ternary_operation)
3293 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3294 if (workarounds().init_varyings_without_static_use)
3295 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3296 if (workarounds().unroll_for_loop_with_sampler_array_index)
3297 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3298 if (workarounds().scalarize_vec_and_mat_constructor_args)
3299 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3300 if (workarounds().regenerate_struct_names)
3301 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3302 if (workarounds().remove_pow_with_constant_exponent)
3303 driver_bug_workarounds |= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT;
3305 if (base::CommandLine::InitializedForCurrentProcess() &&
3306 base::CommandLine::ForCurrentProcess()->HasSwitch(
3307 switches::kEmulateShaderPrecision))
3308 resources.WEBGL_debug_shader_precision = true;
3310 ShShaderOutput shader_output_language =
3311 ShaderTranslator::GetShaderOutputLanguageForContext(
3312 feature_info_->gl_version_info());
3314 vertex_translator_ = shader_translator_cache()->GetTranslator(
3315 GL_VERTEX_SHADER, shader_spec, &resources, shader_output_language,
3316 static_cast<ShCompileOptions>(driver_bug_workarounds));
3317 if (!vertex_translator_.get()) {
3318 LOG(ERROR) << "Could not initialize vertex shader translator.";
3319 Destroy(true);
3320 return false;
3323 fragment_translator_ = shader_translator_cache()->GetTranslator(
3324 GL_FRAGMENT_SHADER, shader_spec, &resources, shader_output_language,
3325 static_cast<ShCompileOptions>(driver_bug_workarounds));
3326 if (!fragment_translator_.get()) {
3327 LOG(ERROR) << "Could not initialize fragment shader translator.";
3328 Destroy(true);
3329 return false;
3331 return true;
3334 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3335 for (GLsizei ii = 0; ii < n; ++ii) {
3336 if (GetBuffer(client_ids[ii])) {
3337 return false;
3340 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3341 glGenBuffersARB(n, service_ids.get());
3342 for (GLsizei ii = 0; ii < n; ++ii) {
3343 CreateBuffer(client_ids[ii], service_ids[ii]);
3345 return true;
3348 bool GLES2DecoderImpl::GenFramebuffersHelper(
3349 GLsizei n, const GLuint* client_ids) {
3350 for (GLsizei ii = 0; ii < n; ++ii) {
3351 if (GetFramebuffer(client_ids[ii])) {
3352 return false;
3355 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3356 glGenFramebuffersEXT(n, service_ids.get());
3357 for (GLsizei ii = 0; ii < n; ++ii) {
3358 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3360 return true;
3363 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3364 GLsizei n, const GLuint* client_ids) {
3365 for (GLsizei ii = 0; ii < n; ++ii) {
3366 if (GetRenderbuffer(client_ids[ii])) {
3367 return false;
3370 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3371 glGenRenderbuffersEXT(n, service_ids.get());
3372 for (GLsizei ii = 0; ii < n; ++ii) {
3373 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3375 return true;
3378 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3379 const GLuint* client_ids) {
3380 for (GLsizei ii = 0; ii < n; ++ii) {
3381 if (GetValuebuffer(client_ids[ii])) {
3382 return false;
3385 for (GLsizei ii = 0; ii < n; ++ii) {
3386 CreateValuebuffer(client_ids[ii]);
3388 return true;
3391 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3392 for (GLsizei ii = 0; ii < n; ++ii) {
3393 if (GetTexture(client_ids[ii])) {
3394 return false;
3397 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3398 glGenTextures(n, service_ids.get());
3399 for (GLsizei ii = 0; ii < n; ++ii) {
3400 CreateTexture(client_ids[ii], service_ids[ii]);
3402 return true;
3405 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id,
3406 GLsizei range) {
3407 GLuint last_client_id;
3408 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3409 return false;
3411 if (path_manager()->HasPathsInRange(first_client_id, last_client_id))
3412 return false;
3414 GLuint first_service_id = glGenPathsNV(range);
3415 if (first_service_id == 0) {
3416 // We have to fail the connection here, because client has already
3417 // succeeded in allocating the ids. This happens if we allocate
3418 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3419 // example).
3420 return false;
3422 // GenPathsNV does not wrap.
3423 DCHECK(first_service_id + range - 1 >= first_service_id);
3425 path_manager()->CreatePathRange(first_client_id, last_client_id,
3426 first_service_id);
3428 return true;
3431 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id,
3432 GLsizei range) {
3433 GLuint last_client_id;
3434 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3435 return false;
3437 path_manager()->RemovePaths(first_client_id, last_client_id);
3438 return true;
3441 void GLES2DecoderImpl::DeleteBuffersHelper(
3442 GLsizei n, const GLuint* client_ids) {
3443 for (GLsizei ii = 0; ii < n; ++ii) {
3444 Buffer* buffer = GetBuffer(client_ids[ii]);
3445 if (buffer && !buffer->IsDeleted()) {
3446 buffer->RemoveMappedRange();
3447 state_.RemoveBoundBuffer(buffer);
3448 RemoveBuffer(client_ids[ii]);
3453 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3454 GLsizei n, const GLuint* client_ids) {
3455 bool supports_separate_framebuffer_binds =
3456 features().chromium_framebuffer_multisample;
3458 for (GLsizei ii = 0; ii < n; ++ii) {
3459 Framebuffer* framebuffer =
3460 GetFramebuffer(client_ids[ii]);
3461 if (framebuffer && !framebuffer->IsDeleted()) {
3462 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3463 GLenum target = supports_separate_framebuffer_binds ?
3464 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3466 // Unbind attachments on FBO before deletion.
3467 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3468 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3470 glBindFramebufferEXT(target, GetBackbufferServiceId());
3471 framebuffer_state_.bound_draw_framebuffer = NULL;
3472 framebuffer_state_.clear_state_dirty = true;
3474 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3475 framebuffer_state_.bound_read_framebuffer = NULL;
3476 GLenum target = supports_separate_framebuffer_binds ?
3477 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3478 glBindFramebufferEXT(target, GetBackbufferServiceId());
3480 OnFboChanged();
3481 RemoveFramebuffer(client_ids[ii]);
3486 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3487 GLsizei n, const GLuint* client_ids) {
3488 bool supports_separate_framebuffer_binds =
3489 features().chromium_framebuffer_multisample;
3490 for (GLsizei ii = 0; ii < n; ++ii) {
3491 Renderbuffer* renderbuffer =
3492 GetRenderbuffer(client_ids[ii]);
3493 if (renderbuffer && !renderbuffer->IsDeleted()) {
3494 if (state_.bound_renderbuffer.get() == renderbuffer) {
3495 state_.bound_renderbuffer = NULL;
3497 // Unbind from current framebuffers.
3498 if (supports_separate_framebuffer_binds) {
3499 if (framebuffer_state_.bound_read_framebuffer.get()) {
3500 framebuffer_state_.bound_read_framebuffer
3501 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3503 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3504 framebuffer_state_.bound_draw_framebuffer
3505 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3507 } else {
3508 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3509 framebuffer_state_.bound_draw_framebuffer
3510 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3513 framebuffer_state_.clear_state_dirty = true;
3514 RemoveRenderbuffer(client_ids[ii]);
3519 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3520 GLsizei n,
3521 const GLuint* client_ids) {
3522 for (GLsizei ii = 0; ii < n; ++ii) {
3523 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3524 if (valuebuffer) {
3525 if (state_.bound_valuebuffer.get() == valuebuffer) {
3526 state_.bound_valuebuffer = NULL;
3528 RemoveValuebuffer(client_ids[ii]);
3533 void GLES2DecoderImpl::DeleteTexturesHelper(
3534 GLsizei n, const GLuint* client_ids) {
3535 bool supports_separate_framebuffer_binds =
3536 features().chromium_framebuffer_multisample;
3537 for (GLsizei ii = 0; ii < n; ++ii) {
3538 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3539 if (texture_ref) {
3540 Texture* texture = texture_ref->texture();
3541 if (texture->IsAttachedToFramebuffer()) {
3542 framebuffer_state_.clear_state_dirty = true;
3544 // Unbind texture_ref from texture_ref units.
3545 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3546 state_.texture_units[jj].Unbind(texture_ref);
3548 // Unbind from current framebuffers.
3549 if (supports_separate_framebuffer_binds) {
3550 if (framebuffer_state_.bound_read_framebuffer.get()) {
3551 framebuffer_state_.bound_read_framebuffer
3552 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3554 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3555 framebuffer_state_.bound_draw_framebuffer
3556 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3558 } else {
3559 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3560 framebuffer_state_.bound_draw_framebuffer
3561 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3564 #if defined(OS_MACOSX)
3565 GLuint service_id = texture->service_id();
3566 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3567 ReleaseIOSurfaceForTexture(service_id);
3569 #endif
3570 RemoveTexture(client_ids[ii]);
3575 // } // anonymous namespace
3577 bool GLES2DecoderImpl::MakeCurrent() {
3578 if (!context_.get())
3579 return false;
3581 if (WasContextLost()) {
3582 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3583 return false;
3586 if (!context_->MakeCurrent(surface_.get())) {
3587 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3588 MarkContextLost(error::kMakeCurrentFailed);
3589 group_->LoseContexts(error::kUnknown);
3590 return false;
3593 if (CheckResetStatus()) {
3594 LOG(ERROR)
3595 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3596 group_->LoseContexts(error::kUnknown);
3597 return false;
3600 ProcessFinishedAsyncTransfers();
3602 // Rebind the FBO if it was unbound by the context.
3603 if (workarounds().unbind_fbo_on_context_switch)
3604 RestoreFramebufferBindings();
3606 framebuffer_state_.clear_state_dirty = true;
3608 return true;
3611 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3612 ProcessPendingReadPixels(false);
3613 if (engine() && query_manager_.get())
3614 query_manager_->ProcessPendingTransferQueries();
3616 // TODO(epenner): Is there a better place to do this?
3617 // This needs to occur before we execute any batch of commands
3618 // from the client, as the client may have recieved an async
3619 // completion while issuing those commands.
3620 // "DidFlushStart" would be ideal if we had such a callback.
3621 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3624 static void RebindCurrentFramebuffer(
3625 GLenum target,
3626 Framebuffer* framebuffer,
3627 GLuint back_buffer_service_id) {
3628 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3630 if (framebuffer_id == 0) {
3631 framebuffer_id = back_buffer_service_id;
3634 glBindFramebufferEXT(target, framebuffer_id);
3637 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3638 framebuffer_state_.clear_state_dirty = true;
3640 if (!features().chromium_framebuffer_multisample) {
3641 RebindCurrentFramebuffer(
3642 GL_FRAMEBUFFER,
3643 framebuffer_state_.bound_draw_framebuffer.get(),
3644 GetBackbufferServiceId());
3645 } else {
3646 RebindCurrentFramebuffer(
3647 GL_READ_FRAMEBUFFER_EXT,
3648 framebuffer_state_.bound_read_framebuffer.get(),
3649 GetBackbufferServiceId());
3650 RebindCurrentFramebuffer(
3651 GL_DRAW_FRAMEBUFFER_EXT,
3652 framebuffer_state_.bound_draw_framebuffer.get(),
3653 GetBackbufferServiceId());
3655 OnFboChanged();
3658 bool GLES2DecoderImpl::CheckFramebufferValid(
3659 Framebuffer* framebuffer,
3660 GLenum target, const char* func_name) {
3661 if (!framebuffer) {
3662 if (surfaceless_)
3663 return false;
3664 if (backbuffer_needs_clear_bits_) {
3665 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3666 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3667 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3668 glClearStencil(0);
3669 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3670 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3671 glClearDepth(1.0f);
3672 state_.SetDeviceDepthMask(GL_TRUE);
3673 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3674 bool reset_draw_buffer = false;
3675 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3676 back_buffer_draw_buffer_ == GL_NONE) {
3677 reset_draw_buffer = true;
3678 GLenum buf = GL_BACK;
3679 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3680 buf = GL_COLOR_ATTACHMENT0;
3681 glDrawBuffersARB(1, &buf);
3683 glClear(backbuffer_needs_clear_bits_);
3684 if (reset_draw_buffer) {
3685 GLenum buf = GL_NONE;
3686 glDrawBuffersARB(1, &buf);
3688 backbuffer_needs_clear_bits_ = 0;
3689 RestoreClearState();
3691 return true;
3694 if (framebuffer_manager()->IsComplete(framebuffer)) {
3695 return true;
3698 GLenum completeness = framebuffer->IsPossiblyComplete();
3699 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3700 LOCAL_SET_GL_ERROR(
3701 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3702 return false;
3705 // Are all the attachments cleared?
3706 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3707 texture_manager()->HaveUnclearedMips()) {
3708 if (!framebuffer->IsCleared()) {
3709 // Can we clear them?
3710 if (framebuffer->GetStatus(texture_manager(), target) !=
3711 GL_FRAMEBUFFER_COMPLETE) {
3712 LOCAL_SET_GL_ERROR(
3713 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3714 "framebuffer incomplete (clear)");
3715 return false;
3717 ClearUnclearedAttachments(target, framebuffer);
3721 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3722 if (framebuffer->GetStatus(texture_manager(), target) !=
3723 GL_FRAMEBUFFER_COMPLETE) {
3724 LOCAL_SET_GL_ERROR(
3725 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3726 "framebuffer incomplete (check)");
3727 return false;
3729 framebuffer_manager()->MarkAsComplete(framebuffer);
3732 // NOTE: At this point we don't know if the framebuffer is complete but
3733 // we DO know that everything that needs to be cleared has been cleared.
3734 return true;
3737 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3738 if (!features().chromium_framebuffer_multisample) {
3739 bool valid = CheckFramebufferValid(
3740 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3741 func_name);
3743 if (valid)
3744 OnUseFramebuffer();
3746 return valid;
3748 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3749 GL_DRAW_FRAMEBUFFER_EXT,
3750 func_name) &&
3751 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3752 GL_READ_FRAMEBUFFER_EXT,
3753 func_name);
3756 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3757 const char* func_name) {
3758 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3759 framebuffer_state_.bound_read_framebuffer.get() :
3760 framebuffer_state_.bound_draw_framebuffer.get();
3761 if (!framebuffer)
3762 return true;
3763 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3764 LOCAL_SET_GL_ERROR(
3765 GL_INVALID_OPERATION, func_name, "no color image attached");
3766 return false;
3768 return true;
3771 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3772 TextureRef* texture, GLint level) {
3773 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3774 framebuffer_state_.bound_read_framebuffer.get() :
3775 framebuffer_state_.bound_draw_framebuffer.get();
3776 if (!framebuffer)
3777 return false;
3778 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3779 GL_COLOR_ATTACHMENT0);
3780 if (!attachment)
3781 return false;
3782 return attachment->FormsFeedbackLoop(texture, level);
3785 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3786 Framebuffer* framebuffer =
3787 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3788 if (framebuffer != NULL) {
3789 const Framebuffer::Attachment* attachment =
3790 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3791 if (attachment) {
3792 return gfx::Size(attachment->width(), attachment->height());
3794 return gfx::Size(0, 0);
3795 } else if (offscreen_target_frame_buffer_.get()) {
3796 return offscreen_size_;
3797 } else {
3798 return surface_->GetSize();
3802 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3803 Framebuffer* framebuffer =
3804 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3805 if (framebuffer) {
3806 return framebuffer->GetReadBufferTextureType();
3807 } else { // Back buffer.
3808 if (back_buffer_read_buffer_ == GL_NONE)
3809 return 0;
3810 return GL_UNSIGNED_BYTE;
3814 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3815 Framebuffer* framebuffer =
3816 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3817 if (framebuffer) {
3818 return framebuffer->GetReadBufferInternalFormat();
3819 } else { // Back buffer.
3820 if (back_buffer_read_buffer_ == GL_NONE)
3821 return 0;
3822 if (offscreen_target_frame_buffer_.get()) {
3823 return offscreen_target_color_format_;
3825 return back_buffer_color_format_;
3829 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3830 if (!offscreen_saved_color_texture_info_.get())
3831 return;
3832 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3833 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3834 texture_manager()->SetLevelInfo(
3835 offscreen_saved_color_texture_info_.get(), GL_TEXTURE_2D,
3836 0, // level
3837 GL_RGBA, offscreen_size_.width(), offscreen_size_.height(),
3838 1, // depth
3839 0, // border
3840 GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(offscreen_size_));
3841 texture_manager()->SetParameteri(
3842 "UpdateParentTextureInfo",
3843 GetErrorState(),
3844 offscreen_saved_color_texture_info_.get(),
3845 GL_TEXTURE_MAG_FILTER,
3846 GL_LINEAR);
3847 texture_manager()->SetParameteri(
3848 "UpdateParentTextureInfo",
3849 GetErrorState(),
3850 offscreen_saved_color_texture_info_.get(),
3851 GL_TEXTURE_MIN_FILTER,
3852 GL_LINEAR);
3853 texture_manager()->SetParameteri(
3854 "UpdateParentTextureInfo",
3855 GetErrorState(),
3856 offscreen_saved_color_texture_info_.get(),
3857 GL_TEXTURE_WRAP_S,
3858 GL_CLAMP_TO_EDGE);
3859 texture_manager()->SetParameteri(
3860 "UpdateParentTextureInfo",
3861 GetErrorState(),
3862 offscreen_saved_color_texture_info_.get(),
3863 GL_TEXTURE_WRAP_T,
3864 GL_CLAMP_TO_EDGE);
3865 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3866 &state_, target);
3867 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3870 void GLES2DecoderImpl::SetResizeCallback(
3871 const base::Callback<void(gfx::Size, float)>& callback) {
3872 resize_callback_ = callback;
3875 Logger* GLES2DecoderImpl::GetLogger() {
3876 return &logger_;
3879 void GLES2DecoderImpl::BeginDecoding() {
3880 gpu_tracer_->BeginDecoding();
3881 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3882 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3883 (*cb_command_trace_category_ != 0);
3884 query_manager_->ProcessFrameBeginUpdates();
3887 void GLES2DecoderImpl::EndDecoding() {
3888 gpu_tracer_->EndDecoding();
3891 ErrorState* GLES2DecoderImpl::GetErrorState() {
3892 return state_.GetErrorState();
3895 void GLES2DecoderImpl::SetShaderCacheCallback(
3896 const ShaderCacheCallback& callback) {
3897 shader_cache_callback_ = callback;
3900 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3901 const WaitSyncPointCallback& callback) {
3902 wait_sync_point_callback_ = callback;
3905 AsyncPixelTransferManager*
3906 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3907 return async_pixel_transfer_manager_.get();
3910 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3911 async_pixel_transfer_manager_.reset();
3914 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3915 AsyncPixelTransferManager* manager) {
3916 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3919 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3920 uint32* service_texture_id) {
3921 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3922 if (texture_ref) {
3923 *service_texture_id = texture_ref->service_id();
3924 return true;
3926 return false;
3929 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3930 return texture_state_.texture_upload_count +
3931 async_pixel_transfer_manager_->GetTextureUploadCount();
3934 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3935 return texture_state_.total_texture_upload_time +
3936 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3939 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3940 return total_processing_commands_time_;
3943 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3944 total_processing_commands_time_ += time;
3947 void GLES2DecoderImpl::Destroy(bool have_context) {
3948 if (!initialized())
3949 return;
3951 DCHECK(!have_context || context_->IsCurrent(NULL));
3953 // Unbind everything.
3954 state_.vertex_attrib_manager = NULL;
3955 state_.default_vertex_attrib_manager = NULL;
3956 state_.texture_units.clear();
3957 state_.bound_array_buffer = NULL;
3958 state_.bound_copy_read_buffer = NULL;
3959 state_.bound_copy_write_buffer = NULL;
3960 state_.bound_pixel_pack_buffer = NULL;
3961 state_.bound_pixel_unpack_buffer = NULL;
3962 state_.bound_transform_feedback_buffer = NULL;
3963 state_.bound_uniform_buffer = NULL;
3964 framebuffer_state_.bound_read_framebuffer = NULL;
3965 framebuffer_state_.bound_draw_framebuffer = NULL;
3966 state_.bound_renderbuffer = NULL;
3967 state_.bound_valuebuffer = NULL;
3969 if (offscreen_saved_color_texture_info_.get()) {
3970 DCHECK(offscreen_target_color_texture_);
3971 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3972 offscreen_saved_color_texture_->id());
3973 offscreen_saved_color_texture_->Invalidate();
3974 offscreen_saved_color_texture_info_ = NULL;
3976 if (have_context) {
3977 if (copy_texture_CHROMIUM_.get()) {
3978 copy_texture_CHROMIUM_->Destroy();
3979 copy_texture_CHROMIUM_.reset();
3982 clear_framebuffer_blit_.reset();
3984 if (state_.current_program.get()) {
3985 program_manager()->UnuseProgram(shader_manager(),
3986 state_.current_program.get());
3989 if (attrib_0_buffer_id_) {
3990 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3992 if (fixed_attrib_buffer_id_) {
3993 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3996 if (validation_texture_) {
3997 glDeleteTextures(1, &validation_texture_);
3998 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3999 glDeleteFramebuffersEXT(1, &validation_fbo_);
4002 if (offscreen_target_frame_buffer_.get())
4003 offscreen_target_frame_buffer_->Destroy();
4004 if (offscreen_target_color_texture_.get())
4005 offscreen_target_color_texture_->Destroy();
4006 if (offscreen_target_color_render_buffer_.get())
4007 offscreen_target_color_render_buffer_->Destroy();
4008 if (offscreen_target_depth_render_buffer_.get())
4009 offscreen_target_depth_render_buffer_->Destroy();
4010 if (offscreen_target_stencil_render_buffer_.get())
4011 offscreen_target_stencil_render_buffer_->Destroy();
4012 if (offscreen_saved_frame_buffer_.get())
4013 offscreen_saved_frame_buffer_->Destroy();
4014 if (offscreen_saved_color_texture_.get())
4015 offscreen_saved_color_texture_->Destroy();
4016 if (offscreen_resolved_frame_buffer_.get())
4017 offscreen_resolved_frame_buffer_->Destroy();
4018 if (offscreen_resolved_color_texture_.get())
4019 offscreen_resolved_color_texture_->Destroy();
4020 } else {
4021 if (offscreen_target_frame_buffer_.get())
4022 offscreen_target_frame_buffer_->Invalidate();
4023 if (offscreen_target_color_texture_.get())
4024 offscreen_target_color_texture_->Invalidate();
4025 if (offscreen_target_color_render_buffer_.get())
4026 offscreen_target_color_render_buffer_->Invalidate();
4027 if (offscreen_target_depth_render_buffer_.get())
4028 offscreen_target_depth_render_buffer_->Invalidate();
4029 if (offscreen_target_stencil_render_buffer_.get())
4030 offscreen_target_stencil_render_buffer_->Invalidate();
4031 if (offscreen_saved_frame_buffer_.get())
4032 offscreen_saved_frame_buffer_->Invalidate();
4033 if (offscreen_saved_color_texture_.get())
4034 offscreen_saved_color_texture_->Invalidate();
4035 if (offscreen_resolved_frame_buffer_.get())
4036 offscreen_resolved_frame_buffer_->Invalidate();
4037 if (offscreen_resolved_color_texture_.get())
4038 offscreen_resolved_color_texture_->Invalidate();
4041 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4042 // Otherwise, we can leak objects. http://crbug.com/258772.
4043 // state_.current_program must be reset before group_ is reset because
4044 // the later deletes the ProgramManager object that referred by
4045 // state_.current_program object.
4046 state_.current_program = NULL;
4048 copy_texture_CHROMIUM_.reset();
4049 clear_framebuffer_blit_.reset();
4051 if (query_manager_.get()) {
4052 query_manager_->Destroy(have_context);
4053 query_manager_.reset();
4056 if (vertex_array_manager_ .get()) {
4057 vertex_array_manager_->Destroy(have_context);
4058 vertex_array_manager_.reset();
4061 if (image_manager_.get()) {
4062 image_manager_->Destroy(have_context);
4063 image_manager_.reset();
4066 offscreen_target_frame_buffer_.reset();
4067 offscreen_target_color_texture_.reset();
4068 offscreen_target_color_render_buffer_.reset();
4069 offscreen_target_depth_render_buffer_.reset();
4070 offscreen_target_stencil_render_buffer_.reset();
4071 offscreen_saved_frame_buffer_.reset();
4072 offscreen_saved_color_texture_.reset();
4073 offscreen_resolved_frame_buffer_.reset();
4074 offscreen_resolved_color_texture_.reset();
4076 // Need to release these before releasing |group_| which may own the
4077 // ShaderTranslatorCache.
4078 fragment_translator_ = NULL;
4079 vertex_translator_ = NULL;
4081 // Should destroy the transfer manager before the texture manager held
4082 // by the context group.
4083 async_pixel_transfer_manager_.reset();
4085 // Destroy the GPU Tracer which may own some in process GPU Timings.
4086 if (gpu_tracer_) {
4087 gpu_tracer_->Destroy(have_context);
4088 gpu_tracer_.reset();
4091 if (group_.get()) {
4092 framebuffer_manager()->RemoveObserver(this);
4093 group_->Destroy(this, have_context);
4094 group_ = NULL;
4097 if (context_.get()) {
4098 context_->ReleaseCurrent(NULL);
4099 context_ = NULL;
4102 #if defined(OS_MACOSX)
4103 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
4104 it != texture_to_io_surface_map_.end(); ++it) {
4105 CFRelease(it->second);
4107 texture_to_io_surface_map_.clear();
4108 #endif
4111 void GLES2DecoderImpl::SetSurface(
4112 const scoped_refptr<gfx::GLSurface>& surface) {
4113 DCHECK(context_->IsCurrent(NULL));
4114 DCHECK(surface_.get());
4115 surface_ = surface;
4116 RestoreCurrentFramebufferBindings();
4119 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
4120 if (!offscreen_saved_color_texture_.get()) {
4121 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
4122 return;
4124 if (!offscreen_saved_color_texture_info_.get()) {
4125 GLuint service_id = offscreen_saved_color_texture_->id();
4126 offscreen_saved_color_texture_info_ = TextureRef::Create(
4127 texture_manager(), 0, service_id);
4128 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
4129 GL_TEXTURE_2D);
4130 UpdateParentTextureInfo();
4132 mailbox_manager()->ProduceTexture(
4133 mailbox, offscreen_saved_color_texture_info_->texture());
4136 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
4137 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4138 if (!is_offscreen) {
4139 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4140 << " with an onscreen framebuffer.";
4141 return false;
4144 if (offscreen_size_ == size)
4145 return true;
4147 offscreen_size_ = size;
4148 int w = offscreen_size_.width();
4149 int h = offscreen_size_.height();
4150 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
4151 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4152 << "to allocate storage due to excessive dimensions.";
4153 return false;
4156 // Reallocate the offscreen target buffers.
4157 DCHECK(offscreen_target_color_format_);
4158 if (IsOffscreenBufferMultisampled()) {
4159 if (!offscreen_target_color_render_buffer_->AllocateStorage(
4160 feature_info_.get(),
4161 offscreen_size_,
4162 offscreen_target_color_format_,
4163 offscreen_target_samples_)) {
4164 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4165 << "to allocate storage for offscreen target color buffer.";
4166 return false;
4168 } else {
4169 if (!offscreen_target_color_texture_->AllocateStorage(
4170 offscreen_size_, offscreen_target_color_format_, false)) {
4171 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4172 << "to allocate storage for offscreen target color texture.";
4173 return false;
4176 if (offscreen_target_depth_format_ &&
4177 !offscreen_target_depth_render_buffer_->AllocateStorage(
4178 feature_info_.get(),
4179 offscreen_size_,
4180 offscreen_target_depth_format_,
4181 offscreen_target_samples_)) {
4182 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4183 << "to allocate storage for offscreen target depth buffer.";
4184 return false;
4186 if (offscreen_target_stencil_format_ &&
4187 !offscreen_target_stencil_render_buffer_->AllocateStorage(
4188 feature_info_.get(),
4189 offscreen_size_,
4190 offscreen_target_stencil_format_,
4191 offscreen_target_samples_)) {
4192 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4193 << "to allocate storage for offscreen target stencil buffer.";
4194 return false;
4197 // Attach the offscreen target buffers to the target frame buffer.
4198 if (IsOffscreenBufferMultisampled()) {
4199 offscreen_target_frame_buffer_->AttachRenderBuffer(
4200 GL_COLOR_ATTACHMENT0,
4201 offscreen_target_color_render_buffer_.get());
4202 } else {
4203 offscreen_target_frame_buffer_->AttachRenderTexture(
4204 offscreen_target_color_texture_.get());
4206 if (offscreen_target_depth_format_) {
4207 offscreen_target_frame_buffer_->AttachRenderBuffer(
4208 GL_DEPTH_ATTACHMENT,
4209 offscreen_target_depth_render_buffer_.get());
4211 const bool packed_depth_stencil =
4212 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4213 if (packed_depth_stencil) {
4214 offscreen_target_frame_buffer_->AttachRenderBuffer(
4215 GL_STENCIL_ATTACHMENT,
4216 offscreen_target_depth_render_buffer_.get());
4217 } else if (offscreen_target_stencil_format_) {
4218 offscreen_target_frame_buffer_->AttachRenderBuffer(
4219 GL_STENCIL_ATTACHMENT,
4220 offscreen_target_stencil_render_buffer_.get());
4223 if (offscreen_target_frame_buffer_->CheckStatus() !=
4224 GL_FRAMEBUFFER_COMPLETE) {
4225 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4226 << "because offscreen FBO was incomplete.";
4227 return false;
4230 // Clear the target frame buffer.
4232 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4233 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f);
4234 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4235 glClearStencil(0);
4236 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4237 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4238 glClearDepth(0);
4239 state_.SetDeviceDepthMask(GL_TRUE);
4240 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4241 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4242 RestoreClearState();
4245 // Destroy the offscreen resolved framebuffers.
4246 if (offscreen_resolved_frame_buffer_.get())
4247 offscreen_resolved_frame_buffer_->Destroy();
4248 if (offscreen_resolved_color_texture_.get())
4249 offscreen_resolved_color_texture_->Destroy();
4250 offscreen_resolved_color_texture_.reset();
4251 offscreen_resolved_frame_buffer_.reset();
4253 return true;
4256 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4257 const void* cmd_data) {
4258 const gles2::cmds::ResizeCHROMIUM& c =
4259 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4260 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4261 return error::kDeferCommandUntilLater;
4263 GLuint width = static_cast<GLuint>(c.width);
4264 GLuint height = static_cast<GLuint>(c.height);
4265 GLfloat scale_factor = c.scale_factor;
4266 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4268 width = std::max(1U, width);
4269 height = std::max(1U, height);
4271 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4272 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4273 // Make sure that we are done drawing to the back buffer before resizing.
4274 glFinish();
4275 #endif
4276 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4277 if (is_offscreen) {
4278 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4279 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4280 << "ResizeOffscreenFrameBuffer failed.";
4281 return error::kLostContext;
4285 if (!resize_callback_.is_null()) {
4286 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4287 DCHECK(context_->IsCurrent(surface_.get()));
4288 if (!context_->IsCurrent(surface_.get())) {
4289 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4290 << "current after resize callback.";
4291 return error::kLostContext;
4295 return error::kNoError;
4298 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4299 if (command_id > kStartPoint && command_id < kNumCommands) {
4300 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4302 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4305 // Decode a command, and call the corresponding GL functions.
4306 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4307 // of commands at once, and is now only used for tests that need to track
4308 // individual commands.
4309 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4310 unsigned int arg_count,
4311 const void* cmd_data) {
4312 return DoCommands(1, cmd_data, arg_count + 1, 0);
4315 // Decode multiple commands, and call the corresponding GL functions.
4316 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4317 // changed by a (malicious) client at any time, so if validation has to happen,
4318 // it should operate on a copy of them.
4319 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4320 // interest of performance in this critical execution loop.
4321 template <bool DebugImpl>
4322 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4323 const void* buffer,
4324 int num_entries,
4325 int* entries_processed) {
4326 commands_to_process_ = num_commands;
4327 error::Error result = error::kNoError;
4328 const CommandBufferEntry* cmd_data =
4329 static_cast<const CommandBufferEntry*>(buffer);
4330 int process_pos = 0;
4331 unsigned int command = 0;
4333 while (process_pos < num_entries && result == error::kNoError &&
4334 commands_to_process_--) {
4335 const unsigned int size = cmd_data->value_header.size;
4336 command = cmd_data->value_header.command;
4338 if (size == 0) {
4339 result = error::kInvalidSize;
4340 break;
4343 if (static_cast<int>(size) + process_pos > num_entries) {
4344 result = error::kOutOfBounds;
4345 break;
4348 if (DebugImpl) {
4349 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4350 GetCommandName(command));
4352 if (log_commands()) {
4353 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4354 << "cmd: " << GetCommandName(command);
4358 const unsigned int arg_count = size - 1;
4359 unsigned int command_index = command - kStartPoint - 1;
4360 if (command_index < arraysize(command_info)) {
4361 const CommandInfo& info = command_info[command_index];
4362 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4363 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4364 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4365 bool doing_gpu_trace = false;
4366 if (DebugImpl && gpu_trace_commands_) {
4367 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4368 doing_gpu_trace = true;
4369 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4370 GetCommandName(command),
4371 kTraceDecoder);
4375 uint32 immediate_data_size = (arg_count - info_arg_count) *
4376 sizeof(CommandBufferEntry); // NOLINT
4378 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4380 if (DebugImpl && doing_gpu_trace)
4381 gpu_tracer_->End(kTraceDecoder);
4383 if (DebugImpl && debug()) {
4384 GLenum error;
4385 while ((error = glGetError()) != GL_NO_ERROR) {
4386 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4387 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4388 << " : " << GetCommandName(command);
4389 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4392 } else {
4393 result = error::kInvalidArguments;
4395 } else {
4396 result = DoCommonCommand(command, arg_count, cmd_data);
4399 if (DebugImpl) {
4400 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4401 GetCommandName(command));
4404 if (result == error::kNoError &&
4405 current_decoder_error_ != error::kNoError) {
4406 result = current_decoder_error_;
4407 current_decoder_error_ = error::kNoError;
4410 if (result != error::kDeferCommandUntilLater) {
4411 process_pos += size;
4412 cmd_data += size;
4416 if (entries_processed)
4417 *entries_processed = process_pos;
4419 if (error::IsError(result)) {
4420 LOG(ERROR) << "Error: " << result << " for Command "
4421 << GetCommandName(command);
4424 return result;
4427 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4428 const void* buffer,
4429 int num_entries,
4430 int* entries_processed) {
4431 if (gpu_debug_commands_) {
4432 return DoCommandsImpl<true>(
4433 num_commands, buffer, num_entries, entries_processed);
4434 } else {
4435 return DoCommandsImpl<false>(
4436 num_commands, buffer, num_entries, entries_processed);
4440 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4441 buffer_manager()->RemoveBuffer(client_id);
4444 void GLES2DecoderImpl::DoFinish() {
4445 glFinish();
4446 ProcessPendingReadPixels(true);
4447 ProcessPendingQueries(true);
4450 void GLES2DecoderImpl::DoFlush() {
4451 glFlush();
4452 ProcessPendingQueries(false);
4455 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4456 GLuint texture_index = texture_unit - GL_TEXTURE0;
4457 if (texture_index >= state_.texture_units.size()) {
4458 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4459 "glActiveTexture", texture_unit, "texture_unit");
4460 return;
4462 state_.active_texture_unit = texture_index;
4463 glActiveTexture(texture_unit);
4466 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4467 Buffer* buffer = NULL;
4468 GLuint service_id = 0;
4469 if (client_id != 0) {
4470 buffer = GetBuffer(client_id);
4471 if (!buffer) {
4472 if (!group_->bind_generates_resource()) {
4473 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4474 "glBindBuffer",
4475 "id not generated by glGenBuffers");
4476 return;
4479 // It's a new id so make a buffer buffer for it.
4480 glGenBuffersARB(1, &service_id);
4481 CreateBuffer(client_id, service_id);
4482 buffer = GetBuffer(client_id);
4485 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4486 if (buffer) {
4487 if (!buffer_manager()->SetTarget(buffer, target)) {
4488 LOCAL_SET_GL_ERROR(
4489 GL_INVALID_OPERATION,
4490 "glBindBuffer", "buffer bound to more than 1 target");
4491 return;
4493 service_id = buffer->service_id();
4495 state_.SetBoundBuffer(target, buffer);
4496 glBindBuffer(target, service_id);
4499 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4500 Framebuffer* framebuffer =
4501 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4502 if (framebuffer)
4503 return framebuffer->HasAlphaMRT();
4504 return BackBufferHasAlpha();
4507 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4508 Framebuffer* framebuffer =
4509 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4510 if (framebuffer) {
4511 return framebuffer->HasDepthAttachment();
4513 if (offscreen_target_frame_buffer_.get()) {
4514 return offscreen_target_depth_format_ != 0;
4516 return back_buffer_has_depth_;
4519 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4520 Framebuffer* framebuffer =
4521 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4522 if (framebuffer) {
4523 return framebuffer->HasStencilAttachment();
4525 if (offscreen_target_frame_buffer_.get()) {
4526 return offscreen_target_stencil_format_ != 0 ||
4527 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4529 return back_buffer_has_stencil_;
4532 void GLES2DecoderImpl::ApplyDirtyState() {
4533 if (framebuffer_state_.clear_state_dirty) {
4534 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha();
4535 state_.SetDeviceColorMask(state_.color_mask_red,
4536 state_.color_mask_green,
4537 state_.color_mask_blue,
4538 state_.color_mask_alpha && have_alpha);
4540 bool have_depth = BoundFramebufferHasDepthAttachment();
4541 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4543 bool have_stencil = BoundFramebufferHasStencilAttachment();
4544 state_.SetDeviceStencilMaskSeparate(
4545 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4546 state_.SetDeviceStencilMaskSeparate(
4547 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4549 state_.SetDeviceCapabilityState(
4550 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4551 state_.SetDeviceCapabilityState(
4552 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4553 framebuffer_state_.clear_state_dirty = false;
4557 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4558 return (offscreen_target_frame_buffer_.get())
4559 ? offscreen_target_frame_buffer_->id()
4560 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4563 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4564 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4565 "context", logger_.GetLogPrefix());
4566 // Restore the Framebuffer first because of bugs in Intel drivers.
4567 // Intel drivers incorrectly clip the viewport settings to
4568 // the size of the current framebuffer object.
4569 RestoreFramebufferBindings();
4570 state_.RestoreState(prev_state);
4573 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4574 GLuint service_id =
4575 framebuffer_state_.bound_draw_framebuffer.get()
4576 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4577 : GetBackbufferServiceId();
4578 if (!features().chromium_framebuffer_multisample) {
4579 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4580 } else {
4581 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4582 service_id = framebuffer_state_.bound_read_framebuffer.get()
4583 ? framebuffer_state_.bound_read_framebuffer->service_id()
4584 : GetBackbufferServiceId();
4585 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4587 OnFboChanged();
4590 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4591 state_.RestoreRenderbufferBindings();
4594 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4595 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4596 if (texture) {
4597 GLenum target = texture->target();
4598 glBindTexture(target, service_id);
4599 glTexParameteri(
4600 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4601 glTexParameteri(
4602 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4603 glTexParameteri(
4604 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4605 glTexParameteri(
4606 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4607 RestoreTextureUnitBindings(state_.active_texture_unit);
4611 void GLES2DecoderImpl::ClearAllAttributes() const {
4612 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4613 // other VAOs.
4614 if (feature_info_->feature_flags().native_vertex_array_object)
4615 glBindVertexArrayOES(0);
4617 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4618 if (i != 0) // Never disable attribute 0
4619 glDisableVertexAttribArray(i);
4620 if (features().angle_instanced_arrays)
4621 glVertexAttribDivisorANGLE(i, 0);
4625 void GLES2DecoderImpl::RestoreAllAttributes() const {
4626 state_.RestoreVertexAttribs();
4629 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4630 state_.SetIgnoreCachedStateForTest(ignore);
4633 void GLES2DecoderImpl::OnFboChanged() const {
4634 if (workarounds().restore_scissor_on_fbo_change)
4635 state_.fbo_binding_for_scissor_workaround_dirty = true;
4637 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4638 GLint bound_fbo_unsigned = -1;
4639 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4640 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4641 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4642 surface_->NotifyWasBound();
4646 // Called after the FBO is checked for completeness.
4647 void GLES2DecoderImpl::OnUseFramebuffer() const {
4648 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4649 state_.fbo_binding_for_scissor_workaround_dirty = false;
4650 // The driver forgets the correct scissor when modifying the FBO binding.
4651 glScissor(state_.scissor_x,
4652 state_.scissor_y,
4653 state_.scissor_width,
4654 state_.scissor_height);
4656 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4657 // it's unclear how this bug works.
4658 glFlush();
4662 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4663 Framebuffer* framebuffer = NULL;
4664 GLuint service_id = 0;
4665 if (client_id != 0) {
4666 framebuffer = GetFramebuffer(client_id);
4667 if (!framebuffer) {
4668 if (!group_->bind_generates_resource()) {
4669 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4670 "glBindFramebuffer",
4671 "id not generated by glGenFramebuffers");
4672 return;
4675 // It's a new id so make a framebuffer framebuffer for it.
4676 glGenFramebuffersEXT(1, &service_id);
4677 CreateFramebuffer(client_id, service_id);
4678 framebuffer = GetFramebuffer(client_id);
4679 } else {
4680 service_id = framebuffer->service_id();
4682 framebuffer->MarkAsValid();
4684 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4686 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4687 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4690 // vmiura: This looks like dup code
4691 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4692 framebuffer_state_.bound_read_framebuffer = framebuffer;
4695 framebuffer_state_.clear_state_dirty = true;
4697 // If we are rendering to the backbuffer get the FBO id for any simulated
4698 // backbuffer.
4699 if (framebuffer == NULL) {
4700 service_id = GetBackbufferServiceId();
4703 glBindFramebufferEXT(target, service_id);
4704 OnFboChanged();
4707 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4708 Renderbuffer* renderbuffer = NULL;
4709 GLuint service_id = 0;
4710 if (client_id != 0) {
4711 renderbuffer = GetRenderbuffer(client_id);
4712 if (!renderbuffer) {
4713 if (!group_->bind_generates_resource()) {
4714 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4715 "glBindRenderbuffer",
4716 "id not generated by glGenRenderbuffers");
4717 return;
4720 // It's a new id so make a renderbuffer for it.
4721 glGenRenderbuffersEXT(1, &service_id);
4722 CreateRenderbuffer(client_id, service_id);
4723 renderbuffer = GetRenderbuffer(client_id);
4724 } else {
4725 service_id = renderbuffer->service_id();
4727 renderbuffer->MarkAsValid();
4729 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4730 state_.bound_renderbuffer = renderbuffer;
4731 state_.bound_renderbuffer_valid = true;
4732 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4735 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4736 TextureRef* texture_ref = NULL;
4737 GLuint service_id = 0;
4738 if (client_id != 0) {
4739 texture_ref = GetTexture(client_id);
4740 if (!texture_ref) {
4741 if (!group_->bind_generates_resource()) {
4742 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4743 "glBindTexture",
4744 "id not generated by glGenTextures");
4745 return;
4748 // It's a new id so make a texture texture for it.
4749 glGenTextures(1, &service_id);
4750 DCHECK_NE(0u, service_id);
4751 CreateTexture(client_id, service_id);
4752 texture_ref = GetTexture(client_id);
4754 } else {
4755 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4758 // Check the texture exists
4759 if (texture_ref) {
4760 Texture* texture = texture_ref->texture();
4761 // Check that we are not trying to bind it to a different target.
4762 if (texture->target() != 0 && texture->target() != target) {
4763 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4764 "glBindTexture",
4765 "texture bound to more than 1 target.");
4766 return;
4768 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4769 if (texture->target() == 0) {
4770 texture_manager()->SetTarget(texture_ref, target);
4772 glBindTexture(target, texture->service_id());
4773 } else {
4774 glBindTexture(target, 0);
4777 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4778 unit.bind_target = target;
4779 switch (target) {
4780 case GL_TEXTURE_2D:
4781 unit.bound_texture_2d = texture_ref;
4782 break;
4783 case GL_TEXTURE_CUBE_MAP:
4784 unit.bound_texture_cube_map = texture_ref;
4785 break;
4786 case GL_TEXTURE_EXTERNAL_OES:
4787 unit.bound_texture_external_oes = texture_ref;
4788 break;
4789 case GL_TEXTURE_RECTANGLE_ARB:
4790 unit.bound_texture_rectangle_arb = texture_ref;
4791 break;
4792 case GL_TEXTURE_3D:
4793 unit.bound_texture_3d = texture_ref;
4794 break;
4795 case GL_TEXTURE_2D_ARRAY:
4796 unit.bound_texture_2d_array = texture_ref;
4797 break;
4798 default:
4799 NOTREACHED(); // Validation should prevent us getting here.
4800 break;
4804 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4805 if (state_.vertex_attrib_manager->Enable(index, false)) {
4806 if (index != 0 ||
4807 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4808 glDisableVertexAttribArray(index);
4810 } else {
4811 LOCAL_SET_GL_ERROR(
4812 GL_INVALID_VALUE,
4813 "glDisableVertexAttribArray", "index out of range");
4817 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4818 GLsizei numAttachments,
4819 const GLenum* attachments) {
4820 if (workarounds().disable_discard_framebuffer)
4821 return;
4823 Framebuffer* framebuffer =
4824 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4826 // Validates the attachments. If one of them fails
4827 // the whole command fails.
4828 for (GLsizei i = 0; i < numAttachments; ++i) {
4829 if ((framebuffer &&
4830 !validators_->attachment.IsValid(attachments[i])) ||
4831 (!framebuffer &&
4832 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4833 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4834 "glDiscardFramebufferEXT", attachments[i], "attachments");
4835 return;
4839 // Marks each one of them as not cleared
4840 for (GLsizei i = 0; i < numAttachments; ++i) {
4841 if (framebuffer) {
4842 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4843 texture_manager(),
4844 attachments[i],
4845 false);
4846 } else {
4847 switch (attachments[i]) {
4848 case GL_COLOR_EXT:
4849 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4850 break;
4851 case GL_DEPTH_EXT:
4852 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4853 case GL_STENCIL_EXT:
4854 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4855 break;
4856 default:
4857 NOTREACHED();
4858 break;
4863 // If the default framebuffer is bound but we are still rendering to an
4864 // FBO, translate attachment names that refer to default framebuffer
4865 // channels to corresponding framebuffer attachments.
4866 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4867 for (GLsizei i = 0; i < numAttachments; ++i) {
4868 GLenum attachment = attachments[i];
4869 if (!framebuffer && GetBackbufferServiceId()) {
4870 switch (attachment) {
4871 case GL_COLOR_EXT:
4872 attachment = GL_COLOR_ATTACHMENT0;
4873 break;
4874 case GL_DEPTH_EXT:
4875 attachment = GL_DEPTH_ATTACHMENT;
4876 break;
4877 case GL_STENCIL_EXT:
4878 attachment = GL_STENCIL_ATTACHMENT;
4879 break;
4880 default:
4881 NOTREACHED();
4882 return;
4885 translated_attachments[i] = attachment;
4888 ScopedRenderTo do_render(framebuffer);
4889 if (feature_info_->gl_version_info().is_es3) {
4890 glInvalidateFramebuffer(
4891 target, numAttachments, translated_attachments.get());
4892 } else {
4893 glDiscardFramebufferEXT(
4894 target, numAttachments, translated_attachments.get());
4898 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4899 if (state_.vertex_attrib_manager->Enable(index, true)) {
4900 glEnableVertexAttribArray(index);
4901 } else {
4902 LOCAL_SET_GL_ERROR(
4903 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4907 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4908 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4909 &state_, target);
4910 if (!texture_ref ||
4911 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4912 LOCAL_SET_GL_ERROR(
4913 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4914 return;
4917 if (target == GL_TEXTURE_CUBE_MAP) {
4918 for (int i = 0; i < 6; ++i) {
4919 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4920 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4921 LOCAL_SET_GL_ERROR(
4922 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4923 return;
4926 } else {
4927 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4928 LOCAL_SET_GL_ERROR(
4929 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4930 return;
4934 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4935 // Workaround for Mac driver bug. In the large scheme of things setting
4936 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4937 // hit so there's probably no need to make this conditional. The bug appears
4938 // to be that if the filtering mode is set to something that doesn't require
4939 // mipmaps for rendering, or is never set to something other than the default,
4940 // then glGenerateMipmap misbehaves.
4941 if (workarounds().set_texture_filter_before_generating_mipmap) {
4942 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4944 glGenerateMipmapEXT(target);
4945 if (workarounds().set_texture_filter_before_generating_mipmap) {
4946 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4947 texture_ref->texture()->min_filter());
4949 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4950 if (error == GL_NO_ERROR) {
4951 texture_manager()->MarkMipmapsGenerated(texture_ref);
4955 bool GLES2DecoderImpl::GetHelper(
4956 GLenum pname, GLint* params, GLsizei* num_written) {
4957 DCHECK(num_written);
4958 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4959 switch (pname) {
4960 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4961 *num_written = 1;
4962 // Return the GL implementation's preferred format and (see below type)
4963 // if we have the GL extension that exposes this. This allows the GPU
4964 // client to use the implementation's preferred format for glReadPixels
4965 // for optimisation.
4967 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4968 // case when requested on integer/floating point buffers but which is
4969 // acceptable on GLES2 and with the GL_OES_read_format extension.
4971 // Therefore if an error occurs we swallow the error and use the
4972 // internal implementation.
4973 if (params) {
4974 if (context_->HasExtension("GL_OES_read_format")) {
4975 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4976 GetErrorState());
4977 glGetIntegerv(pname, params);
4978 if (glGetError() == GL_NO_ERROR)
4979 return true;
4981 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4982 GetBoundReadFrameBufferInternalFormat());
4984 return true;
4985 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4986 *num_written = 1;
4987 if (params) {
4988 if (context_->HasExtension("GL_OES_read_format")) {
4989 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4990 GetErrorState());
4991 glGetIntegerv(pname, params);
4992 if (glGetError() == GL_NO_ERROR)
4993 return true;
4995 *params = GLES2Util::GetPreferredGLReadPixelsType(
4996 GetBoundReadFrameBufferInternalFormat(),
4997 GetBoundReadFrameBufferTextureType());
4999 return true;
5000 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
5001 *num_written = 1;
5002 if (params) {
5003 *params = group_->max_fragment_uniform_vectors();
5005 return true;
5006 case GL_MAX_VARYING_VECTORS:
5007 *num_written = 1;
5008 if (params) {
5009 *params = group_->max_varying_vectors();
5011 return true;
5012 case GL_MAX_VERTEX_UNIFORM_VECTORS:
5013 *num_written = 1;
5014 if (params) {
5015 *params = group_->max_vertex_uniform_vectors();
5017 return true;
5020 if (unsafe_es3_apis_enabled()) {
5021 switch (pname) {
5022 case GL_MAX_VARYING_COMPONENTS: {
5023 if (feature_info_->gl_version_info().is_es) {
5024 // We can just delegate this query to the driver.
5025 return false;
5028 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5029 // OpenGL core profile, so for simplicity, just compute it
5030 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5031 // configurations.
5032 GLint max_varying_vectors = 0;
5033 glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors);
5034 *num_written = 1;
5035 if (params) {
5036 *params = max_varying_vectors * 4;
5038 return true;
5040 case GL_READ_BUFFER:
5041 *num_written = 1;
5042 if (params) {
5043 Framebuffer* framebuffer =
5044 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
5045 GLenum read_buffer;
5046 if (framebuffer) {
5047 read_buffer = framebuffer->read_buffer();
5048 } else {
5049 read_buffer = back_buffer_read_buffer_;
5051 *params = static_cast<GLint>(read_buffer);
5053 return true;
5056 switch (pname) {
5057 case GL_MAX_VIEWPORT_DIMS:
5058 if (offscreen_target_frame_buffer_.get()) {
5059 *num_written = 2;
5060 if (params) {
5061 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5062 params[1] = renderbuffer_manager()->max_renderbuffer_size();
5064 return true;
5066 return false;
5067 case GL_MAX_SAMPLES:
5068 *num_written = 1;
5069 if (params) {
5070 params[0] = renderbuffer_manager()->max_samples();
5072 return true;
5073 case GL_MAX_RENDERBUFFER_SIZE:
5074 *num_written = 1;
5075 if (params) {
5076 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5078 return true;
5079 case GL_MAX_TEXTURE_SIZE:
5080 *num_written = 1;
5081 if (params) {
5082 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
5084 return true;
5085 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
5086 *num_written = 1;
5087 if (params) {
5088 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
5090 return true;
5091 case GL_MAX_COLOR_ATTACHMENTS_EXT:
5092 *num_written = 1;
5093 if (params) {
5094 params[0] = group_->max_color_attachments();
5096 return true;
5097 case GL_MAX_DRAW_BUFFERS_ARB:
5098 *num_written = 1;
5099 if (params) {
5100 params[0] = group_->max_draw_buffers();
5102 return true;
5103 case GL_ALPHA_BITS:
5104 *num_written = 1;
5105 if (params) {
5106 GLint v = 0;
5107 Framebuffer* framebuffer =
5108 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5109 if (framebuffer) {
5110 if (framebuffer->HasAlphaMRT() &&
5111 framebuffer->HasSameInternalFormatsMRT()) {
5112 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5113 glGetFramebufferAttachmentParameterivEXT(
5114 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5115 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
5116 } else {
5117 glGetIntegerv(GL_ALPHA_BITS, &v);
5120 } else {
5121 v = (BackBufferHasAlpha() ? 8 : 0);
5123 params[0] = v;
5125 return true;
5126 case GL_DEPTH_BITS:
5127 *num_written = 1;
5128 if (params) {
5129 GLint v = 0;
5130 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5131 Framebuffer* framebuffer =
5132 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5133 if (framebuffer) {
5134 glGetFramebufferAttachmentParameterivEXT(
5135 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
5136 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
5137 } else {
5138 v = (back_buffer_has_depth_ ? 24 : 0);
5140 } else {
5141 glGetIntegerv(GL_DEPTH_BITS, &v);
5143 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
5145 return true;
5146 case GL_RED_BITS:
5147 case GL_GREEN_BITS:
5148 case GL_BLUE_BITS:
5149 *num_written = 1;
5150 if (params) {
5151 GLint v = 0;
5152 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5153 Framebuffer* framebuffer =
5154 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5155 if (framebuffer) {
5156 GLenum framebuffer_enum = 0;
5157 switch (pname) {
5158 case GL_RED_BITS:
5159 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
5160 break;
5161 case GL_GREEN_BITS:
5162 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
5163 break;
5164 case GL_BLUE_BITS:
5165 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
5166 break;
5168 glGetFramebufferAttachmentParameterivEXT(
5169 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
5170 } else {
5171 v = 8;
5173 } else {
5174 glGetIntegerv(pname, &v);
5176 params[0] = v;
5178 return true;
5179 case GL_STENCIL_BITS:
5180 *num_written = 1;
5181 if (params) {
5182 GLint v = 0;
5183 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5184 Framebuffer* framebuffer =
5185 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5186 if (framebuffer) {
5187 glGetFramebufferAttachmentParameterivEXT(
5188 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
5189 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
5190 } else {
5191 v = (back_buffer_has_stencil_ ? 8 : 0);
5193 } else {
5194 glGetIntegerv(GL_STENCIL_BITS, &v);
5196 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
5198 return true;
5199 case GL_COMPRESSED_TEXTURE_FORMATS:
5200 *num_written = validators_->compressed_texture_format.GetValues().size();
5201 if (params) {
5202 for (GLint ii = 0; ii < *num_written; ++ii) {
5203 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
5206 return true;
5207 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
5208 *num_written = 1;
5209 if (params) {
5210 *params = validators_->compressed_texture_format.GetValues().size();
5212 return true;
5213 case GL_NUM_SHADER_BINARY_FORMATS:
5214 *num_written = 1;
5215 if (params) {
5216 *params = validators_->shader_binary_format.GetValues().size();
5218 return true;
5219 case GL_SHADER_BINARY_FORMATS:
5220 *num_written = validators_->shader_binary_format.GetValues().size();
5221 if (params) {
5222 for (GLint ii = 0; ii < *num_written; ++ii) {
5223 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5226 return true;
5227 case GL_SHADER_COMPILER:
5228 *num_written = 1;
5229 if (params) {
5230 *params = GL_TRUE;
5232 return true;
5233 case GL_ARRAY_BUFFER_BINDING:
5234 *num_written = 1;
5235 if (params) {
5236 *params = GetClientId(
5237 buffer_manager(), state_.bound_array_buffer.get());
5239 return true;
5240 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5241 *num_written = 1;
5242 if (params) {
5243 *params = GetClientId(
5244 buffer_manager(),
5245 state_.vertex_attrib_manager->element_array_buffer());
5247 return true;
5248 case GL_COPY_READ_BUFFER_BINDING:
5249 *num_written = 1;
5250 if (params) {
5251 *params = GetClientId(
5252 buffer_manager(), state_.bound_copy_read_buffer.get());
5254 return true;
5255 case GL_COPY_WRITE_BUFFER_BINDING:
5256 *num_written = 1;
5257 if (params) {
5258 *params = GetClientId(
5259 buffer_manager(), state_.bound_copy_write_buffer.get());
5261 return true;
5262 case GL_PIXEL_PACK_BUFFER_BINDING:
5263 *num_written = 1;
5264 if (params) {
5265 *params = GetClientId(
5266 buffer_manager(), state_.bound_pixel_pack_buffer.get());
5268 return true;
5269 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5270 *num_written = 1;
5271 if (params) {
5272 *params = GetClientId(
5273 buffer_manager(), state_.bound_pixel_unpack_buffer.get());
5275 return true;
5276 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5277 *num_written = 1;
5278 if (params) {
5279 *params = GetClientId(
5280 buffer_manager(), state_.bound_transform_feedback_buffer.get());
5282 return true;
5283 case GL_UNIFORM_BUFFER_BINDING:
5284 *num_written = 1;
5285 if (params) {
5286 *params = GetClientId(
5287 buffer_manager(), state_.bound_uniform_buffer.get());
5289 return true;
5290 case GL_FRAMEBUFFER_BINDING:
5291 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5292 *num_written = 1;
5293 if (params) {
5294 *params = GetClientId(
5295 framebuffer_manager(),
5296 GetFramebufferInfoForTarget(GL_FRAMEBUFFER));
5298 return true;
5299 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5300 *num_written = 1;
5301 if (params) {
5302 *params = GetClientId(
5303 framebuffer_manager(),
5304 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT));
5306 return true;
5307 case GL_RENDERBUFFER_BINDING:
5308 *num_written = 1;
5309 if (params) {
5310 Renderbuffer* renderbuffer =
5311 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5312 if (renderbuffer) {
5313 *params = renderbuffer->client_id();
5314 } else {
5315 *params = 0;
5318 return true;
5319 case GL_CURRENT_PROGRAM:
5320 *num_written = 1;
5321 if (params) {
5322 *params = GetClientId(program_manager(), state_.current_program.get());
5324 return true;
5325 case GL_VERTEX_ARRAY_BINDING_OES:
5326 *num_written = 1;
5327 if (params) {
5328 if (state_.vertex_attrib_manager.get() !=
5329 state_.default_vertex_attrib_manager.get()) {
5330 GLuint client_id = 0;
5331 vertex_array_manager_->GetClientId(
5332 state_.vertex_attrib_manager->service_id(), &client_id);
5333 *params = client_id;
5334 } else {
5335 *params = 0;
5338 return true;
5339 case GL_TEXTURE_BINDING_2D:
5340 *num_written = 1;
5341 if (params) {
5342 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5343 if (unit.bound_texture_2d.get()) {
5344 *params = unit.bound_texture_2d->client_id();
5345 } else {
5346 *params = 0;
5349 return true;
5350 case GL_TEXTURE_BINDING_CUBE_MAP:
5351 *num_written = 1;
5352 if (params) {
5353 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5354 if (unit.bound_texture_cube_map.get()) {
5355 *params = unit.bound_texture_cube_map->client_id();
5356 } else {
5357 *params = 0;
5360 return true;
5361 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5362 *num_written = 1;
5363 if (params) {
5364 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5365 if (unit.bound_texture_external_oes.get()) {
5366 *params = unit.bound_texture_external_oes->client_id();
5367 } else {
5368 *params = 0;
5371 return true;
5372 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5373 *num_written = 1;
5374 if (params) {
5375 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5376 if (unit.bound_texture_rectangle_arb.get()) {
5377 *params = unit.bound_texture_rectangle_arb->client_id();
5378 } else {
5379 *params = 0;
5382 return true;
5383 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5384 *num_written = 1;
5385 if (params) {
5386 params[0] = group_->bind_generates_resource() ? 1 : 0;
5388 return true;
5389 default:
5390 if (pname >= GL_DRAW_BUFFER0_ARB &&
5391 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5392 *num_written = 1;
5393 if (params) {
5394 Framebuffer* framebuffer =
5395 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5396 if (framebuffer) {
5397 params[0] = framebuffer->GetDrawBuffer(pname);
5398 } else { // backbuffer
5399 if (pname == GL_DRAW_BUFFER0_ARB)
5400 params[0] = back_buffer_draw_buffer_;
5401 else
5402 params[0] = GL_NONE;
5405 return true;
5407 *num_written = util_.GLGetNumValuesReturned(pname);
5408 return false;
5412 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5413 GLenum pname, GLsizei* num_values) {
5414 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5415 return true;
5417 return GetHelper(pname, NULL, num_values);
5420 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5421 if (GL_MAX_SAMPLES == pname &&
5422 features().use_img_for_multisampled_render_to_texture) {
5423 return GL_MAX_SAMPLES_IMG;
5425 return pname;
5428 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5429 DCHECK(params);
5430 GLsizei num_written = 0;
5431 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5432 scoped_ptr<GLint[]> values(new GLint[num_written]);
5433 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5434 GetHelper(pname, values.get(), &num_written);
5436 for (GLsizei ii = 0; ii < num_written; ++ii) {
5437 params[ii] = static_cast<GLboolean>(values[ii]);
5439 } else {
5440 pname = AdjustGetPname(pname);
5441 glGetBooleanv(pname, params);
5445 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5446 DCHECK(params);
5447 GLsizei num_written = 0;
5448 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5449 if (GetHelper(pname, NULL, &num_written)) {
5450 scoped_ptr<GLint[]> values(new GLint[num_written]);
5451 GetHelper(pname, values.get(), &num_written);
5452 for (GLsizei ii = 0; ii < num_written; ++ii) {
5453 params[ii] = static_cast<GLfloat>(values[ii]);
5455 } else {
5456 pname = AdjustGetPname(pname);
5457 glGetFloatv(pname, params);
5462 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5463 DCHECK(params);
5464 if (unsafe_es3_apis_enabled()) {
5465 switch (pname) {
5466 case GL_MAX_ELEMENT_INDEX: {
5467 if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
5468 feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
5469 glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
5470 } else {
5471 // Assume that desktop GL implementations can generally support
5472 // 32-bit indices.
5473 if (params) {
5474 *params = std::numeric_limits<unsigned int>::max();
5477 return;
5481 pname = AdjustGetPname(pname);
5482 glGetInteger64v(pname, params);
5485 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5486 DCHECK(params);
5487 GLsizei num_written;
5488 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5489 !GetHelper(pname, params, &num_written)) {
5490 pname = AdjustGetPname(pname);
5491 glGetIntegerv(pname, params);
5495 void GLES2DecoderImpl::DoGetProgramiv(
5496 GLuint program_id, GLenum pname, GLint* params) {
5497 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5498 if (!program) {
5499 return;
5501 program->GetProgramiv(pname, params);
5504 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5505 GLenum target, GLenum pname, GLint64* params) {
5506 // Just delegate it. Some validation is actually done before this.
5507 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5508 &state_, target, pname, params);
5511 void GLES2DecoderImpl::DoGetBufferParameteriv(
5512 GLenum target, GLenum pname, GLint* params) {
5513 // Just delegate it. Some validation is actually done before this.
5514 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5515 &state_, target, pname, params);
5518 void GLES2DecoderImpl::DoBindAttribLocation(
5519 GLuint program_id, GLuint index, const char* name) {
5520 if (!StringIsValidForGLES(name)) {
5521 LOCAL_SET_GL_ERROR(
5522 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5523 return;
5525 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5526 LOCAL_SET_GL_ERROR(
5527 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5528 return;
5530 if (index >= group_->max_vertex_attribs()) {
5531 LOCAL_SET_GL_ERROR(
5532 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5533 return;
5535 Program* program = GetProgramInfoNotShader(
5536 program_id, "glBindAttribLocation");
5537 if (!program) {
5538 return;
5540 // At this point, the program's shaders may not be translated yet,
5541 // therefore, we may not find the hashed attribute name.
5542 // glBindAttribLocation call with original name is useless.
5543 // So instead, we should simply cache the binding, and then call
5544 // Program::ExecuteBindAttribLocationCalls() right before link.
5545 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5546 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5547 glBindAttribLocation(program->service_id(), index, name);
5550 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5551 uint32 immediate_data_size,
5552 const void* cmd_data) {
5553 const gles2::cmds::BindAttribLocationBucket& c =
5554 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5555 GLuint program = static_cast<GLuint>(c.program);
5556 GLuint index = static_cast<GLuint>(c.index);
5557 Bucket* bucket = GetBucket(c.name_bucket_id);
5558 if (!bucket || bucket->size() == 0) {
5559 return error::kInvalidArguments;
5561 std::string name_str;
5562 if (!bucket->GetAsString(&name_str)) {
5563 return error::kInvalidArguments;
5565 DoBindAttribLocation(program, index, name_str.c_str());
5566 return error::kNoError;
5569 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5570 GLuint program_id, GLint location, const char* name) {
5571 if (!StringIsValidForGLES(name)) {
5572 LOCAL_SET_GL_ERROR(
5573 GL_INVALID_VALUE,
5574 "glBindUniformLocationCHROMIUM", "Invalid character");
5575 return;
5577 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5578 LOCAL_SET_GL_ERROR(
5579 GL_INVALID_OPERATION,
5580 "glBindUniformLocationCHROMIUM", "reserved prefix");
5581 return;
5583 if (location < 0 || static_cast<uint32>(location) >=
5584 (group_->max_fragment_uniform_vectors() +
5585 group_->max_vertex_uniform_vectors()) * 4) {
5586 LOCAL_SET_GL_ERROR(
5587 GL_INVALID_VALUE,
5588 "glBindUniformLocationCHROMIUM", "location out of range");
5589 return;
5591 Program* program = GetProgramInfoNotShader(
5592 program_id, "glBindUniformLocationCHROMIUM");
5593 if (!program) {
5594 return;
5596 if (!program->SetUniformLocationBinding(name, location)) {
5597 LOCAL_SET_GL_ERROR(
5598 GL_INVALID_VALUE,
5599 "glBindUniformLocationCHROMIUM", "location out of range");
5603 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5604 uint32 immediate_data_size,
5605 const void* cmd_data) {
5606 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5607 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5608 cmd_data);
5609 GLuint program = static_cast<GLuint>(c.program);
5610 GLint location = static_cast<GLint>(c.location);
5611 Bucket* bucket = GetBucket(c.name_bucket_id);
5612 if (!bucket || bucket->size() == 0) {
5613 return error::kInvalidArguments;
5615 std::string name_str;
5616 if (!bucket->GetAsString(&name_str)) {
5617 return error::kInvalidArguments;
5619 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5620 return error::kNoError;
5623 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5624 const void* cmd_data) {
5625 const gles2::cmds::DeleteShader& c =
5626 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5627 GLuint client_id = c.shader;
5628 if (client_id) {
5629 Shader* shader = GetShader(client_id);
5630 if (shader) {
5631 if (!shader->IsDeleted()) {
5632 shader_manager()->Delete(shader);
5634 } else {
5635 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5638 return error::kNoError;
5641 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5642 const void* cmd_data) {
5643 const gles2::cmds::DeleteProgram& c =
5644 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5645 GLuint client_id = c.program;
5646 if (client_id) {
5647 Program* program = GetProgram(client_id);
5648 if (program) {
5649 if (!program->IsDeleted()) {
5650 program_manager()->MarkAsDeleted(shader_manager(), program);
5652 } else {
5653 LOCAL_SET_GL_ERROR(
5654 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5657 return error::kNoError;
5660 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5661 DCHECK(!ShouldDeferDraws());
5662 if (CheckBoundFramebuffersValid("glClear")) {
5663 ApplyDirtyState();
5664 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5665 if (workarounds().gl_clear_broken) {
5666 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5667 GetErrorState());
5668 if (!BoundFramebufferHasDepthAttachment())
5669 mask &= ~GL_DEPTH_BUFFER_BIT;
5670 if (!BoundFramebufferHasStencilAttachment())
5671 mask &= ~GL_STENCIL_BUFFER_BIT;
5672 clear_framebuffer_blit_->ClearFramebuffer(
5673 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5674 state_.color_clear_green, state_.color_clear_blue,
5675 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5676 return error::kNoError;
5678 glClear(mask);
5680 return error::kNoError;
5683 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5684 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5685 GLuint client_renderbuffer_id) {
5686 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5687 if (!framebuffer) {
5688 LOCAL_SET_GL_ERROR(
5689 GL_INVALID_OPERATION,
5690 "glFramebufferRenderbuffer", "no framebuffer bound");
5691 return;
5693 GLuint service_id = 0;
5694 Renderbuffer* renderbuffer = NULL;
5695 if (client_renderbuffer_id) {
5696 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5697 if (!renderbuffer) {
5698 LOCAL_SET_GL_ERROR(
5699 GL_INVALID_OPERATION,
5700 "glFramebufferRenderbuffer", "unknown renderbuffer");
5701 return;
5703 service_id = renderbuffer->service_id();
5705 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5706 glFramebufferRenderbufferEXT(
5707 target, attachment, renderbuffertarget, service_id);
5708 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5709 if (error == GL_NO_ERROR) {
5710 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5712 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5713 framebuffer_state_.clear_state_dirty = true;
5715 OnFboChanged();
5718 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5719 if (SetCapabilityState(cap, false)) {
5720 glDisable(cap);
5724 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5725 if (SetCapabilityState(cap, true)) {
5726 glEnable(cap);
5730 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5731 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5732 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5733 glDepthRange(znear, zfar);
5736 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5737 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5738 state_.sample_coverage_invert = (invert != 0);
5739 glSampleCoverage(state_.sample_coverage_value, invert);
5742 // Assumes framebuffer is complete.
5743 void GLES2DecoderImpl::ClearUnclearedAttachments(
5744 GLenum target, Framebuffer* framebuffer) {
5745 if (target == GL_READ_FRAMEBUFFER_EXT) {
5746 // bind this to the DRAW point, clear then bind back to READ
5747 // TODO(gman): I don't think there is any guarantee that an FBO that
5748 // is complete on the READ attachment will be complete as a DRAW
5749 // attachment.
5750 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5751 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5753 GLbitfield clear_bits = 0;
5754 if (framebuffer->HasUnclearedColorAttachments()) {
5755 // We should always use alpha == 0 here, because 1) some draw buffers may
5756 // have alpha and some may not; 2) we won't have the same situation as the
5757 // back buffer where alpha channel exists but is not requested.
5758 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
5759 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5760 clear_bits |= GL_COLOR_BUFFER_BIT;
5761 if (feature_info_->feature_flags().ext_draw_buffers)
5762 framebuffer->PrepareDrawBuffersForClear();
5765 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5766 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5767 glClearStencil(0);
5768 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5769 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5770 clear_bits |= GL_STENCIL_BUFFER_BIT;
5773 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5774 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5775 glClearDepth(1.0f);
5776 state_.SetDeviceDepthMask(GL_TRUE);
5777 clear_bits |= GL_DEPTH_BUFFER_BIT;
5780 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5781 glClear(clear_bits);
5783 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5784 feature_info_->feature_flags().ext_draw_buffers)
5785 framebuffer->RestoreDrawBuffersAfterClear();
5787 framebuffer_manager()->MarkAttachmentsAsCleared(
5788 framebuffer, renderbuffer_manager(), texture_manager());
5790 RestoreClearState();
5792 if (target == GL_READ_FRAMEBUFFER_EXT) {
5793 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5794 Framebuffer* draw_framebuffer =
5795 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5796 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5797 GetBackbufferServiceId();
5798 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5802 void GLES2DecoderImpl::RestoreClearState() {
5803 framebuffer_state_.clear_state_dirty = true;
5804 glClearColor(
5805 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5806 state_.color_clear_alpha);
5807 glClearStencil(state_.stencil_clear);
5808 glClearDepth(state_.depth_clear);
5809 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5810 state_.enable_flags.scissor_test);
5811 glScissor(state_.scissor_x, state_.scissor_y, state_.scissor_width,
5812 state_.scissor_height);
5815 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5816 Framebuffer* framebuffer =
5817 GetFramebufferInfoForTarget(target);
5818 if (!framebuffer) {
5819 return GL_FRAMEBUFFER_COMPLETE;
5821 GLenum completeness = framebuffer->IsPossiblyComplete();
5822 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5823 return completeness;
5825 return framebuffer->GetStatus(texture_manager(), target);
5828 void GLES2DecoderImpl::DoFramebufferTexture2D(
5829 GLenum target, GLenum attachment, GLenum textarget,
5830 GLuint client_texture_id, GLint level) {
5831 DoFramebufferTexture2DCommon(
5832 "glFramebufferTexture2D", target, attachment,
5833 textarget, client_texture_id, level, 0);
5836 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5837 GLenum target, GLenum attachment, GLenum textarget,
5838 GLuint client_texture_id, GLint level, GLsizei samples) {
5839 DoFramebufferTexture2DCommon(
5840 "glFramebufferTexture2DMultisample", target, attachment,
5841 textarget, client_texture_id, level, samples);
5844 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5845 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5846 GLuint client_texture_id, GLint level, GLsizei samples) {
5847 if (samples > renderbuffer_manager()->max_samples()) {
5848 LOCAL_SET_GL_ERROR(
5849 GL_INVALID_VALUE,
5850 "glFramebufferTexture2DMultisample", "samples too large");
5851 return;
5853 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5854 if (!framebuffer) {
5855 LOCAL_SET_GL_ERROR(
5856 GL_INVALID_OPERATION,
5857 name, "no framebuffer bound.");
5858 return;
5860 GLuint service_id = 0;
5861 TextureRef* texture_ref = NULL;
5862 if (client_texture_id) {
5863 texture_ref = GetTexture(client_texture_id);
5864 if (!texture_ref) {
5865 LOCAL_SET_GL_ERROR(
5866 GL_INVALID_OPERATION,
5867 name, "unknown texture_ref");
5868 return;
5870 service_id = texture_ref->service_id();
5873 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5874 LOCAL_SET_GL_ERROR(
5875 GL_INVALID_VALUE,
5876 name, "level out of range");
5877 return;
5880 if (texture_ref)
5881 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5883 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5884 if (0 == samples) {
5885 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5886 } else {
5887 if (features().use_img_for_multisampled_render_to_texture) {
5888 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5889 service_id, level, samples);
5890 } else {
5891 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5892 service_id, level, samples);
5895 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5896 if (error == GL_NO_ERROR) {
5897 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5898 samples);
5900 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5901 framebuffer_state_.clear_state_dirty = true;
5904 if (texture_ref)
5905 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5907 OnFboChanged();
5910 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5911 GLenum target, GLenum attachment, GLuint client_texture_id,
5912 GLint level, GLint layer) {
5913 // TODO(zmo): Unsafe ES3 API, missing states update.
5914 GLuint service_id = 0;
5915 TextureRef* texture_ref = NULL;
5916 if (client_texture_id) {
5917 texture_ref = GetTexture(client_texture_id);
5918 if (!texture_ref) {
5919 LOCAL_SET_GL_ERROR(
5920 GL_INVALID_OPERATION,
5921 "glFramebufferTextureLayer", "unknown texture_ref");
5922 return;
5924 service_id = texture_ref->service_id();
5926 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5929 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5930 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5931 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5932 if (!framebuffer) {
5933 LOCAL_SET_GL_ERROR(
5934 GL_INVALID_OPERATION,
5935 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5936 return;
5938 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5939 const Framebuffer::Attachment* attachment_object =
5940 framebuffer->GetAttachment(attachment);
5941 *params = attachment_object ? attachment_object->object_name() : 0;
5942 } else {
5943 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5944 features().use_img_for_multisampled_render_to_texture) {
5945 pname = GL_TEXTURE_SAMPLES_IMG;
5947 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5951 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5952 GLenum target, GLenum pname, GLint* params) {
5953 Renderbuffer* renderbuffer =
5954 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5955 if (!renderbuffer) {
5956 LOCAL_SET_GL_ERROR(
5957 GL_INVALID_OPERATION,
5958 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5959 return;
5962 EnsureRenderbufferBound();
5963 switch (pname) {
5964 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5965 *params = renderbuffer->internal_format();
5966 break;
5967 case GL_RENDERBUFFER_WIDTH:
5968 *params = renderbuffer->width();
5969 break;
5970 case GL_RENDERBUFFER_HEIGHT:
5971 *params = renderbuffer->height();
5972 break;
5973 case GL_RENDERBUFFER_SAMPLES_EXT:
5974 if (features().use_img_for_multisampled_render_to_texture) {
5975 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5976 params);
5977 } else {
5978 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5979 params);
5981 default:
5982 glGetRenderbufferParameterivEXT(target, pname, params);
5983 break;
5987 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5988 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5989 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5990 GLbitfield mask, GLenum filter) {
5991 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5993 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5994 return;
5997 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5998 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5999 BlitFramebufferHelper(
6000 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6001 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
6002 state_.enable_flags.scissor_test);
6005 void GLES2DecoderImpl::EnsureRenderbufferBound() {
6006 if (!state_.bound_renderbuffer_valid) {
6007 state_.bound_renderbuffer_valid = true;
6008 glBindRenderbufferEXT(GL_RENDERBUFFER,
6009 state_.bound_renderbuffer.get()
6010 ? state_.bound_renderbuffer->service_id()
6011 : 0);
6015 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6016 const FeatureInfo* feature_info,
6017 GLenum target,
6018 GLsizei samples,
6019 GLenum internal_format,
6020 GLsizei width,
6021 GLsizei height) {
6022 // TODO(sievers): This could be resolved at the GL binding level, but the
6023 // binding process is currently a bit too 'brute force'.
6024 if (feature_info->gl_version_info().is_angle) {
6025 glRenderbufferStorageMultisampleANGLE(
6026 target, samples, internal_format, width, height);
6027 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
6028 glRenderbufferStorageMultisample(
6029 target, samples, internal_format, width, height);
6030 } else {
6031 glRenderbufferStorageMultisampleEXT(
6032 target, samples, internal_format, width, height);
6036 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
6037 GLint srcY0,
6038 GLint srcX1,
6039 GLint srcY1,
6040 GLint dstX0,
6041 GLint dstY0,
6042 GLint dstX1,
6043 GLint dstY1,
6044 GLbitfield mask,
6045 GLenum filter) {
6046 // TODO(sievers): This could be resolved at the GL binding level, but the
6047 // binding process is currently a bit too 'brute force'.
6048 if (feature_info_->gl_version_info().is_angle) {
6049 glBlitFramebufferANGLE(
6050 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6051 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
6052 glBlitFramebuffer(
6053 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6054 } else {
6055 glBlitFramebufferEXT(
6056 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6060 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6061 GLsizei samples,
6062 GLenum internalformat,
6063 GLsizei width,
6064 GLsizei height) {
6065 if (samples > renderbuffer_manager()->max_samples()) {
6066 LOCAL_SET_GL_ERROR(
6067 GL_INVALID_VALUE,
6068 "glRenderbufferStorageMultisample", "samples too large");
6069 return false;
6072 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6073 height > renderbuffer_manager()->max_renderbuffer_size()) {
6074 LOCAL_SET_GL_ERROR(
6075 GL_INVALID_VALUE,
6076 "glRenderbufferStorageMultisample", "dimensions too large");
6077 return false;
6080 uint32 estimated_size = 0;
6081 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6082 width, height, samples, internalformat, &estimated_size)) {
6083 LOCAL_SET_GL_ERROR(
6084 GL_OUT_OF_MEMORY,
6085 "glRenderbufferStorageMultisample", "dimensions too large");
6086 return false;
6089 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6090 LOCAL_SET_GL_ERROR(
6091 GL_OUT_OF_MEMORY,
6092 "glRenderbufferStorageMultisample", "out of memory");
6093 return false;
6096 return true;
6099 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6100 GLenum target, GLsizei samples, GLenum internalformat,
6101 GLsizei width, GLsizei height) {
6102 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6103 if (!renderbuffer) {
6104 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6105 "glRenderbufferStorageMultisampleCHROMIUM",
6106 "no renderbuffer bound");
6107 return;
6110 if (!ValidateRenderbufferStorageMultisample(
6111 samples, internalformat, width, height)) {
6112 return;
6115 EnsureRenderbufferBound();
6116 GLenum impl_format =
6117 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6118 internalformat);
6119 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6120 "glRenderbufferStorageMultisampleCHROMIUM");
6121 RenderbufferStorageMultisampleHelper(
6122 feature_info_.get(), target, samples, impl_format, width, height);
6123 GLenum error =
6124 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6125 if (error == GL_NO_ERROR) {
6126 if (workarounds().validate_multisample_buffer_allocation) {
6127 if (!VerifyMultisampleRenderbufferIntegrity(
6128 renderbuffer->service_id(), impl_format)) {
6129 LOCAL_SET_GL_ERROR(
6130 GL_OUT_OF_MEMORY,
6131 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6132 return;
6136 // TODO(gman): If renderbuffers tracked which framebuffers they were
6137 // attached to we could just mark those framebuffers as not complete.
6138 framebuffer_manager()->IncFramebufferStateChangeCount();
6139 renderbuffer_manager()->SetInfo(
6140 renderbuffer, samples, internalformat, width, height);
6144 // This is the handler for multisampled_render_to_texture extensions.
6145 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6146 GLenum target, GLsizei samples, GLenum internalformat,
6147 GLsizei width, GLsizei height) {
6148 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6149 if (!renderbuffer) {
6150 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6151 "glRenderbufferStorageMultisampleEXT",
6152 "no renderbuffer bound");
6153 return;
6156 if (!ValidateRenderbufferStorageMultisample(
6157 samples, internalformat, width, height)) {
6158 return;
6161 EnsureRenderbufferBound();
6162 GLenum impl_format =
6163 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6164 internalformat);
6165 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6166 if (features().use_img_for_multisampled_render_to_texture) {
6167 glRenderbufferStorageMultisampleIMG(
6168 target, samples, impl_format, width, height);
6169 } else {
6170 glRenderbufferStorageMultisampleEXT(
6171 target, samples, impl_format, width, height);
6173 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6174 if (error == GL_NO_ERROR) {
6175 // TODO(gman): If renderbuffers tracked which framebuffers they were
6176 // attached to we could just mark those framebuffers as not complete.
6177 framebuffer_manager()->IncFramebufferStateChangeCount();
6178 renderbuffer_manager()->SetInfo(
6179 renderbuffer, samples, internalformat, width, height);
6183 // This function validates the allocation of a multisampled renderbuffer
6184 // by clearing it to a key color, blitting the contents to a texture, and
6185 // reading back the color to ensure it matches the key.
6186 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6187 GLuint renderbuffer, GLenum format) {
6189 // Only validate color buffers.
6190 // These formats have been selected because they are very common or are known
6191 // to be used by the WebGL backbuffer. If problems are observed with other
6192 // color formats they can be added here.
6193 switch (format) {
6194 case GL_RGB:
6195 case GL_RGB8:
6196 case GL_RGBA:
6197 case GL_RGBA8:
6198 break;
6199 default:
6200 return true;
6203 GLint draw_framebuffer, read_framebuffer;
6205 // Cache framebuffer and texture bindings.
6206 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
6207 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
6209 if (!validation_texture_) {
6210 GLint bound_texture;
6211 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
6213 // Create additional resources needed for the verification.
6214 glGenTextures(1, &validation_texture_);
6215 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
6216 glGenFramebuffersEXT(1, &validation_fbo_);
6218 // Texture only needs to be 1x1.
6219 glBindTexture(GL_TEXTURE_2D, validation_texture_);
6220 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6221 // multisample will fail if the color format of the source and destination
6222 // do not match. Here, we assume that the source is GL_RGBA, and make the
6223 // destination GL_RGBA. http://crbug.com/484203
6224 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
6225 GL_UNSIGNED_BYTE, NULL);
6227 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6228 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6229 GL_TEXTURE_2D, validation_texture_, 0);
6231 glBindTexture(GL_TEXTURE_2D, bound_texture);
6234 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6235 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6236 GL_RENDERBUFFER, renderbuffer);
6238 // Cache current state and reset it to the values we require.
6239 GLboolean scissor_enabled = false;
6240 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6241 if (scissor_enabled)
6242 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6244 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6245 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6246 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6248 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6249 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6250 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6252 // Clear the buffer to the desired key color.
6253 glClear(GL_COLOR_BUFFER_BIT);
6255 // Blit from the multisample buffer to a standard texture.
6256 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6257 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6259 BlitFramebufferHelper(
6260 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6262 // Read a pixel from the buffer.
6263 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6265 unsigned char pixel[3] = {0, 0, 0};
6266 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6268 // Detach the renderbuffer.
6269 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6270 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6271 GL_RENDERBUFFER, 0);
6273 // Restore cached state.
6274 if (scissor_enabled)
6275 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6277 state_.SetDeviceColorMask(
6278 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6279 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6280 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6281 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6283 // Return true if the pixel matched the desired key color.
6284 return (pixel[0] == 0xFF &&
6285 pixel[1] == 0x00 &&
6286 pixel[2] == 0xFF);
6289 void GLES2DecoderImpl::DoRenderbufferStorage(
6290 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6291 Renderbuffer* renderbuffer =
6292 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6293 if (!renderbuffer) {
6294 LOCAL_SET_GL_ERROR(
6295 GL_INVALID_OPERATION,
6296 "glRenderbufferStorage", "no renderbuffer bound");
6297 return;
6300 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6301 height > renderbuffer_manager()->max_renderbuffer_size()) {
6302 LOCAL_SET_GL_ERROR(
6303 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6304 return;
6307 uint32 estimated_size = 0;
6308 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6309 width, height, 1, internalformat, &estimated_size)) {
6310 LOCAL_SET_GL_ERROR(
6311 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6312 return;
6315 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6316 LOCAL_SET_GL_ERROR(
6317 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6318 return;
6321 EnsureRenderbufferBound();
6322 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6323 glRenderbufferStorageEXT(
6324 target,
6325 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6326 internalformat),
6327 width,
6328 height);
6329 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6330 if (error == GL_NO_ERROR) {
6331 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6332 // we could just mark those framebuffers as not complete.
6333 framebuffer_manager()->IncFramebufferStateChangeCount();
6334 renderbuffer_manager()->SetInfo(
6335 renderbuffer, 1, internalformat, width, height);
6339 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6340 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6341 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6342 Program* program = GetProgramInfoNotShader(
6343 program_id, "glLinkProgram");
6344 if (!program) {
6345 return;
6348 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6349 if (program->Link(shader_manager(),
6350 workarounds().count_all_in_varyings_packing ?
6351 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6352 shader_cache_callback_)) {
6353 if (program == state_.current_program.get()) {
6354 if (workarounds().use_current_program_after_successful_link)
6355 glUseProgram(program->service_id());
6356 if (workarounds().clear_uniforms_before_first_program_use)
6357 program_manager()->ClearUniforms(program);
6361 // LinkProgram can be very slow. Exit command processing to allow for
6362 // context preemption and GPU watchdog checks.
6363 ExitCommandProcessingEarly();
6366 void GLES2DecoderImpl::DoReadBuffer(GLenum src) {
6367 switch (src) {
6368 case GL_NONE:
6369 case GL_BACK:
6370 break;
6371 default:
6373 GLenum upper_limit = static_cast<GLenum>(
6374 group_->max_color_attachments() + GL_COLOR_ATTACHMENT0);
6375 if (src < GL_COLOR_ATTACHMENT0 || src >= upper_limit) {
6376 LOCAL_SET_GL_ERROR(
6377 GL_INVALID_ENUM, "glReadBuffer", "invalid enum for src");
6378 return;
6381 break;
6384 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
6385 if (framebuffer) {
6386 if (src == GL_BACK) {
6387 LOCAL_SET_GL_ERROR(
6388 GL_INVALID_ENUM, "glReadBuffer",
6389 "invalid src for a named framebuffer");
6390 return;
6392 framebuffer->set_read_buffer(src);
6393 } else {
6394 if (src != GL_NONE && src != GL_BACK) {
6395 LOCAL_SET_GL_ERROR(
6396 GL_INVALID_ENUM, "glReadBuffer",
6397 "invalid src for the default framebuffer");
6398 return;
6400 back_buffer_read_buffer_ = src;
6401 if (GetBackbufferServiceId() && src == GL_BACK)
6402 src = GL_COLOR_ATTACHMENT0;
6404 glReadBuffer(src);
6407 void GLES2DecoderImpl::DoSamplerParameterfv(
6408 GLuint sampler, GLenum pname, const GLfloat* params) {
6409 DCHECK(params);
6410 glSamplerParameterf(sampler, pname, params[0]);
6413 void GLES2DecoderImpl::DoSamplerParameteriv(
6414 GLuint sampler, GLenum pname, const GLint* params) {
6415 DCHECK(params);
6416 glSamplerParameteri(sampler, pname, params[0]);
6419 void GLES2DecoderImpl::DoTexParameterf(
6420 GLenum target, GLenum pname, GLfloat param) {
6421 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6422 &state_, target);
6423 if (!texture) {
6424 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6425 return;
6428 texture_manager()->SetParameterf(
6429 "glTexParameterf", GetErrorState(), texture, pname, param);
6432 void GLES2DecoderImpl::DoTexParameteri(
6433 GLenum target, GLenum pname, GLint param) {
6434 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6435 &state_, target);
6436 if (!texture) {
6437 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6438 return;
6441 texture_manager()->SetParameteri(
6442 "glTexParameteri", GetErrorState(), texture, pname, param);
6445 void GLES2DecoderImpl::DoTexParameterfv(
6446 GLenum target, GLenum pname, const GLfloat* params) {
6447 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6448 &state_, target);
6449 if (!texture) {
6450 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6451 return;
6454 texture_manager()->SetParameterf(
6455 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6458 void GLES2DecoderImpl::DoTexParameteriv(
6459 GLenum target, GLenum pname, const GLint* params) {
6460 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6461 &state_, target);
6462 if (!texture) {
6463 LOCAL_SET_GL_ERROR(
6464 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6465 return;
6468 texture_manager()->SetParameteri(
6469 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6472 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6473 if (!state_.bound_valuebuffer.get()) {
6474 // There is no valuebuffer bound
6475 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6476 "no valuebuffer in use");
6477 return false;
6479 return true;
6482 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6483 GLenum subscription,
6484 const char* function_name) {
6485 if (!CheckCurrentValuebuffer(function_name)) {
6486 return false;
6488 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6489 // The valuebuffer is not subscribed to the target
6490 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6491 "valuebuffer is not subscribed");
6492 return false;
6494 return true;
6497 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6498 GLenum subscription,
6499 const char* function_name) {
6500 if (!CheckCurrentProgramForUniform(location, function_name)) {
6501 return false;
6503 GLint real_location = -1;
6504 GLint array_index = -1;
6505 const Program::UniformInfo* info =
6506 state_.current_program->GetUniformInfoByFakeLocation(
6507 location, &real_location, &array_index);
6508 if (!info) {
6509 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6510 return false;
6512 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6513 info->accepts_api_type) == 0) {
6514 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6515 "wrong type for subscription");
6516 return false;
6518 return true;
6521 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6522 if (!state_.current_program.get()) {
6523 // The program does not exist.
6524 LOCAL_SET_GL_ERROR(
6525 GL_INVALID_OPERATION, function_name, "no program in use");
6526 return false;
6528 if (!state_.current_program->InUse()) {
6529 LOCAL_SET_GL_ERROR(
6530 GL_INVALID_OPERATION, function_name, "program not linked");
6531 return false;
6533 return true;
6536 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6537 GLint location, const char* function_name) {
6538 if (!CheckCurrentProgram(function_name)) {
6539 return false;
6541 return location != -1;
6544 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6545 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6546 if (!framebuffer)
6547 return false;
6548 const Framebuffer::Attachment* attachment =
6549 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6550 if (!attachment)
6551 return false;
6553 DCHECK(state_.current_program.get());
6554 const Program::SamplerIndices& sampler_indices =
6555 state_.current_program->sampler_indices();
6556 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6557 const Program::UniformInfo* uniform_info =
6558 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6559 DCHECK(uniform_info);
6560 if (uniform_info->type != GL_SAMPLER_2D)
6561 continue;
6562 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6563 GLuint texture_unit_index = uniform_info->texture_units[jj];
6564 if (texture_unit_index >= state_.texture_units.size())
6565 continue;
6566 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6567 TextureRef* texture_ref =
6568 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6569 if (attachment->IsTexture(texture_ref))
6570 return true;
6573 return false;
6576 bool GLES2DecoderImpl::CheckUniformForApiType(
6577 const Program::UniformInfo* info,
6578 const char* function_name,
6579 Program::UniformApiType api_type) {
6580 DCHECK(info);
6581 if ((api_type & info->accepts_api_type) == 0) {
6582 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6583 "wrong uniform function for type");
6584 return false;
6586 return true;
6589 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6590 GLint fake_location,
6591 const char* function_name,
6592 Program::UniformApiType api_type,
6593 GLint* real_location,
6594 GLenum* type,
6595 GLsizei* count) {
6596 DCHECK(type);
6597 DCHECK(count);
6598 DCHECK(real_location);
6600 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6601 return false;
6603 GLint array_index = -1;
6604 const Program::UniformInfo* info =
6605 state_.current_program->GetUniformInfoByFakeLocation(
6606 fake_location, real_location, &array_index);
6607 if (!info) {
6608 LOCAL_SET_GL_ERROR(
6609 GL_INVALID_OPERATION, function_name, "unknown location");
6610 return false;
6612 if (!CheckUniformForApiType(info, function_name, api_type)) {
6613 return false;
6615 if (*count > 1 && !info->is_array) {
6616 LOCAL_SET_GL_ERROR(
6617 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6618 return false;
6620 *count = std::min(info->size - array_index, *count);
6621 if (*count <= 0) {
6622 return false;
6624 *type = info->type;
6625 return true;
6628 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6629 GLenum type = 0;
6630 GLsizei count = 1;
6631 GLint real_location = -1;
6632 if (!PrepForSetUniformByLocation(fake_location,
6633 "glUniform1i",
6634 Program::kUniform1i,
6635 &real_location,
6636 &type,
6637 &count)) {
6638 return;
6640 if (!state_.current_program->SetSamplers(
6641 state_.texture_units.size(), fake_location, 1, &v0)) {
6642 LOCAL_SET_GL_ERROR(
6643 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6644 return;
6646 glUniform1i(real_location, v0);
6649 void GLES2DecoderImpl::DoUniform1iv(
6650 GLint fake_location, GLsizei count, const GLint *value) {
6651 GLenum type = 0;
6652 GLint real_location = -1;
6653 if (!PrepForSetUniformByLocation(fake_location,
6654 "glUniform1iv",
6655 Program::kUniform1i,
6656 &real_location,
6657 &type,
6658 &count)) {
6659 return;
6661 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6662 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6663 if (!state_.current_program->SetSamplers(
6664 state_.texture_units.size(), fake_location, count, value)) {
6665 LOCAL_SET_GL_ERROR(
6666 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6667 return;
6670 glUniform1iv(real_location, count, value);
6673 void GLES2DecoderImpl::DoUniform1fv(
6674 GLint fake_location, GLsizei count, const GLfloat* value) {
6675 GLenum type = 0;
6676 GLint real_location = -1;
6677 if (!PrepForSetUniformByLocation(fake_location,
6678 "glUniform1fv",
6679 Program::kUniform1f,
6680 &real_location,
6681 &type,
6682 &count)) {
6683 return;
6685 if (type == GL_BOOL) {
6686 scoped_ptr<GLint[]> temp(new GLint[count]);
6687 for (GLsizei ii = 0; ii < count; ++ii) {
6688 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6690 DoUniform1iv(real_location, count, temp.get());
6691 } else {
6692 glUniform1fv(real_location, count, value);
6696 void GLES2DecoderImpl::DoUniform2fv(
6697 GLint fake_location, GLsizei count, const GLfloat* value) {
6698 GLenum type = 0;
6699 GLint real_location = -1;
6700 if (!PrepForSetUniformByLocation(fake_location,
6701 "glUniform2fv",
6702 Program::kUniform2f,
6703 &real_location,
6704 &type,
6705 &count)) {
6706 return;
6708 if (type == GL_BOOL_VEC2) {
6709 GLsizei num_values = count * 2;
6710 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6711 for (GLsizei ii = 0; ii < num_values; ++ii) {
6712 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6714 glUniform2iv(real_location, count, temp.get());
6715 } else {
6716 glUniform2fv(real_location, count, value);
6720 void GLES2DecoderImpl::DoUniform3fv(
6721 GLint fake_location, GLsizei count, const GLfloat* value) {
6722 GLenum type = 0;
6723 GLint real_location = -1;
6724 if (!PrepForSetUniformByLocation(fake_location,
6725 "glUniform3fv",
6726 Program::kUniform3f,
6727 &real_location,
6728 &type,
6729 &count)) {
6730 return;
6732 if (type == GL_BOOL_VEC3) {
6733 GLsizei num_values = count * 3;
6734 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6735 for (GLsizei ii = 0; ii < num_values; ++ii) {
6736 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6738 glUniform3iv(real_location, count, temp.get());
6739 } else {
6740 glUniform3fv(real_location, count, value);
6744 void GLES2DecoderImpl::DoUniform4fv(
6745 GLint fake_location, GLsizei count, const GLfloat* value) {
6746 GLenum type = 0;
6747 GLint real_location = -1;
6748 if (!PrepForSetUniformByLocation(fake_location,
6749 "glUniform4fv",
6750 Program::kUniform4f,
6751 &real_location,
6752 &type,
6753 &count)) {
6754 return;
6756 if (type == GL_BOOL_VEC4) {
6757 GLsizei num_values = count * 4;
6758 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6759 for (GLsizei ii = 0; ii < num_values; ++ii) {
6760 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6762 glUniform4iv(real_location, count, temp.get());
6763 } else {
6764 glUniform4fv(real_location, count, value);
6768 void GLES2DecoderImpl::DoUniform2iv(
6769 GLint fake_location, GLsizei count, const GLint* value) {
6770 GLenum type = 0;
6771 GLint real_location = -1;
6772 if (!PrepForSetUniformByLocation(fake_location,
6773 "glUniform2iv",
6774 Program::kUniform2i,
6775 &real_location,
6776 &type,
6777 &count)) {
6778 return;
6780 glUniform2iv(real_location, count, value);
6783 void GLES2DecoderImpl::DoUniform3iv(
6784 GLint fake_location, GLsizei count, const GLint* value) {
6785 GLenum type = 0;
6786 GLint real_location = -1;
6787 if (!PrepForSetUniformByLocation(fake_location,
6788 "glUniform3iv",
6789 Program::kUniform3i,
6790 &real_location,
6791 &type,
6792 &count)) {
6793 return;
6795 glUniform3iv(real_location, count, value);
6798 void GLES2DecoderImpl::DoUniform4iv(
6799 GLint fake_location, GLsizei count, const GLint* value) {
6800 GLenum type = 0;
6801 GLint real_location = -1;
6802 if (!PrepForSetUniformByLocation(fake_location,
6803 "glUniform4iv",
6804 Program::kUniform4i,
6805 &real_location,
6806 &type,
6807 &count)) {
6808 return;
6810 glUniform4iv(real_location, count, value);
6813 void GLES2DecoderImpl::DoUniformMatrix2fv(
6814 GLint fake_location, GLsizei count, GLboolean transpose,
6815 const GLfloat* value) {
6816 GLenum type = 0;
6817 GLint real_location = -1;
6818 if (!PrepForSetUniformByLocation(fake_location,
6819 "glUniformMatrix2fv",
6820 Program::kUniformMatrix2f,
6821 &real_location,
6822 &type,
6823 &count)) {
6824 return;
6826 glUniformMatrix2fv(real_location, count, transpose, value);
6829 void GLES2DecoderImpl::DoUniformMatrix3fv(
6830 GLint fake_location, GLsizei count, GLboolean transpose,
6831 const GLfloat* value) {
6832 GLenum type = 0;
6833 GLint real_location = -1;
6834 if (!PrepForSetUniformByLocation(fake_location,
6835 "glUniformMatrix3fv",
6836 Program::kUniformMatrix3f,
6837 &real_location,
6838 &type,
6839 &count)) {
6840 return;
6842 glUniformMatrix3fv(real_location, count, transpose, value);
6845 void GLES2DecoderImpl::DoUniformMatrix4fv(
6846 GLint fake_location, GLsizei count, GLboolean transpose,
6847 const GLfloat* value) {
6848 GLenum type = 0;
6849 GLint real_location = -1;
6850 if (!PrepForSetUniformByLocation(fake_location,
6851 "glUniformMatrix4fv",
6852 Program::kUniformMatrix4f,
6853 &real_location,
6854 &type,
6855 &count)) {
6856 return;
6858 glUniformMatrix4fv(real_location, count, transpose, value);
6861 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6862 GLuint service_id = 0;
6863 Program* program = NULL;
6864 if (program_id) {
6865 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6866 if (!program) {
6867 return;
6869 if (!program->IsValid()) {
6870 // Program was not linked successfully. (ie, glLinkProgram)
6871 LOCAL_SET_GL_ERROR(
6872 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6873 return;
6875 service_id = program->service_id();
6877 if (state_.current_program.get()) {
6878 program_manager()->UnuseProgram(shader_manager(),
6879 state_.current_program.get());
6881 state_.current_program = program;
6882 LogClientServiceMapping("glUseProgram", program_id, service_id);
6883 glUseProgram(service_id);
6884 if (state_.current_program.get()) {
6885 program_manager()->UseProgram(state_.current_program.get());
6886 if (workarounds().clear_uniforms_before_first_program_use)
6887 program_manager()->ClearUniforms(program);
6891 void GLES2DecoderImpl::RenderWarning(
6892 const char* filename, int line, const std::string& msg) {
6893 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6896 void GLES2DecoderImpl::PerformanceWarning(
6897 const char* filename, int line, const std::string& msg) {
6898 logger_.LogMessage(filename, line,
6899 std::string("PERFORMANCE WARNING: ") + msg);
6902 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6903 Texture* texture, GLenum textarget) {
6904 // Image is already in use if texture is attached to a framebuffer.
6905 if (texture && !texture->IsAttachedToFramebuffer()) {
6906 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6907 if (image) {
6908 ScopedGLErrorSuppressor suppressor(
6909 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6910 GetErrorState());
6911 glBindTexture(textarget, texture->service_id());
6912 image->WillUseTexImage();
6913 RestoreCurrentTextureBindings(&state_, textarget);
6918 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6919 Texture* texture, GLenum textarget) {
6920 // Image is still in use if texture is attached to a framebuffer.
6921 if (texture && !texture->IsAttachedToFramebuffer()) {
6922 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6923 if (image) {
6924 ScopedGLErrorSuppressor suppressor(
6925 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6926 GetErrorState());
6927 glBindTexture(textarget, texture->service_id());
6928 image->DidUseTexImage();
6929 RestoreCurrentTextureBindings(&state_, textarget);
6934 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6935 DCHECK(state_.current_program.get());
6936 if (!texture_manager()->HaveUnrenderableTextures() &&
6937 !texture_manager()->HaveImages()) {
6938 return true;
6941 bool textures_set = false;
6942 const Program::SamplerIndices& sampler_indices =
6943 state_.current_program->sampler_indices();
6944 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6945 const Program::UniformInfo* uniform_info =
6946 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6947 DCHECK(uniform_info);
6948 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6949 GLuint texture_unit_index = uniform_info->texture_units[jj];
6950 if (texture_unit_index < state_.texture_units.size()) {
6951 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6952 TextureRef* texture_ref =
6953 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6954 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6955 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6956 textures_set = true;
6957 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6958 glBindTexture(
6959 textarget,
6960 texture_manager()->black_texture_id(uniform_info->type));
6961 if (!texture_ref) {
6962 LOCAL_RENDER_WARNING(
6963 std::string("there is no texture bound to the unit ") +
6964 base::IntToString(texture_unit_index));
6965 } else {
6966 LOCAL_RENDER_WARNING(
6967 std::string("texture bound to texture unit ") +
6968 base::IntToString(texture_unit_index) +
6969 " is not renderable. It maybe non-power-of-2 and have"
6970 " incompatible texture filtering.");
6972 continue;
6975 if (textarget != GL_TEXTURE_CUBE_MAP) {
6976 Texture* texture = texture_ref->texture();
6977 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6978 if (image && !texture->IsAttachedToFramebuffer()) {
6979 ScopedGLErrorSuppressor suppressor(
6980 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6981 textures_set = true;
6982 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6983 image->WillUseTexImage();
6984 continue;
6988 // else: should this be an error?
6991 return !textures_set;
6994 void GLES2DecoderImpl::RestoreStateForTextures() {
6995 DCHECK(state_.current_program.get());
6996 const Program::SamplerIndices& sampler_indices =
6997 state_.current_program->sampler_indices();
6998 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6999 const Program::UniformInfo* uniform_info =
7000 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7001 DCHECK(uniform_info);
7002 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7003 GLuint texture_unit_index = uniform_info->texture_units[jj];
7004 if (texture_unit_index < state_.texture_units.size()) {
7005 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7006 TextureRef* texture_ref =
7007 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7008 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
7009 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7010 // Get the texture_ref info that was previously bound here.
7011 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
7012 ? texture_unit.bound_texture_2d.get()
7013 : texture_unit.bound_texture_cube_map.get();
7014 glBindTexture(texture_unit.bind_target,
7015 texture_ref ? texture_ref->service_id() : 0);
7016 continue;
7019 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
7020 Texture* texture = texture_ref->texture();
7021 gfx::GLImage* image =
7022 texture->GetLevelImage(texture_unit.bind_target, 0);
7023 if (image && !texture->IsAttachedToFramebuffer()) {
7024 ScopedGLErrorSuppressor suppressor(
7025 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7026 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7027 image->DidUseTexImage();
7028 continue;
7034 // Set the active texture back to whatever the user had it as.
7035 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
7038 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7039 // Only check if there are some uncleared textures.
7040 if (!texture_manager()->HaveUnsafeTextures()) {
7041 return true;
7044 // 1: Check all textures we are about to render with.
7045 if (state_.current_program.get()) {
7046 const Program::SamplerIndices& sampler_indices =
7047 state_.current_program->sampler_indices();
7048 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7049 const Program::UniformInfo* uniform_info =
7050 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7051 DCHECK(uniform_info);
7052 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7053 GLuint texture_unit_index = uniform_info->texture_units[jj];
7054 if (texture_unit_index < state_.texture_units.size()) {
7055 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7056 TextureRef* texture_ref =
7057 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7058 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
7059 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
7060 return false;
7067 return true;
7070 bool GLES2DecoderImpl::IsDrawValid(
7071 const char* function_name, GLuint max_vertex_accessed, bool instanced,
7072 GLsizei primcount) {
7073 DCHECK(instanced || primcount == 1);
7075 // NOTE: We specifically do not check current_program->IsValid() because
7076 // it could never be invalid since glUseProgram would have failed. While
7077 // glLinkProgram could later mark the program as invalid the previous
7078 // valid program will still function if it is still the current program.
7079 if (!state_.current_program.get()) {
7080 // The program does not exist.
7081 // But GL says no ERROR.
7082 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7083 return false;
7086 if (CheckDrawingFeedbackLoops()) {
7087 LOCAL_SET_GL_ERROR(
7088 GL_INVALID_OPERATION, function_name,
7089 "Source and destination textures of the draw are the same.");
7090 return false;
7093 return state_.vertex_attrib_manager
7094 ->ValidateBindings(function_name,
7095 this,
7096 feature_info_.get(),
7097 state_.current_program.get(),
7098 max_vertex_accessed,
7099 instanced,
7100 primcount);
7103 bool GLES2DecoderImpl::SimulateAttrib0(
7104 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
7105 DCHECK(simulated);
7106 *simulated = false;
7108 if (feature_info_->gl_version_info().BehavesLikeGLES())
7109 return true;
7111 const VertexAttrib* attrib =
7112 state_.vertex_attrib_manager->GetVertexAttrib(0);
7113 // If it's enabled or it's not used then we don't need to do anything.
7114 bool attrib_0_used =
7115 state_.current_program->GetAttribInfoByLocation(0) != NULL;
7116 if (attrib->enabled() && attrib_0_used) {
7117 return true;
7120 // Make a buffer with a single repeated vec4 value enough to
7121 // simulate the constant value that is supposed to be here.
7122 // This is required to emulate GLES2 on GL.
7123 GLuint num_vertices = max_vertex_accessed + 1;
7124 uint32 size_needed = 0;
7126 if (num_vertices == 0 ||
7127 !SafeMultiplyUint32(num_vertices, sizeof(Vec4f), &size_needed) ||
7128 size_needed > 0x7FFFFFFFU) {
7129 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7130 return false;
7133 LOCAL_PERFORMANCE_WARNING(
7134 "Attribute 0 is disabled. This has signficant performance penalty");
7136 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7137 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
7139 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
7140 if (new_buffer) {
7141 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7142 GLenum error = glGetError();
7143 if (error != GL_NO_ERROR) {
7144 LOCAL_SET_GL_ERROR(
7145 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7146 return false;
7150 const Vec4& value = state_.attrib_values[0];
7151 if (new_buffer ||
7152 (attrib_0_used &&
7153 (!attrib_0_buffer_matches_value_ || !value.Equal(attrib_0_value_)))){
7154 // TODO(zmo): This is not 100% correct because we might lose data when
7155 // casting to float type, but it is a corner case and once we migrate to
7156 // core profiles on desktop GL, it is no longer relevant.
7157 Vec4f fvalue(value);
7158 std::vector<Vec4f> temp(num_vertices, fvalue);
7159 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
7160 attrib_0_buffer_matches_value_ = true;
7161 attrib_0_value_ = value;
7162 attrib_0_size_ = size_needed;
7165 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
7167 if (attrib->divisor())
7168 glVertexAttribDivisorANGLE(0, 0);
7170 *simulated = true;
7171 return true;
7174 void GLES2DecoderImpl::RestoreStateForAttrib(
7175 GLuint attrib_index, bool restore_array_binding) {
7176 const VertexAttrib* attrib =
7177 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
7178 if (restore_array_binding) {
7179 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
7180 Buffer* buffer = attrib->buffer();
7181 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
7182 glVertexAttribPointer(
7183 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
7184 attrib->gl_stride(), ptr);
7186 if (attrib->divisor())
7187 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
7188 glBindBuffer(
7189 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
7190 state_.bound_array_buffer->service_id() : 0);
7192 // Never touch vertex attribute 0's state (in particular, never
7193 // disable it) when running on desktop GL because it will never be
7194 // re-enabled.
7195 if (attrib_index != 0 ||
7196 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
7197 if (attrib->enabled()) {
7198 glEnableVertexAttribArray(attrib_index);
7199 } else {
7200 glDisableVertexAttribArray(attrib_index);
7205 bool GLES2DecoderImpl::SimulateFixedAttribs(
7206 const char* function_name,
7207 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
7208 DCHECK(simulated);
7209 *simulated = false;
7210 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
7211 return true;
7213 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
7214 return true;
7217 LOCAL_PERFORMANCE_WARNING(
7218 "GL_FIXED attributes have a signficant performance penalty");
7220 // NOTE: we could be smart and try to check if a buffer is used
7221 // twice in 2 different attribs, find the overlapping parts and therefore
7222 // duplicate the minimum amount of data but this whole code path is not meant
7223 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7224 // tests so we just add to the buffer attrib used.
7226 GLuint elements_needed = 0;
7227 const VertexAttribManager::VertexAttribList& enabled_attribs =
7228 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
7229 for (VertexAttribManager::VertexAttribList::const_iterator it =
7230 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7231 const VertexAttrib* attrib = *it;
7232 const Program::VertexAttrib* attrib_info =
7233 state_.current_program->GetAttribInfoByLocation(attrib->index());
7234 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7235 max_vertex_accessed);
7236 GLuint num_vertices = max_accessed + 1;
7237 if (num_vertices == 0) {
7238 LOCAL_SET_GL_ERROR(
7239 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7240 return false;
7242 if (attrib_info &&
7243 attrib->CanAccess(max_accessed) &&
7244 attrib->type() == GL_FIXED) {
7245 uint32 elements_used = 0;
7246 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
7247 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
7248 LOCAL_SET_GL_ERROR(
7249 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7250 return false;
7255 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
7256 uint32 size_needed = 0;
7257 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
7258 size_needed > 0x7FFFFFFFU) {
7259 LOCAL_SET_GL_ERROR(
7260 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7261 return false;
7264 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7266 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
7267 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
7268 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7269 GLenum error = glGetError();
7270 if (error != GL_NO_ERROR) {
7271 LOCAL_SET_GL_ERROR(
7272 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7273 return false;
7277 // Copy the elements and convert to float
7278 GLintptr offset = 0;
7279 for (VertexAttribManager::VertexAttribList::const_iterator it =
7280 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7281 const VertexAttrib* attrib = *it;
7282 const Program::VertexAttrib* attrib_info =
7283 state_.current_program->GetAttribInfoByLocation(attrib->index());
7284 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7285 max_vertex_accessed);
7286 GLuint num_vertices = max_accessed + 1;
7287 if (num_vertices == 0) {
7288 LOCAL_SET_GL_ERROR(
7289 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7290 return false;
7292 if (attrib_info &&
7293 attrib->CanAccess(max_accessed) &&
7294 attrib->type() == GL_FIXED) {
7295 int num_elements = attrib->size() * num_vertices;
7296 const int src_size = num_elements * sizeof(int32);
7297 const int dst_size = num_elements * sizeof(float);
7298 scoped_ptr<float[]> data(new float[num_elements]);
7299 const int32* src = reinterpret_cast<const int32 *>(
7300 attrib->buffer()->GetRange(attrib->offset(), src_size));
7301 const int32* end = src + num_elements;
7302 float* dst = data.get();
7303 while (src != end) {
7304 *dst++ = static_cast<float>(*src++) / 65536.0f;
7306 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7307 glVertexAttribPointer(
7308 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7309 reinterpret_cast<GLvoid*>(offset));
7310 offset += dst_size;
7313 *simulated = true;
7314 return true;
7317 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7318 // There's no need to call glVertexAttribPointer because we shadow all the
7319 // settings and passing GL_FIXED to it will not work.
7320 glBindBuffer(
7321 GL_ARRAY_BUFFER,
7322 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7323 : 0);
7326 error::Error GLES2DecoderImpl::DoDrawArrays(
7327 const char* function_name,
7328 bool instanced,
7329 GLenum mode,
7330 GLint first,
7331 GLsizei count,
7332 GLsizei primcount) {
7333 error::Error error = WillAccessBoundFramebufferForDraw();
7334 if (error != error::kNoError)
7335 return error;
7336 if (!validators_->draw_mode.IsValid(mode)) {
7337 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7338 return error::kNoError;
7340 if (count < 0) {
7341 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7342 return error::kNoError;
7344 if (primcount < 0) {
7345 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7346 return error::kNoError;
7348 if (!CheckBoundFramebuffersValid(function_name)) {
7349 return error::kNoError;
7351 // We have to check this here because the prototype for glDrawArrays
7352 // is GLint not GLsizei.
7353 if (first < 0) {
7354 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7355 return error::kNoError;
7358 if (count == 0 || primcount == 0) {
7359 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7360 return error::kNoError;
7363 GLuint max_vertex_accessed = first + count - 1;
7364 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7365 if (!ClearUnclearedTextures()) {
7366 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7367 return error::kNoError;
7369 bool simulated_attrib_0 = false;
7370 if (!SimulateAttrib0(
7371 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7372 return error::kNoError;
7374 bool simulated_fixed_attribs = false;
7375 if (SimulateFixedAttribs(
7376 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7377 primcount)) {
7378 bool textures_set = !PrepareTexturesForRender();
7379 ApplyDirtyState();
7380 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7381 if (!instanced) {
7382 glDrawArrays(mode, first, count);
7383 } else {
7384 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7386 if (textures_set) {
7387 RestoreStateForTextures();
7389 if (simulated_fixed_attribs) {
7390 RestoreStateForSimulatedFixedAttribs();
7393 if (simulated_attrib_0) {
7394 // We don't have to restore attrib 0 generic data at the end of this
7395 // function even if it is simulated. This is because we will simulate
7396 // it in each draw call, and attrib 0 generic data queries use cached
7397 // values instead of passing down to the underlying driver.
7398 RestoreStateForAttrib(0, false);
7401 return error::kNoError;
7404 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7405 const void* cmd_data) {
7406 // TODO(zmo): crbug.com/481184
7407 // On Desktop GL with versions lower than 4.3, we need to emulate
7408 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7409 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7410 return DoDrawArrays("glDrawArrays",
7411 false,
7412 static_cast<GLenum>(c.mode),
7413 static_cast<GLint>(c.first),
7414 static_cast<GLsizei>(c.count),
7418 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7419 uint32 immediate_data_size,
7420 const void* cmd_data) {
7421 const gles2::cmds::DrawArraysInstancedANGLE& c =
7422 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7423 if (!features().angle_instanced_arrays) {
7424 LOCAL_SET_GL_ERROR(
7425 GL_INVALID_OPERATION,
7426 "glDrawArraysInstancedANGLE", "function not available");
7427 return error::kNoError;
7429 return DoDrawArrays("glDrawArraysIntancedANGLE",
7430 true,
7431 static_cast<GLenum>(c.mode),
7432 static_cast<GLint>(c.first),
7433 static_cast<GLsizei>(c.count),
7434 static_cast<GLsizei>(c.primcount));
7437 error::Error GLES2DecoderImpl::DoDrawElements(
7438 const char* function_name,
7439 bool instanced,
7440 GLenum mode,
7441 GLsizei count,
7442 GLenum type,
7443 int32 offset,
7444 GLsizei primcount) {
7445 error::Error error = WillAccessBoundFramebufferForDraw();
7446 if (error != error::kNoError)
7447 return error;
7448 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7449 LOCAL_SET_GL_ERROR(
7450 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7451 return error::kNoError;
7454 if (count < 0) {
7455 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7456 return error::kNoError;
7458 if (offset < 0) {
7459 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7460 return error::kNoError;
7462 if (!validators_->draw_mode.IsValid(mode)) {
7463 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7464 return error::kNoError;
7466 if (!validators_->index_type.IsValid(type)) {
7467 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7468 return error::kNoError;
7470 if (primcount < 0) {
7471 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7472 return error::kNoError;
7475 if (!CheckBoundFramebuffersValid(function_name)) {
7476 return error::kNoError;
7479 if (count == 0 || primcount == 0) {
7480 return error::kNoError;
7483 GLuint max_vertex_accessed;
7484 Buffer* element_array_buffer =
7485 state_.vertex_attrib_manager->element_array_buffer();
7487 if (!element_array_buffer->GetMaxValueForRange(
7488 offset, count, type, &max_vertex_accessed)) {
7489 LOCAL_SET_GL_ERROR(
7490 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7491 return error::kNoError;
7494 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7495 if (!ClearUnclearedTextures()) {
7496 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7497 return error::kNoError;
7499 bool simulated_attrib_0 = false;
7500 if (!SimulateAttrib0(
7501 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7502 return error::kNoError;
7504 bool simulated_fixed_attribs = false;
7505 if (SimulateFixedAttribs(
7506 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7507 primcount)) {
7508 bool textures_set = !PrepareTexturesForRender();
7509 ApplyDirtyState();
7510 // TODO(gman): Refactor to hide these details in BufferManager or
7511 // VertexAttribManager.
7512 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7513 bool used_client_side_array = false;
7514 if (element_array_buffer->IsClientSideArray()) {
7515 used_client_side_array = true;
7516 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7517 indices = element_array_buffer->GetRange(offset, 0);
7520 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7521 if (!instanced) {
7522 glDrawElements(mode, count, type, indices);
7523 } else {
7524 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7527 if (used_client_side_array) {
7528 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7529 element_array_buffer->service_id());
7532 if (textures_set) {
7533 RestoreStateForTextures();
7535 if (simulated_fixed_attribs) {
7536 RestoreStateForSimulatedFixedAttribs();
7539 if (simulated_attrib_0) {
7540 // We don't have to restore attrib 0 generic data at the end of this
7541 // function even if it is simulated. This is because we will simulate
7542 // it in each draw call, and attrib 0 generic data queries use cached
7543 // values instead of passing down to the underlying driver.
7544 RestoreStateForAttrib(0, false);
7547 return error::kNoError;
7550 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7551 const void* cmd_data) {
7552 // TODO(zmo): crbug.com/481184
7553 // On Desktop GL with versions lower than 4.3, we need to emulate
7554 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7555 const gles2::cmds::DrawElements& c =
7556 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7557 return DoDrawElements("glDrawElements",
7558 false,
7559 static_cast<GLenum>(c.mode),
7560 static_cast<GLsizei>(c.count),
7561 static_cast<GLenum>(c.type),
7562 static_cast<int32>(c.index_offset),
7566 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7567 uint32 immediate_data_size,
7568 const void* cmd_data) {
7569 const gles2::cmds::DrawElementsInstancedANGLE& c =
7570 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7571 if (!features().angle_instanced_arrays) {
7572 LOCAL_SET_GL_ERROR(
7573 GL_INVALID_OPERATION,
7574 "glDrawElementsInstancedANGLE", "function not available");
7575 return error::kNoError;
7577 return DoDrawElements("glDrawElementsInstancedANGLE",
7578 true,
7579 static_cast<GLenum>(c.mode),
7580 static_cast<GLsizei>(c.count),
7581 static_cast<GLenum>(c.type),
7582 static_cast<int32>(c.index_offset),
7583 static_cast<GLsizei>(c.primcount));
7586 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7587 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7588 GLuint max_vertex_accessed = 0;
7589 Buffer* buffer = GetBuffer(buffer_id);
7590 if (!buffer) {
7591 // TODO(gman): Should this be a GL error or a command buffer error?
7592 LOCAL_SET_GL_ERROR(
7593 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7594 } else {
7595 if (!buffer->GetMaxValueForRange(
7596 offset, count, type, &max_vertex_accessed)) {
7597 // TODO(gman): Should this be a GL error or a command buffer error?
7598 LOCAL_SET_GL_ERROR(
7599 GL_INVALID_OPERATION,
7600 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7603 return max_vertex_accessed;
7606 void GLES2DecoderImpl::DoShaderSource(
7607 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7608 std::string str;
7609 for (GLsizei ii = 0; ii < count; ++ii) {
7610 if (length && length[ii] > 0)
7611 str.append(data[ii], length[ii]);
7612 else
7613 str.append(data[ii]);
7615 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7616 if (!shader) {
7617 return;
7619 // Note: We don't actually call glShaderSource here. We wait until
7620 // we actually compile the shader.
7621 shader->set_source(str);
7624 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7625 GLuint client_program_id, GLsizei count, const char* const* varyings,
7626 GLenum buffer_mode) {
7627 Program* program = GetProgramInfoNotShader(
7628 client_program_id, "glTransformFeedbackVaryings");
7629 if (!program) {
7630 return;
7632 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7633 glTransformFeedbackVaryings(
7634 program->service_id(), count, varyings, buffer_mode);
7637 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7638 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7639 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7640 if (!shader) {
7641 return;
7644 scoped_refptr<ShaderTranslatorInterface> translator;
7645 if (use_shader_translator_) {
7646 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7647 vertex_translator_ : fragment_translator_;
7650 const Shader::TranslatedShaderSourceType source_type =
7651 feature_info_->feature_flags().angle_translated_shader_source ?
7652 Shader::kANGLE : Shader::kGL;
7653 shader->RequestCompile(translator, source_type);
7656 void GLES2DecoderImpl::DoGetShaderiv(
7657 GLuint shader_id, GLenum pname, GLint* params) {
7658 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7659 if (!shader) {
7660 return;
7663 // Compile now for statuses that require it.
7664 switch (pname) {
7665 case GL_COMPILE_STATUS:
7666 case GL_INFO_LOG_LENGTH:
7667 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7668 shader->DoCompile();
7669 break;
7671 default:
7672 break;
7675 switch (pname) {
7676 case GL_SHADER_SOURCE_LENGTH:
7677 *params = shader->source().size();
7678 if (*params)
7679 ++(*params);
7680 return;
7681 case GL_COMPILE_STATUS:
7682 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7683 return;
7684 case GL_INFO_LOG_LENGTH:
7685 *params = shader->log_info().size();
7686 if (*params)
7687 ++(*params);
7688 return;
7689 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7690 *params = shader->translated_source().size();
7691 if (*params)
7692 ++(*params);
7693 return;
7694 default:
7695 break;
7697 glGetShaderiv(shader->service_id(), pname, params);
7700 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7701 const void* cmd_data) {
7702 const gles2::cmds::GetShaderSource& c =
7703 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7704 GLuint shader_id = c.shader;
7705 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7706 Bucket* bucket = CreateBucket(bucket_id);
7707 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7708 if (!shader || shader->source().empty()) {
7709 bucket->SetSize(0);
7710 return error::kNoError;
7712 bucket->SetFromString(shader->source().c_str());
7713 return error::kNoError;
7716 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7717 uint32 immediate_data_size,
7718 const void* cmd_data) {
7719 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7720 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7721 cmd_data);
7722 GLuint shader_id = c.shader;
7723 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7724 Bucket* bucket = CreateBucket(bucket_id);
7725 Shader* shader = GetShaderInfoNotProgram(
7726 shader_id, "glGetTranslatedShaderSourceANGLE");
7727 if (!shader) {
7728 bucket->SetSize(0);
7729 return error::kNoError;
7732 // Make sure translator has been utilized in compile.
7733 shader->DoCompile();
7735 bucket->SetFromString(shader->translated_source().c_str());
7736 return error::kNoError;
7739 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7740 uint32 immediate_data_size,
7741 const void* cmd_data) {
7742 const gles2::cmds::GetProgramInfoLog& c =
7743 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7744 GLuint program_id = c.program;
7745 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7746 Bucket* bucket = CreateBucket(bucket_id);
7747 Program* program = GetProgramInfoNotShader(
7748 program_id, "glGetProgramInfoLog");
7749 if (!program || !program->log_info()) {
7750 bucket->SetFromString("");
7751 return error::kNoError;
7753 bucket->SetFromString(program->log_info()->c_str());
7754 return error::kNoError;
7757 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7758 uint32 immediate_data_size,
7759 const void* cmd_data) {
7760 const gles2::cmds::GetShaderInfoLog& c =
7761 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7762 GLuint shader_id = c.shader;
7763 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7764 Bucket* bucket = CreateBucket(bucket_id);
7765 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7766 if (!shader) {
7767 bucket->SetFromString("");
7768 return error::kNoError;
7771 // Shader must be compiled in order to get the info log.
7772 shader->DoCompile();
7774 bucket->SetFromString(shader->log_info().c_str());
7775 return error::kNoError;
7778 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7779 return state_.GetEnabled(cap);
7782 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7783 const Buffer* buffer = GetBuffer(client_id);
7784 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7787 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7788 const Framebuffer* framebuffer =
7789 GetFramebuffer(client_id);
7790 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7793 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7794 // IsProgram is true for programs as soon as they are created, until they are
7795 // deleted and no longer in use.
7796 const Program* program = GetProgram(client_id);
7797 return program != NULL && !program->IsDeleted();
7800 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7801 const Renderbuffer* renderbuffer =
7802 GetRenderbuffer(client_id);
7803 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7806 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7807 // IsShader is true for shaders as soon as they are created, until they
7808 // are deleted and not attached to any programs.
7809 const Shader* shader = GetShader(client_id);
7810 return shader != NULL && !shader->IsDeleted();
7813 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7814 const TextureRef* texture_ref = GetTexture(client_id);
7815 return texture_ref && texture_ref->texture()->IsValid();
7818 void GLES2DecoderImpl::DoAttachShader(
7819 GLuint program_client_id, GLint shader_client_id) {
7820 Program* program = GetProgramInfoNotShader(
7821 program_client_id, "glAttachShader");
7822 if (!program) {
7823 return;
7825 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7826 if (!shader) {
7827 return;
7829 if (!program->AttachShader(shader_manager(), shader)) {
7830 LOCAL_SET_GL_ERROR(
7831 GL_INVALID_OPERATION,
7832 "glAttachShader",
7833 "can not attach more than one shader of the same type.");
7834 return;
7836 glAttachShader(program->service_id(), shader->service_id());
7839 void GLES2DecoderImpl::DoDetachShader(
7840 GLuint program_client_id, GLint shader_client_id) {
7841 Program* program = GetProgramInfoNotShader(
7842 program_client_id, "glDetachShader");
7843 if (!program) {
7844 return;
7846 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7847 if (!shader) {
7848 return;
7850 if (!program->DetachShader(shader_manager(), shader)) {
7851 LOCAL_SET_GL_ERROR(
7852 GL_INVALID_OPERATION,
7853 "glDetachShader", "shader not attached to program");
7854 return;
7856 glDetachShader(program->service_id(), shader->service_id());
7859 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7860 Program* program = GetProgramInfoNotShader(
7861 program_client_id, "glValidateProgram");
7862 if (!program) {
7863 return;
7865 program->Validate();
7868 void GLES2DecoderImpl::GetVertexAttribHelper(
7869 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7870 switch (pname) {
7871 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
7873 Buffer* buffer = attrib->buffer();
7874 if (buffer && !buffer->IsDeleted()) {
7875 GLuint client_id;
7876 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7877 *params = client_id;
7879 break;
7881 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7882 *params = attrib->enabled();
7883 break;
7884 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7885 *params = attrib->size();
7886 break;
7887 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7888 *params = attrib->gl_stride();
7889 break;
7890 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7891 *params = attrib->type();
7892 break;
7893 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7894 *params = attrib->normalized();
7895 break;
7896 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
7897 *params = attrib->divisor();
7898 break;
7899 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
7900 *params = attrib->integer();
7901 break;
7902 default:
7903 NOTREACHED();
7904 break;
7908 void GLES2DecoderImpl::DoGetTexParameterfv(
7909 GLenum target, GLenum pname, GLfloat* params) {
7910 InitTextureMaxAnisotropyIfNeeded(target, pname);
7911 glGetTexParameterfv(target, pname, params);
7914 void GLES2DecoderImpl::DoGetTexParameteriv(
7915 GLenum target, GLenum pname, GLint* params) {
7916 InitTextureMaxAnisotropyIfNeeded(target, pname);
7917 glGetTexParameteriv(target, pname, params);
7920 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7921 GLenum target, GLenum pname) {
7922 if (!workarounds().init_texture_max_anisotropy)
7923 return;
7924 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7925 !validators_->texture_parameter.IsValid(pname)) {
7926 return;
7929 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7930 &state_, target);
7931 if (!texture_ref) {
7932 LOCAL_SET_GL_ERROR(
7933 GL_INVALID_OPERATION,
7934 "glGetTexParamter{fi}v", "unknown texture for target");
7935 return;
7937 Texture* texture = texture_ref->texture();
7938 texture->InitTextureMaxAnisotropyIfNeeded(target);
7941 template <typename T>
7942 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7943 GLuint index, GLenum pname, T* params) {
7944 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7945 if (!attrib) {
7946 LOCAL_SET_GL_ERROR(
7947 GL_INVALID_VALUE, "glGetVertexAttrib", "index out of range");
7948 return;
7950 switch (pname) {
7951 case GL_CURRENT_VERTEX_ATTRIB:
7952 state_.attrib_values[index].GetValues(params);
7953 break;
7954 default: {
7955 GLint value = 0;
7956 GetVertexAttribHelper(attrib, pname, &value);
7957 *params = static_cast<T>(value);
7958 break;
7963 void GLES2DecoderImpl::DoGetVertexAttribfv(
7964 GLuint index, GLenum pname, GLfloat* params) {
7965 DoGetVertexAttribImpl<GLfloat>(index, pname, params);
7968 void GLES2DecoderImpl::DoGetVertexAttribiv(
7969 GLuint index, GLenum pname, GLint* params) {
7970 DoGetVertexAttribImpl<GLint>(index, pname, params);
7973 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7974 GLuint index, GLenum pname, GLint* params) {
7975 DoGetVertexAttribImpl<GLint>(index, pname, params);
7978 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7979 GLuint index, GLenum pname, GLuint* params) {
7980 DoGetVertexAttribImpl<GLuint>(index, pname, params);
7983 template <typename T>
7984 bool GLES2DecoderImpl::SetVertexAttribValue(
7985 const char* function_name, GLuint index, const T* value) {
7986 if (index >= state_.attrib_values.size()) {
7987 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7988 return false;
7990 state_.attrib_values[index].SetValues(value);
7991 return true;
7994 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7995 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7996 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7997 glVertexAttrib1f(index, v0);
8001 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
8002 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
8003 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
8004 glVertexAttrib2f(index, v0, v1);
8008 void GLES2DecoderImpl::DoVertexAttrib3f(
8009 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
8010 GLfloat v[4] = { v0, v1, v2, 1.0f, };
8011 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
8012 glVertexAttrib3f(index, v0, v1, v2);
8016 void GLES2DecoderImpl::DoVertexAttrib4f(
8017 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
8018 GLfloat v[4] = { v0, v1, v2, v3, };
8019 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
8020 glVertexAttrib4f(index, v0, v1, v2, v3);
8024 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
8025 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
8026 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
8027 glVertexAttrib1fv(index, v);
8031 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
8032 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
8033 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
8034 glVertexAttrib2fv(index, v);
8038 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
8039 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
8040 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
8041 glVertexAttrib3fv(index, v);
8045 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
8046 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
8047 glVertexAttrib4fv(index, v);
8051 void GLES2DecoderImpl::DoVertexAttribI4i(
8052 GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
8053 GLint v[4] = { v0, v1, v2, v3 };
8054 if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
8055 glVertexAttribI4i(index, v0, v1, v2, v3);
8059 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
8060 if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
8061 glVertexAttribI4iv(index, v);
8065 void GLES2DecoderImpl::DoVertexAttribI4ui(
8066 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
8067 GLuint v[4] = { v0, v1, v2, v3 };
8068 if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
8069 glVertexAttribI4ui(index, v0, v1, v2, v3);
8073 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
8074 if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
8075 glVertexAttribI4uiv(index, v);
8079 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
8080 uint32 immediate_data_size,
8081 const void* cmd_data) {
8082 if (!unsafe_es3_apis_enabled())
8083 return error::kUnknownCommand;
8084 const gles2::cmds::VertexAttribIPointer& c =
8085 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
8087 if (!state_.bound_array_buffer.get() ||
8088 state_.bound_array_buffer->IsDeleted()) {
8089 if (state_.vertex_attrib_manager.get() ==
8090 state_.default_vertex_attrib_manager.get()) {
8091 LOCAL_SET_GL_ERROR(
8092 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
8093 return error::kNoError;
8094 } else if (c.offset != 0) {
8095 LOCAL_SET_GL_ERROR(
8096 GL_INVALID_VALUE,
8097 "glVertexAttribIPointer", "client side arrays are not allowed");
8098 return error::kNoError;
8102 GLuint indx = c.indx;
8103 GLint size = c.size;
8104 GLenum type = c.type;
8105 GLsizei stride = c.stride;
8106 GLsizei offset = c.offset;
8107 const void* ptr = reinterpret_cast<const void*>(offset);
8108 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
8109 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
8110 return error::kNoError;
8112 if (!validators_->vertex_attrib_size.IsValid(size)) {
8113 LOCAL_SET_GL_ERROR(
8114 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8115 return error::kNoError;
8117 if (indx >= group_->max_vertex_attribs()) {
8118 LOCAL_SET_GL_ERROR(
8119 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
8120 return error::kNoError;
8122 if (stride < 0) {
8123 LOCAL_SET_GL_ERROR(
8124 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
8125 return error::kNoError;
8127 if (stride > 255) {
8128 LOCAL_SET_GL_ERROR(
8129 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
8130 return error::kNoError;
8132 if (offset < 0) {
8133 LOCAL_SET_GL_ERROR(
8134 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
8135 return error::kNoError;
8137 GLsizei component_size =
8138 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8139 // component_size must be a power of two to use & as optimized modulo.
8140 DCHECK(GLES2Util::IsPOT(component_size));
8141 if (offset & (component_size - 1)) {
8142 LOCAL_SET_GL_ERROR(
8143 GL_INVALID_OPERATION,
8144 "glVertexAttribIPointer", "offset not valid for type");
8145 return error::kNoError;
8147 if (stride & (component_size - 1)) {
8148 LOCAL_SET_GL_ERROR(
8149 GL_INVALID_OPERATION,
8150 "glVertexAttribIPointer", "stride not valid for type");
8151 return error::kNoError;
8153 state_.vertex_attrib_manager
8154 ->SetAttribInfo(indx,
8155 state_.bound_array_buffer.get(),
8156 size,
8157 type,
8158 GL_FALSE,
8159 stride,
8160 stride != 0 ? stride : component_size * size,
8161 offset,
8162 GL_TRUE);
8163 glVertexAttribIPointer(indx, size, type, stride, ptr);
8164 return error::kNoError;
8167 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
8168 uint32 immediate_data_size,
8169 const void* cmd_data) {
8170 const gles2::cmds::VertexAttribPointer& c =
8171 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
8173 if (!state_.bound_array_buffer.get() ||
8174 state_.bound_array_buffer->IsDeleted()) {
8175 if (state_.vertex_attrib_manager.get() ==
8176 state_.default_vertex_attrib_manager.get()) {
8177 LOCAL_SET_GL_ERROR(
8178 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
8179 return error::kNoError;
8180 } else if (c.offset != 0) {
8181 LOCAL_SET_GL_ERROR(
8182 GL_INVALID_VALUE,
8183 "glVertexAttribPointer", "client side arrays are not allowed");
8184 return error::kNoError;
8188 GLuint indx = c.indx;
8189 GLint size = c.size;
8190 GLenum type = c.type;
8191 GLboolean normalized = static_cast<GLboolean>(c.normalized);
8192 GLsizei stride = c.stride;
8193 GLsizei offset = c.offset;
8194 const void* ptr = reinterpret_cast<const void*>(offset);
8195 if (!validators_->vertex_attrib_type.IsValid(type)) {
8196 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
8197 return error::kNoError;
8199 if (!validators_->vertex_attrib_size.IsValid(size)) {
8200 LOCAL_SET_GL_ERROR(
8201 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8202 return error::kNoError;
8204 if (indx >= group_->max_vertex_attribs()) {
8205 LOCAL_SET_GL_ERROR(
8206 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
8207 return error::kNoError;
8209 if (stride < 0) {
8210 LOCAL_SET_GL_ERROR(
8211 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
8212 return error::kNoError;
8214 if (stride > 255) {
8215 LOCAL_SET_GL_ERROR(
8216 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
8217 return error::kNoError;
8219 if (offset < 0) {
8220 LOCAL_SET_GL_ERROR(
8221 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
8222 return error::kNoError;
8224 GLsizei component_size =
8225 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8226 // component_size must be a power of two to use & as optimized modulo.
8227 DCHECK(GLES2Util::IsPOT(component_size));
8228 if (offset & (component_size - 1)) {
8229 LOCAL_SET_GL_ERROR(
8230 GL_INVALID_OPERATION,
8231 "glVertexAttribPointer", "offset not valid for type");
8232 return error::kNoError;
8234 if (stride & (component_size - 1)) {
8235 LOCAL_SET_GL_ERROR(
8236 GL_INVALID_OPERATION,
8237 "glVertexAttribPointer", "stride not valid for type");
8238 return error::kNoError;
8240 state_.vertex_attrib_manager
8241 ->SetAttribInfo(indx,
8242 state_.bound_array_buffer.get(),
8243 size,
8244 type,
8245 normalized,
8246 stride,
8247 stride != 0 ? stride : component_size * size,
8248 offset,
8249 GL_FALSE);
8250 // We support GL_FIXED natively on EGL/GLES2 implementations
8251 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
8252 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
8254 return error::kNoError;
8257 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
8258 GLsizei height) {
8259 state_.viewport_x = x;
8260 state_.viewport_y = y;
8261 state_.viewport_width = std::min(width, viewport_max_width_);
8262 state_.viewport_height = std::min(height, viewport_max_height_);
8263 glViewport(x, y, width, height);
8266 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8267 uint32 immediate_data_size,
8268 const void* cmd_data) {
8269 const gles2::cmds::VertexAttribDivisorANGLE& c =
8270 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
8271 if (!features().angle_instanced_arrays) {
8272 LOCAL_SET_GL_ERROR(
8273 GL_INVALID_OPERATION,
8274 "glVertexAttribDivisorANGLE", "function not available");
8275 return error::kNoError;
8277 GLuint index = c.index;
8278 GLuint divisor = c.divisor;
8279 if (index >= group_->max_vertex_attribs()) {
8280 LOCAL_SET_GL_ERROR(
8281 GL_INVALID_VALUE,
8282 "glVertexAttribDivisorANGLE", "index out of range");
8283 return error::kNoError;
8286 state_.vertex_attrib_manager->SetDivisor(
8287 index,
8288 divisor);
8289 glVertexAttribDivisorANGLE(index, divisor);
8290 return error::kNoError;
8293 template <typename pixel_data_type>
8294 static void WriteAlphaData(
8295 void* pixels, uint32 row_count, uint32 channel_count,
8296 uint32 alpha_channel_index, uint32 unpadded_row_size,
8297 uint32 padded_row_size, pixel_data_type alpha_value) {
8298 DCHECK_GT(channel_count, 0U);
8299 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8300 uint32 unpadded_row_size_in_elements =
8301 unpadded_row_size / sizeof(pixel_data_type);
8302 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8303 uint32 padded_row_size_in_elements =
8304 padded_row_size / sizeof(pixel_data_type);
8305 pixel_data_type* dst =
8306 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8307 for (uint32 yy = 0; yy < row_count; ++yy) {
8308 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8309 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8310 *d = alpha_value;
8312 dst += padded_row_size_in_elements;
8316 void GLES2DecoderImpl::FinishReadPixels(
8317 const cmds::ReadPixels& c,
8318 GLuint buffer) {
8319 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8320 GLsizei width = c.width;
8321 GLsizei height = c.height;
8322 GLenum format = c.format;
8323 GLenum type = c.type;
8324 typedef cmds::ReadPixels::Result Result;
8325 uint32 pixels_size;
8326 Result* result = NULL;
8327 if (c.result_shm_id != 0) {
8328 result = GetSharedMemoryAs<Result*>(
8329 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8330 if (!result) {
8331 if (buffer != 0) {
8332 glDeleteBuffersARB(1, &buffer);
8334 return;
8337 GLES2Util::ComputeImageDataSizes(
8338 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8339 NULL, NULL);
8340 void* pixels = GetSharedMemoryAs<void*>(
8341 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8342 if (!pixels) {
8343 if (buffer != 0) {
8344 glDeleteBuffersARB(1, &buffer);
8346 return;
8349 if (buffer != 0) {
8350 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8351 void* data;
8352 if (features().map_buffer_range) {
8353 data = glMapBufferRange(
8354 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8355 } else {
8356 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8358 if (!data) {
8359 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8360 "Unable to map memory for readback.");
8361 return;
8363 memcpy(pixels, data, pixels_size);
8364 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8365 // have to restore the state.
8366 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8367 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8368 glDeleteBuffersARB(1, &buffer);
8371 if (result != NULL) {
8372 *result = true;
8375 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8376 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8377 if ((channels_exist & 0x0008) == 0 &&
8378 workarounds().clear_alpha_in_readpixels) {
8379 // Set the alpha to 255 because some drivers are buggy in this regard.
8380 uint32 temp_size;
8382 uint32 unpadded_row_size;
8383 uint32 padded_row_size;
8384 if (!GLES2Util::ComputeImageDataSizes(
8385 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8386 &unpadded_row_size, &padded_row_size)) {
8387 return;
8390 uint32 channel_count = 0;
8391 uint32 alpha_channel = 0;
8392 switch (format) {
8393 case GL_RGBA:
8394 case GL_BGRA_EXT:
8395 channel_count = 4;
8396 alpha_channel = 3;
8397 break;
8398 case GL_ALPHA:
8399 channel_count = 1;
8400 alpha_channel = 0;
8401 break;
8404 if (channel_count > 0) {
8405 switch (type) {
8406 case GL_UNSIGNED_BYTE:
8407 WriteAlphaData<uint8>(
8408 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8409 padded_row_size, 0xFF);
8410 break;
8411 case GL_FLOAT:
8412 WriteAlphaData<float>(
8413 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8414 padded_row_size, 1.0f);
8415 break;
8416 case GL_HALF_FLOAT:
8417 WriteAlphaData<uint16>(
8418 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8419 padded_row_size, 0x3C00);
8420 break;
8426 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8427 const void* cmd_data) {
8428 const gles2::cmds::ReadPixels& c =
8429 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8430 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8431 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8432 if (fbo_error != error::kNoError)
8433 return fbo_error;
8434 GLint x = c.x;
8435 GLint y = c.y;
8436 GLsizei width = c.width;
8437 GLsizei height = c.height;
8438 GLenum format = c.format;
8439 GLenum type = c.type;
8440 GLboolean async = static_cast<GLboolean>(c.async);
8441 if (width < 0 || height < 0) {
8442 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8443 return error::kNoError;
8445 typedef cmds::ReadPixels::Result Result;
8446 uint32 pixels_size;
8447 if (!GLES2Util::ComputeImageDataSizes(
8448 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8449 NULL, NULL)) {
8450 return error::kOutOfBounds;
8452 void* pixels = GetSharedMemoryAs<void*>(
8453 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8454 if (!pixels) {
8455 return error::kOutOfBounds;
8457 Result* result = NULL;
8458 if (c.result_shm_id != 0) {
8459 result = GetSharedMemoryAs<Result*>(
8460 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8461 if (!result) {
8462 return error::kOutOfBounds;
8466 if (!validators_->read_pixel_format.IsValid(format)) {
8467 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8468 return error::kNoError;
8470 if (!validators_->read_pixel_type.IsValid(type)) {
8471 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8472 return error::kNoError;
8475 GLenum src_internal_format = GetBoundReadFrameBufferInternalFormat();
8476 if (src_internal_format == 0) {
8477 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels",
8478 "no valid read buffer source");
8479 return error::kNoError;
8481 std::vector<GLenum> accepted_formats;
8482 std::vector<GLenum> accepted_types;
8483 switch (src_internal_format) {
8484 case GL_RGB10_A2UI:
8485 accepted_formats.push_back(GL_RGBA);
8486 accepted_types.push_back(GL_UNSIGNED_INT_2_10_10_10_REV);
8487 case GL_R8UI:
8488 case GL_R16UI:
8489 case GL_R32UI:
8490 case GL_RG8UI:
8491 case GL_RG16UI:
8492 case GL_RG32UI:
8493 // All the RGB_INTEGER formats are not renderable.
8494 case GL_RGBA8UI:
8495 case GL_RGBA16UI:
8496 case GL_RGBA32UI:
8497 accepted_formats.push_back(GL_RGBA_INTEGER);
8498 accepted_types.push_back(GL_UNSIGNED_INT);
8499 break;
8500 case GL_R8I:
8501 case GL_R16I:
8502 case GL_R32I:
8503 case GL_RG8I:
8504 case GL_RG16I:
8505 case GL_RG32I:
8506 case GL_RGBA8I:
8507 case GL_RGBA16I:
8508 case GL_RGBA32I:
8509 accepted_formats.push_back(GL_RGBA_INTEGER);
8510 accepted_types.push_back(GL_INT);
8511 break;
8512 default:
8513 accepted_formats.push_back(GL_RGBA);
8515 GLenum src_type = GetBoundReadFrameBufferTextureType();
8516 switch (src_type) {
8517 case GL_HALF_FLOAT:
8518 case GL_HALF_FLOAT_OES:
8519 case GL_FLOAT:
8520 case GL_UNSIGNED_INT_10F_11F_11F_REV:
8521 accepted_types.push_back(GL_FLOAT);
8522 break;
8523 default:
8524 accepted_types.push_back(GL_UNSIGNED_BYTE);
8525 break;
8528 break;
8530 if (!IsWebGLContext()) {
8531 accepted_formats.push_back(GL_BGRA_EXT);
8532 accepted_types.push_back(GL_UNSIGNED_BYTE);
8534 DCHECK_EQ(accepted_formats.size(), accepted_types.size());
8535 bool format_type_acceptable = false;
8536 for (size_t ii = 0; ii < accepted_formats.size(); ++ii) {
8537 if (format == accepted_formats[ii] && type == accepted_types[ii]) {
8538 format_type_acceptable = true;
8539 break;
8542 if (!format_type_acceptable) {
8543 // format and type are acceptable enums but not guaranteed to be supported
8544 // for this framebuffer. Have to ask gl if they are valid.
8545 GLint preferred_format = 0;
8546 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
8547 GLint preferred_type = 0;
8548 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
8549 if (format == static_cast<GLenum>(preferred_format) &&
8550 type == static_cast<GLenum>(preferred_type)) {
8551 format_type_acceptable = true;
8554 if (!format_type_acceptable) {
8555 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadPixels",
8556 "format and type incompatible with the current read framebuffer");
8557 return error::kNoError;
8559 if (width == 0 || height == 0) {
8560 return error::kNoError;
8563 // Get the size of the current fbo or backbuffer.
8564 gfx::Size max_size = GetBoundReadFrameBufferSize();
8566 int32 max_x;
8567 int32 max_y;
8568 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8569 LOCAL_SET_GL_ERROR(
8570 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8571 return error::kNoError;
8574 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8575 return error::kNoError;
8578 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8580 ScopedResolvedFrameBufferBinder binder(this, false, true);
8582 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8583 // The user requested an out of range area. Get the results 1 line
8584 // at a time.
8585 uint32 temp_size;
8586 uint32 unpadded_row_size;
8587 uint32 padded_row_size;
8588 if (!GLES2Util::ComputeImageDataSizes(
8589 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8590 &unpadded_row_size, &padded_row_size)) {
8591 LOCAL_SET_GL_ERROR(
8592 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8593 return error::kNoError;
8596 GLint dest_x_offset = std::max(-x, 0);
8597 uint32 dest_row_offset;
8598 if (!GLES2Util::ComputeImageDataSizes(
8599 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8600 &dest_row_offset, NULL, NULL)) {
8601 LOCAL_SET_GL_ERROR(
8602 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8603 return error::kNoError;
8606 // Copy each row into the larger dest rect.
8607 int8* dst = static_cast<int8*>(pixels);
8608 GLint read_x = std::max(0, x);
8609 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8610 GLint read_width = read_end_x - read_x;
8611 for (GLint yy = 0; yy < height; ++yy) {
8612 GLint ry = y + yy;
8614 // Clear the row.
8615 memset(dst, 0, unpadded_row_size);
8617 // If the row is in range, copy it.
8618 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8619 glReadPixels(
8620 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8622 dst += padded_row_size;
8624 } else {
8625 if (async && features().use_async_readpixels) {
8626 GLuint buffer = 0;
8627 glGenBuffersARB(1, &buffer);
8628 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8629 // For ANGLE client version 2, GL_STREAM_READ is not available.
8630 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8631 GL_STATIC_DRAW : GL_STREAM_READ;
8632 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8633 GLenum error = glGetError();
8634 if (error == GL_NO_ERROR) {
8635 glReadPixels(x, y, width, height, format, type, 0);
8636 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8637 new FenceCallback()));
8638 WaitForReadPixels(base::Bind(
8639 &GLES2DecoderImpl::FinishReadPixels,
8640 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8641 <GLES2DecoderImpl>(this),
8642 c, buffer));
8643 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8644 return error::kNoError;
8645 } else {
8646 // On error, unbind pack buffer and fall through to sync readpixels
8647 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8648 glDeleteBuffersARB(1, &buffer);
8651 glReadPixels(x, y, width, height, format, type, pixels);
8653 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8654 if (error == GL_NO_ERROR) {
8655 if (result != NULL) {
8656 *result = true;
8658 FinishReadPixels(c, 0);
8661 return error::kNoError;
8664 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8665 const void* cmd_data) {
8666 const gles2::cmds::PixelStorei& c =
8667 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8668 GLenum pname = c.pname;
8669 GLenum param = c.param;
8670 if (!validators_->pixel_store.IsValid(pname)) {
8671 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8672 return error::kNoError;
8674 switch (pname) {
8675 case GL_PACK_ALIGNMENT:
8676 case GL_UNPACK_ALIGNMENT:
8677 if (!validators_->pixel_store_alignment.IsValid(param)) {
8678 LOCAL_SET_GL_ERROR(
8679 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8680 return error::kNoError;
8682 break;
8683 default:
8684 break;
8686 glPixelStorei(pname, param);
8687 switch (pname) {
8688 case GL_PACK_ALIGNMENT:
8689 state_.pack_alignment = param;
8690 break;
8691 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8692 state_.pack_reverse_row_order = (param != 0);
8693 break;
8694 case GL_UNPACK_ALIGNMENT:
8695 state_.unpack_alignment = param;
8696 break;
8697 default:
8698 // Validation should have prevented us from getting here.
8699 NOTREACHED();
8700 break;
8702 return error::kNoError;
8705 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8706 uint32 immediate_data_size,
8707 const void* cmd_data) {
8708 const gles2::cmds::PostSubBufferCHROMIUM& c =
8709 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8710 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8712 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8714 if (!supports_post_sub_buffer_) {
8715 LOCAL_SET_GL_ERROR(
8716 GL_INVALID_OPERATION,
8717 "glPostSubBufferCHROMIUM", "command not supported by surface");
8718 return error::kNoError;
8720 bool is_tracing;
8721 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8722 &is_tracing);
8723 if (is_tracing) {
8724 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8725 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8726 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8727 is_offscreen ? offscreen_size_ : surface_->GetSize());
8729 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height) !=
8730 gfx::SwapResult::SWAP_FAILED) {
8731 return error::kNoError;
8732 } else {
8733 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8734 return error::kLostContext;
8738 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8739 uint32 immediate_data_size,
8740 const void* cmd_data) {
8741 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8742 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8743 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8744 if (!ref) {
8745 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8746 "glScheduleOverlayPlaneCHROMIUM",
8747 "unknown texture");
8748 return error::kNoError;
8750 gfx::GLImage* image =
8751 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8752 if (!image) {
8753 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8754 "glScheduleOverlayPlaneCHROMIUM",
8755 "unsupported texture format");
8756 return error::kNoError;
8758 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8759 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8760 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8761 "glScheduleOverlayPlaneCHROMIUM",
8762 "invalid transform enum");
8763 return error::kNoError;
8765 if (!surface_->ScheduleOverlayPlane(
8766 c.plane_z_order,
8767 transform,
8768 image,
8769 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8770 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8771 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8772 "glScheduleOverlayPlaneCHROMIUM",
8773 "failed to schedule overlay");
8775 return error::kNoError;
8778 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8779 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8780 const std::string& name_str) {
8781 if (!StringIsValidForGLES(name_str.c_str())) {
8782 LOCAL_SET_GL_ERROR(
8783 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8784 return error::kNoError;
8786 Program* program = GetProgramInfoNotShader(
8787 client_id, "glGetAttribLocation");
8788 if (!program) {
8789 return error::kNoError;
8791 if (!program->IsValid()) {
8792 LOCAL_SET_GL_ERROR(
8793 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8794 return error::kNoError;
8796 GLint* location = GetSharedMemoryAs<GLint*>(
8797 location_shm_id, location_shm_offset, sizeof(GLint));
8798 if (!location) {
8799 return error::kOutOfBounds;
8801 // Require the client to init this incase the context is lost and we are no
8802 // longer executing commands.
8803 if (*location != -1) {
8804 return error::kGenericError;
8806 *location = program->GetAttribLocation(name_str);
8807 return error::kNoError;
8810 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8811 uint32 immediate_data_size,
8812 const void* cmd_data) {
8813 const gles2::cmds::GetAttribLocation& c =
8814 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8815 Bucket* bucket = GetBucket(c.name_bucket_id);
8816 if (!bucket) {
8817 return error::kInvalidArguments;
8819 std::string name_str;
8820 if (!bucket->GetAsString(&name_str)) {
8821 return error::kInvalidArguments;
8823 return GetAttribLocationHelper(
8824 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8827 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8828 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8829 const std::string& name_str) {
8830 if (!StringIsValidForGLES(name_str.c_str())) {
8831 LOCAL_SET_GL_ERROR(
8832 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8833 return error::kNoError;
8835 Program* program = GetProgramInfoNotShader(
8836 client_id, "glGetUniformLocation");
8837 if (!program) {
8838 return error::kNoError;
8840 if (!program->IsValid()) {
8841 LOCAL_SET_GL_ERROR(
8842 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8843 return error::kNoError;
8845 GLint* location = GetSharedMemoryAs<GLint*>(
8846 location_shm_id, location_shm_offset, sizeof(GLint));
8847 if (!location) {
8848 return error::kOutOfBounds;
8850 // Require the client to init this incase the context is lost an we are no
8851 // longer executing commands.
8852 if (*location != -1) {
8853 return error::kGenericError;
8855 *location = program->GetUniformFakeLocation(name_str);
8856 return error::kNoError;
8859 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8860 uint32 immediate_data_size,
8861 const void* cmd_data) {
8862 const gles2::cmds::GetUniformLocation& c =
8863 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8864 Bucket* bucket = GetBucket(c.name_bucket_id);
8865 if (!bucket) {
8866 return error::kInvalidArguments;
8868 std::string name_str;
8869 if (!bucket->GetAsString(&name_str)) {
8870 return error::kInvalidArguments;
8872 return GetUniformLocationHelper(
8873 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8876 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8877 uint32 immediate_data_size,
8878 const void* cmd_data) {
8879 if (!unsafe_es3_apis_enabled())
8880 return error::kUnknownCommand;
8881 const gles2::cmds::GetUniformIndices& c =
8882 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8883 Bucket* bucket = GetBucket(c.names_bucket_id);
8884 if (!bucket) {
8885 return error::kInvalidArguments;
8887 GLsizei count = 0;
8888 std::vector<char*> names;
8889 std::vector<GLint> len;
8890 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8891 return error::kInvalidArguments;
8893 typedef cmds::GetUniformIndices::Result Result;
8894 Result* result = GetSharedMemoryAs<Result*>(
8895 c.indices_shm_id, c.indices_shm_offset,
8896 Result::ComputeSize(static_cast<size_t>(count)));
8897 GLuint* indices = result ? result->GetData() : NULL;
8898 if (indices == NULL) {
8899 return error::kOutOfBounds;
8901 // Check that the client initialized the result.
8902 if (result->size != 0) {
8903 return error::kInvalidArguments;
8905 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8906 if (!program) {
8907 return error::kNoError;
8909 GLuint service_id = program->service_id();
8910 GLint link_status = GL_FALSE;
8911 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8912 if (link_status != GL_TRUE) {
8913 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8914 "glGetUniformIndices", "program not linked");
8915 return error::kNoError;
8917 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8918 glGetUniformIndices(service_id, count, &names[0], indices);
8919 GLenum error = glGetError();
8920 if (error == GL_NO_ERROR) {
8921 result->SetNumResults(count);
8922 } else {
8923 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8925 return error::kNoError;
8928 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8929 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8930 const std::string& name_str) {
8931 GLint* location = GetSharedMemoryAs<GLint*>(
8932 location_shm_id, location_shm_offset, sizeof(GLint));
8933 if (!location) {
8934 return error::kOutOfBounds;
8936 // Require the client to init this incase the context is lost and we are no
8937 // longer executing commands.
8938 if (*location != -1) {
8939 return error::kGenericError;
8941 Program* program = GetProgramInfoNotShader(
8942 client_id, "glGetFragDataLocation");
8943 if (!program) {
8944 return error::kNoError;
8946 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8947 return error::kNoError;
8950 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8951 uint32 immediate_data_size,
8952 const void* cmd_data) {
8953 if (!unsafe_es3_apis_enabled())
8954 return error::kUnknownCommand;
8955 const gles2::cmds::GetFragDataLocation& c =
8956 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8957 Bucket* bucket = GetBucket(c.name_bucket_id);
8958 if (!bucket) {
8959 return error::kInvalidArguments;
8961 std::string name_str;
8962 if (!bucket->GetAsString(&name_str)) {
8963 return error::kInvalidArguments;
8965 return GetFragDataLocationHelper(
8966 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8969 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8970 uint32 immediate_data_size, const void* cmd_data) {
8971 if (!unsafe_es3_apis_enabled())
8972 return error::kUnknownCommand;
8973 const gles2::cmds::GetUniformBlockIndex& c =
8974 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8975 Bucket* bucket = GetBucket(c.name_bucket_id);
8976 if (!bucket) {
8977 return error::kInvalidArguments;
8979 std::string name_str;
8980 if (!bucket->GetAsString(&name_str)) {
8981 return error::kInvalidArguments;
8983 GLuint* index = GetSharedMemoryAs<GLuint*>(
8984 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8985 if (!index) {
8986 return error::kOutOfBounds;
8988 // Require the client to init this in case the context is lost and we are no
8989 // longer executing commands.
8990 if (*index != GL_INVALID_INDEX) {
8991 return error::kGenericError;
8993 Program* program = GetProgramInfoNotShader(
8994 c.program, "glGetUniformBlockIndex");
8995 if (!program) {
8996 return error::kNoError;
8998 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8999 return error::kNoError;
9002 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
9003 const void* cmd_data) {
9004 const gles2::cmds::GetString& c =
9005 *static_cast<const gles2::cmds::GetString*>(cmd_data);
9006 GLenum name = static_cast<GLenum>(c.name);
9007 if (!validators_->string_type.IsValid(name)) {
9008 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
9009 return error::kNoError;
9012 const char* str = nullptr;
9013 std::string extensions;
9014 switch (name) {
9015 case GL_VERSION:
9016 if (unsafe_es3_apis_enabled())
9017 str = "OpenGL ES 3.0 Chromium";
9018 else
9019 str = "OpenGL ES 2.0 Chromium";
9020 break;
9021 case GL_SHADING_LANGUAGE_VERSION:
9022 if (unsafe_es3_apis_enabled())
9023 str = "OpenGL ES GLSL ES 3.0 Chromium";
9024 else
9025 str = "OpenGL ES GLSL ES 1.0 Chromium";
9026 break;
9027 case GL_RENDERER:
9028 case GL_VENDOR:
9029 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9030 // They are used by WEBGL_debug_renderer_info.
9031 if (!IsWebGLContext())
9032 str = "Chromium";
9033 else
9034 str = reinterpret_cast<const char*>(glGetString(name));
9035 break;
9036 case GL_EXTENSIONS:
9038 // For WebGL contexts, strip out the OES derivatives and
9039 // EXT frag depth extensions if they have not been enabled.
9040 if (IsWebGLContext()) {
9041 extensions = feature_info_->extensions();
9042 if (!derivatives_explicitly_enabled_) {
9043 size_t offset = extensions.find(kOESDerivativeExtension);
9044 if (std::string::npos != offset) {
9045 extensions.replace(offset, arraysize(kOESDerivativeExtension),
9046 std::string());
9049 if (!frag_depth_explicitly_enabled_) {
9050 size_t offset = extensions.find(kEXTFragDepthExtension);
9051 if (std::string::npos != offset) {
9052 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
9053 std::string());
9056 if (!draw_buffers_explicitly_enabled_) {
9057 size_t offset = extensions.find(kEXTDrawBuffersExtension);
9058 if (std::string::npos != offset) {
9059 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
9060 std::string());
9063 if (!shader_texture_lod_explicitly_enabled_) {
9064 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
9065 if (std::string::npos != offset) {
9066 extensions.replace(offset,
9067 arraysize(kEXTShaderTextureLodExtension),
9068 std::string());
9071 } else {
9072 extensions = feature_info_->extensions().c_str();
9074 if (supports_post_sub_buffer_)
9075 extensions += " GL_CHROMIUM_post_sub_buffer";
9076 str = extensions.c_str();
9078 break;
9079 default:
9080 str = reinterpret_cast<const char*>(glGetString(name));
9081 break;
9083 Bucket* bucket = CreateBucket(c.bucket_id);
9084 bucket->SetFromString(str);
9085 return error::kNoError;
9088 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
9089 const void* cmd_data) {
9090 const gles2::cmds::BufferData& c =
9091 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
9092 GLenum target = static_cast<GLenum>(c.target);
9093 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
9094 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9095 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9096 GLenum usage = static_cast<GLenum>(c.usage);
9097 const void* data = NULL;
9098 if (data_shm_id != 0 || data_shm_offset != 0) {
9099 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
9100 if (!data) {
9101 return error::kOutOfBounds;
9104 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
9105 return error::kNoError;
9108 void GLES2DecoderImpl::DoBufferSubData(
9109 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
9110 // Just delegate it. Some validation is actually done before this.
9111 buffer_manager()->ValidateAndDoBufferSubData(
9112 &state_, target, offset, size, data);
9115 bool GLES2DecoderImpl::ClearLevel(Texture* texture,
9116 unsigned target,
9117 int level,
9118 unsigned format,
9119 unsigned type,
9120 int xoffset,
9121 int yoffset,
9122 int width,
9123 int height) {
9124 uint32 channels = GLES2Util::GetChannelsForFormat(format);
9125 if ((feature_info_->feature_flags().angle_depth_texture ||
9126 feature_info_->IsES3Enabled())
9127 && (channels & GLES2Util::kDepth) != 0) {
9128 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9129 // on depth formats.
9130 GLuint fb = 0;
9131 glGenFramebuffersEXT(1, &fb);
9132 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
9134 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
9135 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
9136 GL_DEPTH_ATTACHMENT;
9138 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
9139 texture->service_id(), level);
9140 // ANGLE promises a depth only attachment ok.
9141 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
9142 GL_FRAMEBUFFER_COMPLETE) {
9143 return false;
9145 glClearStencil(0);
9146 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
9147 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
9148 glClearDepth(1.0f);
9149 state_.SetDeviceDepthMask(GL_TRUE);
9150 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
9151 glScissor(xoffset, yoffset, width, height);
9152 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
9154 RestoreClearState();
9156 glDeleteFramebuffersEXT(1, &fb);
9157 Framebuffer* framebuffer =
9158 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
9159 GLuint fb_service_id =
9160 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
9161 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
9162 return true;
9165 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
9167 uint32 size;
9168 uint32 padded_row_size;
9169 if (!GLES2Util::ComputeImageDataSizes(
9170 width, height, 1, format, type, state_.unpack_alignment, &size,
9171 NULL, &padded_row_size)) {
9172 return false;
9175 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
9177 int tile_height;
9179 if (size > kMaxZeroSize) {
9180 if (kMaxZeroSize < padded_row_size) {
9181 // That'd be an awfully large texture.
9182 return false;
9184 // We should never have a large total size with a zero row size.
9185 DCHECK_GT(padded_row_size, 0U);
9186 tile_height = kMaxZeroSize / padded_row_size;
9187 if (!GLES2Util::ComputeImageDataSizes(
9188 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
9189 NULL, NULL)) {
9190 return false;
9192 } else {
9193 tile_height = height;
9196 // Assumes the size has already been checked.
9197 scoped_ptr<char[]> zero(new char[size]);
9198 memset(zero.get(), 0, size);
9199 glBindTexture(texture->target(), texture->service_id());
9201 GLint y = 0;
9202 while (y < height) {
9203 GLint h = y + tile_height > height ? height - y : tile_height;
9204 glTexSubImage2D(target, level, xoffset, yoffset + y, width, h, format, type,
9205 zero.get());
9206 y += tile_height;
9208 TextureRef* bound_texture =
9209 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
9210 glBindTexture(texture->target(),
9211 bound_texture ? bound_texture->service_id() : 0);
9212 return true;
9215 namespace {
9217 const int kS3TCBlockWidth = 4;
9218 const int kS3TCBlockHeight = 4;
9219 const int kS3TCDXT1BlockSize = 8;
9220 const int kS3TCDXT3AndDXT5BlockSize = 16;
9221 const int kEACAndETC2BlockSize = 4;
9223 bool IsValidDXTSize(GLint level, GLsizei size) {
9224 return (size == 1) ||
9225 (size == 2) || !(size % kS3TCBlockWidth);
9228 bool IsValidPVRTCSize(GLint level, GLsizei size) {
9229 return GLES2Util::IsPOT(size);
9232 } // anonymous namespace.
9234 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9235 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9236 GLenum format, GLsizei* size_in_bytes) {
9237 base::CheckedNumeric<GLsizei> bytes_required(0);
9239 switch (format) {
9240 case GL_ATC_RGB_AMD:
9241 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9242 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9243 case GL_ETC1_RGB8_OES:
9244 bytes_required =
9245 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9246 bytes_required *=
9247 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9248 bytes_required *= kS3TCDXT1BlockSize;
9249 break;
9250 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9251 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9252 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9253 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9254 bytes_required =
9255 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9256 bytes_required *=
9257 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9258 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
9259 break;
9260 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9261 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9262 bytes_required = std::max(width, 8);
9263 bytes_required *= std::max(height, 8);
9264 bytes_required *= 4;
9265 bytes_required += 7;
9266 bytes_required /= 8;
9267 break;
9268 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9269 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9270 bytes_required = std::max(width, 16);
9271 bytes_required *= std::max(height, 8);
9272 bytes_required *= 2;
9273 bytes_required += 7;
9274 bytes_required /= 8;
9275 break;
9277 // ES3 formats.
9278 case GL_COMPRESSED_R11_EAC:
9279 case GL_COMPRESSED_SIGNED_R11_EAC:
9280 case GL_COMPRESSED_RGB8_ETC2:
9281 case GL_COMPRESSED_SRGB8_ETC2:
9282 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9283 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9284 bytes_required =
9285 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9286 bytes_required *=
9287 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9288 bytes_required *= 8;
9289 bytes_required *= depth;
9290 break;
9291 case GL_COMPRESSED_RG11_EAC:
9292 case GL_COMPRESSED_SIGNED_RG11_EAC:
9293 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9294 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9295 bytes_required =
9296 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9297 bytes_required *=
9298 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9299 bytes_required *= 16;
9300 bytes_required *= depth;
9301 break;
9302 default:
9303 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
9304 return false;
9307 if (!bytes_required.IsValid()) {
9308 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid size");
9309 return false;
9312 *size_in_bytes = bytes_required.ValueOrDefault(0);
9313 return true;
9316 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9317 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9318 GLenum format, GLsizei size) {
9319 GLsizei bytes_required = 0;
9320 if (!GetCompressedTexSizeInBytes(
9321 function_name, width, height, depth, format, &bytes_required)) {
9322 return false;
9325 if (size != bytes_required) {
9326 LOCAL_SET_GL_ERROR(
9327 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
9328 return false;
9331 return true;
9334 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9335 const char* function_name, GLenum target, GLint level,
9336 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
9337 switch (format) {
9338 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9339 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9340 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9341 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9342 DCHECK_EQ(1, depth); // 2D formats.
9343 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
9344 LOCAL_SET_GL_ERROR(
9345 GL_INVALID_OPERATION, function_name,
9346 "width or height invalid for level");
9347 return false;
9349 return true;
9350 case GL_ATC_RGB_AMD:
9351 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9352 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9353 case GL_ETC1_RGB8_OES:
9354 DCHECK_EQ(1, depth); // 2D formats.
9355 if (width <= 0 || height <= 0) {
9356 LOCAL_SET_GL_ERROR(
9357 GL_INVALID_OPERATION, function_name,
9358 "width or height invalid for level");
9359 return false;
9361 return true;
9362 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9363 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9364 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9365 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9366 DCHECK_EQ(1, depth); // 2D formats.
9367 if (!IsValidPVRTCSize(level, width) ||
9368 !IsValidPVRTCSize(level, height)) {
9369 LOCAL_SET_GL_ERROR(
9370 GL_INVALID_OPERATION, function_name,
9371 "width or height invalid for level");
9372 return false;
9374 return true;
9376 // ES3 formats.
9377 case GL_COMPRESSED_R11_EAC:
9378 case GL_COMPRESSED_SIGNED_R11_EAC:
9379 case GL_COMPRESSED_RG11_EAC:
9380 case GL_COMPRESSED_SIGNED_RG11_EAC:
9381 case GL_COMPRESSED_RGB8_ETC2:
9382 case GL_COMPRESSED_SRGB8_ETC2:
9383 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9384 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9385 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9386 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9387 if (width <= 0 || height <= 0 || depth <= 0) {
9388 LOCAL_SET_GL_ERROR(
9389 GL_INVALID_OPERATION, function_name,
9390 "width, height, or depth invalid");
9391 return false;
9393 if (target == GL_TEXTURE_3D) {
9394 LOCAL_SET_GL_ERROR(
9395 GL_INVALID_OPERATION, function_name,
9396 "target invalid for format");
9397 return false;
9399 return true;
9400 default:
9401 return false;
9405 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9406 const char* function_name,
9407 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9408 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9409 Texture* texture) {
9410 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9411 LOCAL_SET_GL_ERROR(
9412 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9413 return false;
9416 switch (format) {
9417 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9418 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9419 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9420 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9421 const int kBlockWidth = 4;
9422 const int kBlockHeight = 4;
9423 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9424 LOCAL_SET_GL_ERROR(
9425 GL_INVALID_OPERATION, function_name,
9426 "xoffset or yoffset not multiple of 4");
9427 return false;
9429 GLsizei tex_width = 0;
9430 GLsizei tex_height = 0;
9431 if (!texture->GetLevelSize(target, level,
9432 &tex_width, &tex_height, nullptr) ||
9433 width - xoffset > tex_width ||
9434 height - yoffset > tex_height) {
9435 LOCAL_SET_GL_ERROR(
9436 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9437 return false;
9439 return ValidateCompressedTexDimensions(
9440 function_name, target, level, width, height, 1, format);
9442 case GL_ATC_RGB_AMD:
9443 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9444 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
9445 LOCAL_SET_GL_ERROR(
9446 GL_INVALID_OPERATION, function_name,
9447 "not supported for ATC textures");
9448 return false;
9450 case GL_ETC1_RGB8_OES: {
9451 LOCAL_SET_GL_ERROR(
9452 GL_INVALID_OPERATION, function_name,
9453 "not supported for ECT1_RGB8_OES textures");
9454 return false;
9456 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9457 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9458 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9459 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
9460 if ((xoffset != 0) || (yoffset != 0)) {
9461 LOCAL_SET_GL_ERROR(
9462 GL_INVALID_OPERATION, function_name,
9463 "xoffset and yoffset must be zero");
9464 return false;
9466 GLsizei tex_width = 0;
9467 GLsizei tex_height = 0;
9468 if (!texture->GetLevelSize(target, level,
9469 &tex_width, &tex_height, nullptr) ||
9470 width != tex_width ||
9471 height != tex_height) {
9472 LOCAL_SET_GL_ERROR(
9473 GL_INVALID_OPERATION, function_name,
9474 "dimensions must match existing texture level dimensions");
9475 return false;
9477 return ValidateCompressedTexDimensions(
9478 function_name, target, level, width, height, 1, format);
9481 // ES3 formats
9482 case GL_COMPRESSED_R11_EAC:
9483 case GL_COMPRESSED_SIGNED_R11_EAC:
9484 case GL_COMPRESSED_RG11_EAC:
9485 case GL_COMPRESSED_SIGNED_RG11_EAC:
9486 case GL_COMPRESSED_RGB8_ETC2:
9487 case GL_COMPRESSED_SRGB8_ETC2:
9488 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9489 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9490 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9491 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9493 const int kBlockSize = 4;
9494 GLsizei tex_width, tex_height;
9495 if (target == GL_TEXTURE_3D ||
9496 !texture->GetLevelSize(target, level,
9497 &tex_width, &tex_height, nullptr) ||
9498 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
9499 ((width % kBlockSize) && xoffset + width != tex_width) ||
9500 ((height % kBlockSize) && yoffset + height != tex_height)) {
9501 LOCAL_SET_GL_ERROR(
9502 GL_INVALID_OPERATION, function_name,
9503 "dimensions must match existing texture level dimensions");
9504 return false;
9506 return true;
9508 default:
9509 return false;
9513 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
9514 GLenum target,
9515 GLint level,
9516 GLenum internal_format,
9517 GLsizei width,
9518 GLsizei height,
9519 GLint border,
9520 GLsizei image_size,
9521 const void* data) {
9522 if (!validators_->texture_target.IsValid(target)) {
9523 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9524 "glCompressedTexImage2D", target, "target");
9525 return error::kNoError;
9527 if (!validators_->compressed_texture_format.IsValid(
9528 internal_format)) {
9529 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9530 "glCompressedTexImage2D", internal_format, "internal_format");
9531 return error::kNoError;
9533 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9534 border != 0) {
9535 LOCAL_SET_GL_ERROR(
9536 GL_INVALID_VALUE,
9537 "glCompressedTexImage2D", "dimensions out of range");
9538 return error::kNoError;
9540 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9541 &state_, target);
9542 if (!texture_ref) {
9543 LOCAL_SET_GL_ERROR(
9544 GL_INVALID_VALUE,
9545 "glCompressedTexImage2D", "unknown texture target");
9546 return error::kNoError;
9548 Texture* texture = texture_ref->texture();
9549 if (texture->IsImmutable()) {
9550 LOCAL_SET_GL_ERROR(
9551 GL_INVALID_OPERATION,
9552 "glCompressedTexImage2D", "texture is immutable");
9553 return error::kNoError;
9556 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
9557 width, height, 1, internal_format) ||
9558 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
9559 1, internal_format, image_size)) {
9560 return error::kNoError;
9563 if (!EnsureGPUMemoryAvailable(image_size)) {
9564 LOCAL_SET_GL_ERROR(
9565 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
9566 return error::kNoError;
9569 if (texture->IsAttachedToFramebuffer()) {
9570 framebuffer_state_.clear_state_dirty = true;
9573 scoped_ptr<int8[]> zero;
9574 if (!data) {
9575 zero.reset(new int8[image_size]);
9576 memset(zero.get(), 0, image_size);
9577 data = zero.get();
9579 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9580 glCompressedTexImage2D(
9581 target, level, internal_format, width, height, border, image_size, data);
9582 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9583 if (error == GL_NO_ERROR) {
9584 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9585 width, height, 1, border, 0, 0,
9586 gfx::Rect(width, height));
9589 // This may be a slow command. Exit command processing to allow for
9590 // context preemption and GPU watchdog checks.
9591 ExitCommandProcessingEarly();
9592 return error::kNoError;
9595 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
9596 uint32 immediate_data_size,
9597 const void* cmd_data) {
9598 const gles2::cmds::CompressedTexImage2D& c =
9599 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
9600 GLenum target = static_cast<GLenum>(c.target);
9601 GLint level = static_cast<GLint>(c.level);
9602 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9603 GLsizei width = static_cast<GLsizei>(c.width);
9604 GLsizei height = static_cast<GLsizei>(c.height);
9605 GLint border = static_cast<GLint>(c.border);
9606 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9607 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9608 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9609 const void* data = NULL;
9610 if (data_shm_id != 0 || data_shm_offset != 0) {
9611 data = GetSharedMemoryAs<const void*>(
9612 data_shm_id, data_shm_offset, image_size);
9613 if (!data) {
9614 return error::kOutOfBounds;
9617 return DoCompressedTexImage2D(
9618 target, level, internal_format, width, height, border, image_size, data);
9621 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9622 uint32 immediate_data_size,
9623 const void* cmd_data) {
9624 const gles2::cmds::CompressedTexImage2DBucket& c =
9625 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
9626 GLenum target = static_cast<GLenum>(c.target);
9627 GLint level = static_cast<GLint>(c.level);
9628 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9629 GLsizei width = static_cast<GLsizei>(c.width);
9630 GLsizei height = static_cast<GLsizei>(c.height);
9631 GLint border = static_cast<GLint>(c.border);
9632 Bucket* bucket = GetBucket(c.bucket_id);
9633 if (!bucket) {
9634 return error::kInvalidArguments;
9636 uint32 data_size = bucket->size();
9637 GLsizei imageSize = data_size;
9638 const void* data = bucket->GetData(0, data_size);
9639 if (!data) {
9640 return error::kInvalidArguments;
9642 return DoCompressedTexImage2D(
9643 target, level, internal_format, width, height, border,
9644 imageSize, data);
9647 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9648 uint32 immediate_data_size,
9649 const void* cmd_data) {
9650 const gles2::cmds::CompressedTexSubImage2DBucket& c =
9651 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
9652 GLenum target = static_cast<GLenum>(c.target);
9653 GLint level = static_cast<GLint>(c.level);
9654 GLint xoffset = static_cast<GLint>(c.xoffset);
9655 GLint yoffset = static_cast<GLint>(c.yoffset);
9656 GLsizei width = static_cast<GLsizei>(c.width);
9657 GLsizei height = static_cast<GLsizei>(c.height);
9658 GLenum format = static_cast<GLenum>(c.format);
9659 Bucket* bucket = GetBucket(c.bucket_id);
9660 if (!bucket) {
9661 return error::kInvalidArguments;
9663 uint32 data_size = bucket->size();
9664 GLsizei imageSize = data_size;
9665 const void* data = bucket->GetData(0, data_size);
9666 if (!data) {
9667 return error::kInvalidArguments;
9669 if (!validators_->texture_target.IsValid(target)) {
9670 LOCAL_SET_GL_ERROR(
9671 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9672 return error::kNoError;
9674 if (!validators_->compressed_texture_format.IsValid(format)) {
9675 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9676 "glCompressedTexSubImage2D", format, "format");
9677 return error::kNoError;
9679 if (width < 0) {
9680 LOCAL_SET_GL_ERROR(
9681 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9682 return error::kNoError;
9684 if (height < 0) {
9685 LOCAL_SET_GL_ERROR(
9686 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9687 return error::kNoError;
9689 if (imageSize < 0) {
9690 LOCAL_SET_GL_ERROR(
9691 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9692 return error::kNoError;
9694 DoCompressedTexSubImage2D(
9695 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9696 return error::kNoError;
9699 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
9700 GLenum target,
9701 GLint level,
9702 GLenum internal_format,
9703 GLsizei width,
9704 GLsizei height,
9705 GLsizei depth,
9706 GLint border,
9707 GLsizei image_size,
9708 const void* data) {
9709 if (!validators_->texture_3_d_target.IsValid(target)) {
9710 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9711 "glCompressedTexImage3D", target, "target");
9712 return error::kNoError;
9714 if (!validators_->compressed_texture_format.IsValid(
9715 internal_format)) {
9716 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9717 "glCompressedTexImage3D", internal_format, "internal_format");
9718 return error::kNoError;
9720 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
9721 border != 0) {
9722 LOCAL_SET_GL_ERROR(
9723 GL_INVALID_VALUE,
9724 "glCompressedTexImage3D", "dimensions out of range");
9725 return error::kNoError;
9727 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9728 &state_, target);
9729 if (!texture_ref) {
9730 LOCAL_SET_GL_ERROR(
9731 GL_INVALID_VALUE,
9732 "glCompressedTexImage3D", "unknown texture target");
9733 return error::kNoError;
9735 Texture* texture = texture_ref->texture();
9736 if (texture->IsImmutable()) {
9737 LOCAL_SET_GL_ERROR(
9738 GL_INVALID_OPERATION,
9739 "glCompressedTexImage3D", "texture is immutable");
9740 return error::kNoError;
9743 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
9744 width, height, depth, internal_format) ||
9745 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
9746 depth, internal_format, image_size)) {
9747 return error::kNoError;
9750 if (!EnsureGPUMemoryAvailable(image_size)) {
9751 LOCAL_SET_GL_ERROR(
9752 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
9753 return error::kNoError;
9756 if (texture->IsAttachedToFramebuffer()) {
9757 framebuffer_state_.clear_state_dirty = true;
9760 scoped_ptr<int8[]> zero;
9761 if (!data) {
9762 zero.reset(new int8[image_size]);
9763 memset(zero.get(), 0, image_size);
9764 data = zero.get();
9766 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9767 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
9768 border, image_size, data);
9769 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9770 if (error == GL_NO_ERROR) {
9771 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9772 width, height, depth, border, 0, 0,
9773 gfx::Rect(width, height));
9776 // This may be a slow command. Exit command processing to allow for
9777 // context preemption and GPU watchdog checks.
9778 ExitCommandProcessingEarly();
9779 return error::kNoError;
9782 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
9783 uint32 immediate_data_size, const void* cmd_data) {
9784 if (!unsafe_es3_apis_enabled())
9785 return error::kUnknownCommand;
9787 const gles2::cmds::CompressedTexImage3D& c =
9788 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
9789 GLenum target = static_cast<GLenum>(c.target);
9790 GLint level = static_cast<GLint>(c.level);
9791 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9792 GLsizei width = static_cast<GLsizei>(c.width);
9793 GLsizei height = static_cast<GLsizei>(c.height);
9794 GLsizei depth = static_cast<GLsizei>(c.depth);
9795 GLint border = static_cast<GLint>(c.border);
9796 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9797 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9798 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9799 const void* data = NULL;
9800 if (data_shm_id != 0 || data_shm_offset != 0) {
9801 data = GetSharedMemoryAs<const void*>(
9802 data_shm_id, data_shm_offset, image_size);
9803 if (!data) {
9804 return error::kOutOfBounds;
9807 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9808 depth, border, image_size, data);
9811 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9812 uint32 immediate_data_size, const void* cmd_data) {
9813 if (!unsafe_es3_apis_enabled())
9814 return error::kUnknownCommand;
9816 const gles2::cmds::CompressedTexImage3DBucket& c =
9817 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
9818 GLenum target = static_cast<GLenum>(c.target);
9819 GLint level = static_cast<GLint>(c.level);
9820 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9821 GLsizei width = static_cast<GLsizei>(c.width);
9822 GLsizei height = static_cast<GLsizei>(c.height);
9823 GLsizei depth = static_cast<GLsizei>(c.depth);
9824 GLint border = static_cast<GLint>(c.border);
9825 Bucket* bucket = GetBucket(c.bucket_id);
9826 if (!bucket) {
9827 return error::kInvalidArguments;
9829 uint32 data_size = bucket->size();
9830 GLsizei imageSize = data_size;
9831 const void* data = bucket->GetData(0, data_size);
9832 if (!data) {
9833 return error::kInvalidArguments;
9835 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9836 depth, border, imageSize, data);
9839 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9840 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9841 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9842 GLsizei image_size, const void* data) {
9843 if (!validators_->texture_3_d_target.IsValid(target)) {
9844 LOCAL_SET_GL_ERROR(
9845 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
9846 return;
9848 if (!validators_->compressed_texture_format.IsValid(format)) {
9849 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9850 "glCompressedTexSubImage3D", format, "format");
9851 return;
9853 if (width < 0 || height < 0 || depth < 0) {
9854 LOCAL_SET_GL_ERROR(
9855 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
9856 return;
9858 if (image_size < 0) {
9859 LOCAL_SET_GL_ERROR(
9860 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
9861 return;
9863 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9864 &state_, target);
9865 if (!texture_ref) {
9866 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9867 "unknown texture for target");
9868 return;
9870 Texture* texture = texture_ref->texture();
9871 GLenum type = 0, internal_format = 0;
9872 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9873 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9874 "level does not exist");
9875 return;
9877 if (internal_format != format) {
9878 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9879 "format does not match internal format");
9880 return;
9882 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
9883 width, height, depth, type)) {
9884 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
9885 "bad dimensions");
9886 return;
9888 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9889 width, height, depth, format,
9890 image_size) ||
9891 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9892 target, level, xoffset, yoffset,
9893 zoffset, width, height, depth,
9894 format, texture)) {
9895 return;
9898 // Note: There is no need to deal with texture cleared tracking here
9899 // because the validation above means you can only get here if the level
9900 // is already a matching compressed format and in that case
9901 // CompressedTexImage3D already cleared the texture.
9902 glCompressedTexSubImage3D(
9903 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9904 image_size, data);
9906 // This may be a slow command. Exit command processing to allow for
9907 // context preemption and GPU watchdog checks.
9908 ExitCommandProcessingEarly();
9911 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9912 uint32 immediate_data_size, const void* cmd_data) {
9913 if (!unsafe_es3_apis_enabled())
9914 return error::kUnknownCommand;
9915 const gles2::cmds::CompressedTexSubImage3DBucket& c =
9916 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
9917 GLenum target = static_cast<GLenum>(c.target);
9918 GLint level = static_cast<GLint>(c.level);
9919 GLint xoffset = static_cast<GLint>(c.xoffset);
9920 GLint yoffset = static_cast<GLint>(c.yoffset);
9921 GLint zoffset = static_cast<GLint>(c.zoffset);
9922 GLsizei width = static_cast<GLsizei>(c.width);
9923 GLsizei height = static_cast<GLsizei>(c.height);
9924 GLsizei depth = static_cast<GLsizei>(c.depth);
9925 GLenum format = static_cast<GLenum>(c.format);
9926 Bucket* bucket = GetBucket(c.bucket_id);
9927 if (!bucket) {
9928 return error::kInvalidArguments;
9930 uint32 data_size = bucket->size();
9931 GLsizei image_size = data_size;
9932 const void* data = bucket->GetData(0, data_size);
9933 if (!data) {
9934 return error::kInvalidArguments;
9936 DoCompressedTexSubImage3D(
9937 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9938 image_size, data);
9939 return error::kNoError;
9942 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9943 const void* cmd_data) {
9944 const gles2::cmds::TexImage2D& c =
9945 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9946 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9947 "width", c.width, "height", c.height);
9948 // Set as failed for now, but if it successed, this will be set to not failed.
9949 texture_state_.tex_image_failed = true;
9950 GLenum target = static_cast<GLenum>(c.target);
9951 GLint level = static_cast<GLint>(c.level);
9952 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9953 // for internalformat.
9954 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9955 GLsizei width = static_cast<GLsizei>(c.width);
9956 GLsizei height = static_cast<GLsizei>(c.height);
9957 GLint border = static_cast<GLint>(c.border);
9958 GLenum format = static_cast<GLenum>(c.format);
9959 GLenum type = static_cast<GLenum>(c.type);
9960 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9961 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9962 uint32 pixels_size;
9963 if (!GLES2Util::ComputeImageDataSizes(
9964 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9965 NULL, NULL)) {
9966 return error::kOutOfBounds;
9968 const void* pixels = NULL;
9969 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9970 pixels = GetSharedMemoryAs<const void*>(
9971 pixels_shm_id, pixels_shm_offset, pixels_size);
9972 if (!pixels) {
9973 return error::kOutOfBounds;
9977 // For testing only. Allows us to stress the ability to respond to OOM errors.
9978 if (workarounds().simulate_out_of_memory_on_large_textures &&
9979 (width * height >= 4096 * 4096)) {
9980 LOCAL_SET_GL_ERROR(
9981 GL_OUT_OF_MEMORY,
9982 "glTexImage2D", "synthetic out of memory");
9983 return error::kNoError;
9986 TextureManager::DoTexImageArguments args = {
9987 target, level, internal_format, width, height, 1, border, format, type,
9988 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
9989 texture_manager()->ValidateAndDoTexImage(
9990 &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
9992 // This may be a slow command. Exit command processing to allow for
9993 // context preemption and GPU watchdog checks.
9994 ExitCommandProcessingEarly();
9995 return error::kNoError;
9998 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
9999 const void* cmd_data) {
10000 if (!unsafe_es3_apis_enabled())
10001 return error::kUnknownCommand;
10003 const gles2::cmds::TexImage3D& c =
10004 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
10005 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
10006 "widthXheight", c.width * c.height, "depth", c.depth);
10007 // Set as failed for now, but if it successed, this will be set to not failed.
10008 texture_state_.tex_image_failed = true;
10009 GLenum target = static_cast<GLenum>(c.target);
10010 GLint level = static_cast<GLint>(c.level);
10011 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10012 GLsizei width = static_cast<GLsizei>(c.width);
10013 GLsizei height = static_cast<GLsizei>(c.height);
10014 GLsizei depth = static_cast<GLsizei>(c.depth);
10015 GLint border = static_cast<GLint>(c.border);
10016 GLenum format = static_cast<GLenum>(c.format);
10017 GLenum type = static_cast<GLenum>(c.type);
10018 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10019 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10020 uint32 pixels_size;
10021 if (!GLES2Util::ComputeImageDataSizes(
10022 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
10023 NULL, NULL)) {
10024 return error::kOutOfBounds;
10026 const void* pixels = NULL;
10027 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10028 pixels = GetSharedMemoryAs<const void*>(
10029 pixels_shm_id, pixels_shm_offset, pixels_size);
10030 if (!pixels) {
10031 return error::kOutOfBounds;
10035 // For testing only. Allows us to stress the ability to respond to OOM errors.
10036 if (workarounds().simulate_out_of_memory_on_large_textures &&
10037 (width * height * depth >= 4096 * 4096)) {
10038 LOCAL_SET_GL_ERROR(
10039 GL_OUT_OF_MEMORY,
10040 "glTexImage3D", "synthetic out of memory");
10041 return error::kNoError;
10044 TextureManager::DoTexImageArguments args = {
10045 target, level, internal_format, width, height, depth, border, format, type,
10046 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
10047 texture_manager()->ValidateAndDoTexImage(
10048 &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
10050 // This may be a slow command. Exit command processing to allow for
10051 // context preemption and GPU watchdog checks.
10052 ExitCommandProcessingEarly();
10053 return error::kNoError;
10056 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10057 GLenum target,
10058 GLint level,
10059 GLint xoffset,
10060 GLint yoffset,
10061 GLsizei width,
10062 GLsizei height,
10063 GLenum format,
10064 GLsizei image_size,
10065 const void * data) {
10066 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10067 &state_, target);
10068 if (!texture_ref) {
10069 LOCAL_SET_GL_ERROR(
10070 GL_INVALID_OPERATION,
10071 "glCompressedTexSubImage2D", "unknown texture for target");
10072 return;
10074 Texture* texture = texture_ref->texture();
10075 GLenum type = 0;
10076 GLenum internal_format = 0;
10077 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
10078 LOCAL_SET_GL_ERROR(
10079 GL_INVALID_OPERATION,
10080 "glCompressedTexSubImage2D", "level does not exist.");
10081 return;
10083 if (internal_format != format) {
10084 LOCAL_SET_GL_ERROR(
10085 GL_INVALID_OPERATION,
10086 "glCompressedTexSubImage2D", "format does not match internal format.");
10087 return;
10089 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
10090 height, 1, type)) {
10091 LOCAL_SET_GL_ERROR(
10092 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
10093 return;
10096 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10097 width, height, 1, format, image_size) ||
10098 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10099 target, level, xoffset, yoffset, 0,
10100 width, height, 1, format, texture)) {
10101 return;
10105 // Note: There is no need to deal with texture cleared tracking here
10106 // because the validation above means you can only get here if the level
10107 // is already a matching compressed format and in that case
10108 // CompressedTexImage2D already cleared the texture.
10109 glCompressedTexSubImage2D(
10110 target, level, xoffset, yoffset, width, height, format, image_size, data);
10112 // This may be a slow command. Exit command processing to allow for
10113 // context preemption and GPU watchdog checks.
10114 ExitCommandProcessingEarly();
10117 static void Clip(
10118 GLint start, GLint range, GLint sourceRange,
10119 GLint* out_start, GLint* out_range) {
10120 DCHECK(out_start);
10121 DCHECK(out_range);
10122 if (start < 0) {
10123 range += start;
10124 start = 0;
10126 GLint end = start + range;
10127 if (end > sourceRange) {
10128 range -= end - sourceRange;
10130 *out_start = start;
10131 *out_range = range;
10134 void GLES2DecoderImpl::DoCopyTexImage2D(
10135 GLenum target,
10136 GLint level,
10137 GLenum internal_format,
10138 GLint x,
10139 GLint y,
10140 GLsizei width,
10141 GLsizei height,
10142 GLint border) {
10143 DCHECK(!ShouldDeferReads());
10144 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10145 &state_, target);
10146 if (!texture_ref) {
10147 LOCAL_SET_GL_ERROR(
10148 GL_INVALID_OPERATION,
10149 "glCopyTexImage2D", "unknown texture for target");
10150 return;
10152 Texture* texture = texture_ref->texture();
10153 if (texture->IsImmutable()) {
10154 LOCAL_SET_GL_ERROR(
10155 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
10156 return;
10158 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
10159 border != 0) {
10160 LOCAL_SET_GL_ERROR(
10161 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
10162 return;
10164 if (!texture_manager()->ValidateFormatAndTypeCombination(
10165 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
10166 GL_UNSIGNED_BYTE)) {
10167 return;
10170 // Check we have compatible formats.
10171 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10172 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10173 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
10175 if ((channels_needed & channels_exist) != channels_needed) {
10176 LOCAL_SET_GL_ERROR(
10177 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
10178 return;
10181 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10182 LOCAL_SET_GL_ERROR(
10183 GL_INVALID_OPERATION,
10184 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10185 return;
10188 uint32 estimated_size = 0;
10189 if (!GLES2Util::ComputeImageDataSizes(
10190 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10191 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
10192 LOCAL_SET_GL_ERROR(
10193 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
10194 return;
10197 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10198 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
10199 return;
10202 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10203 return;
10206 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10207 LOCAL_SET_GL_ERROR(
10208 GL_INVALID_OPERATION,
10209 "glCopyTexImage2D", "source and destination textures are the same");
10210 return;
10213 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10214 return;
10217 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10218 ScopedResolvedFrameBufferBinder binder(this, false, true);
10219 gfx::Size size = GetBoundReadFrameBufferSize();
10221 if (texture->IsAttachedToFramebuffer()) {
10222 framebuffer_state_.clear_state_dirty = true;
10225 // Clip to size to source dimensions
10226 GLint copyX = 0;
10227 GLint copyY = 0;
10228 GLint copyWidth = 0;
10229 GLint copyHeight = 0;
10230 Clip(x, width, size.width(), &copyX, &copyWidth);
10231 Clip(y, height, size.height(), &copyY, &copyHeight);
10233 if (copyX != x ||
10234 copyY != y ||
10235 copyWidth != width ||
10236 copyHeight != height) {
10237 // some part was clipped so clear the rect.
10238 uint32 pixels_size = 0;
10239 if (!GLES2Util::ComputeImageDataSizes(
10240 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10241 state_.unpack_alignment, &pixels_size, NULL, NULL)) {
10242 LOCAL_SET_GL_ERROR(
10243 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
10244 return;
10246 scoped_ptr<char[]> zero(new char[pixels_size]);
10247 memset(zero.get(), 0, pixels_size);
10248 ScopedModifyPixels modify(texture_ref);
10249 glTexImage2D(target, level, internal_format, width, height, border,
10250 internal_format, GL_UNSIGNED_BYTE, zero.get());
10251 if (copyHeight > 0 && copyWidth > 0) {
10252 GLint dx = copyX - x;
10253 GLint dy = copyY - y;
10254 GLint destX = dx;
10255 GLint destY = dy;
10256 glCopyTexSubImage2D(target, level,
10257 destX, destY, copyX, copyY,
10258 copyWidth, copyHeight);
10260 } else {
10261 ScopedModifyPixels modify(texture_ref);
10262 glCopyTexImage2D(target, level, internal_format,
10263 copyX, copyY, copyWidth, copyHeight, border);
10265 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10266 if (error == GL_NO_ERROR) {
10267 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10268 width, height, 1, border, internal_format,
10269 GL_UNSIGNED_BYTE, gfx::Rect(width, height));
10272 // This may be a slow command. Exit command processing to allow for
10273 // context preemption and GPU watchdog checks.
10274 ExitCommandProcessingEarly();
10277 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10278 GLenum target,
10279 GLint level,
10280 GLint xoffset,
10281 GLint yoffset,
10282 GLint x,
10283 GLint y,
10284 GLsizei width,
10285 GLsizei height) {
10286 DCHECK(!ShouldDeferReads());
10287 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10288 &state_, target);
10289 if (!texture_ref) {
10290 LOCAL_SET_GL_ERROR(
10291 GL_INVALID_OPERATION,
10292 "glCopyTexSubImage2D", "unknown texture for target");
10293 return;
10295 Texture* texture = texture_ref->texture();
10296 GLenum type = 0;
10297 GLenum format = 0;
10298 if (!texture->GetLevelType(target, level, &type, &format) ||
10299 !texture->ValidForTexture(
10300 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10301 LOCAL_SET_GL_ERROR(
10302 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
10303 return;
10305 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10306 LOCAL_SET_GL_ERROR(
10307 GL_INVALID_OPERATION,
10308 "glCopyTexSubImage2D", "async upload pending for texture");
10309 return;
10312 // Check we have compatible formats.
10313 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10314 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10315 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
10317 if (!channels_needed ||
10318 (channels_needed & channels_exist) != channels_needed) {
10319 LOCAL_SET_GL_ERROR(
10320 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
10321 return;
10324 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10325 LOCAL_SET_GL_ERROR(
10326 GL_INVALID_OPERATION,
10327 "glCopySubImage2D", "can not be used with depth or stencil textures");
10328 return;
10331 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10332 return;
10335 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10336 LOCAL_SET_GL_ERROR(
10337 GL_INVALID_OPERATION,
10338 "glCopyTexSubImage2D", "source and destination textures are the same");
10339 return;
10342 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10343 return;
10346 ScopedResolvedFrameBufferBinder binder(this, false, true);
10347 gfx::Size size = GetBoundReadFrameBufferSize();
10348 GLint copyX = 0;
10349 GLint copyY = 0;
10350 GLint copyWidth = 0;
10351 GLint copyHeight = 0;
10352 Clip(x, width, size.width(), &copyX, &copyWidth);
10353 Clip(y, height, size.height(), &copyY, &copyHeight);
10355 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
10356 height != size.height()) {
10357 gfx::Rect cleared_rect;
10358 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10359 gfx::Rect(xoffset, yoffset, width, height),
10360 &cleared_rect)) {
10361 DCHECK_GE(cleared_rect.size().GetArea(),
10362 texture->GetLevelClearedRect(target, level).size().GetArea());
10363 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10364 cleared_rect);
10365 } else {
10366 // Otherwise clear part of texture level that is not already cleared.
10367 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10368 level)) {
10369 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
10370 "dimensions too big");
10371 return;
10374 } else {
10375 // Write all pixels in below.
10376 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10379 if (copyX != x ||
10380 copyY != y ||
10381 copyWidth != width ||
10382 copyHeight != height) {
10383 // some part was clipped so clear the sub rect.
10384 uint32 pixels_size = 0;
10385 if (!GLES2Util::ComputeImageDataSizes(
10386 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10387 NULL, NULL)) {
10388 LOCAL_SET_GL_ERROR(
10389 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
10390 return;
10392 scoped_ptr<char[]> zero(new char[pixels_size]);
10393 memset(zero.get(), 0, pixels_size);
10394 ScopedModifyPixels modify(texture_ref);
10395 glTexSubImage2D(
10396 target, level, xoffset, yoffset, width, height,
10397 format, type, zero.get());
10400 if (copyHeight > 0 && copyWidth > 0) {
10401 GLint dx = copyX - x;
10402 GLint dy = copyY - y;
10403 GLint destX = xoffset + dx;
10404 GLint destY = yoffset + dy;
10405 ScopedModifyPixels modify(texture_ref);
10406 glCopyTexSubImage2D(target, level,
10407 destX, destY, copyX, copyY,
10408 copyWidth, copyHeight);
10411 // This may be a slow command. Exit command processing to allow for
10412 // context preemption and GPU watchdog checks.
10413 ExitCommandProcessingEarly();
10416 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10417 error::Error* error,
10418 const char* function_name,
10419 GLenum target,
10420 GLint level,
10421 GLint xoffset,
10422 GLint yoffset,
10423 GLsizei width,
10424 GLsizei height,
10425 GLenum format,
10426 GLenum type,
10427 const void * data) {
10428 (*error) = error::kNoError;
10429 if (!validators_->texture_target.IsValid(target)) {
10430 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10431 return false;
10433 if (width < 0) {
10434 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10435 return false;
10437 if (height < 0) {
10438 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10439 return false;
10441 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10442 &state_, target);
10443 if (!texture_ref) {
10444 LOCAL_SET_GL_ERROR(
10445 GL_INVALID_OPERATION,
10446 function_name, "unknown texture for target");
10447 return false;
10449 Texture* texture = texture_ref->texture();
10450 GLenum current_type = 0;
10451 GLenum internal_format = 0;
10452 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
10453 LOCAL_SET_GL_ERROR(
10454 GL_INVALID_OPERATION, function_name, "level does not exist.");
10455 return false;
10457 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
10458 function_name, format, type, internal_format, level)) {
10459 return false;
10461 if (type != current_type) {
10462 LOCAL_SET_GL_ERROR(
10463 GL_INVALID_OPERATION,
10464 function_name, "type does not match type of texture.");
10465 return false;
10467 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10468 LOCAL_SET_GL_ERROR(
10469 GL_INVALID_OPERATION,
10470 function_name, "async upload pending for texture");
10471 return false;
10473 if (!texture->ValidForTexture(
10474 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10475 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
10476 return false;
10478 if ((GLES2Util::GetChannelsForFormat(format) &
10479 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0
10480 && !feature_info_->IsES3Enabled()) {
10481 LOCAL_SET_GL_ERROR(
10482 GL_INVALID_OPERATION,
10483 function_name, "can not supply data for depth or stencil textures");
10484 return false;
10486 if (data == NULL) {
10487 (*error) = error::kOutOfBounds;
10488 return false;
10490 return true;
10493 error::Error GLES2DecoderImpl::DoTexSubImage2D(
10494 GLenum target,
10495 GLint level,
10496 GLint xoffset,
10497 GLint yoffset,
10498 GLsizei width,
10499 GLsizei height,
10500 GLenum format,
10501 GLenum type,
10502 const void * data) {
10503 error::Error error = error::kNoError;
10504 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
10505 xoffset, yoffset, width, height, format, type, data)) {
10506 return error;
10508 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10509 &state_, target);
10510 Texture* texture = texture_ref->texture();
10511 GLsizei tex_width = 0;
10512 GLsizei tex_height = 0;
10513 bool ok = texture->GetLevelSize(
10514 target, level, &tex_width, &tex_height, nullptr);
10515 DCHECK(ok);
10516 if (xoffset != 0 || yoffset != 0 ||
10517 width != tex_width || height != tex_height) {
10518 gfx::Rect cleared_rect;
10519 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10520 gfx::Rect(xoffset, yoffset, width, height),
10521 &cleared_rect)) {
10522 DCHECK_GE(cleared_rect.size().GetArea(),
10523 texture->GetLevelClearedRect(target, level).size().GetArea());
10524 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10525 cleared_rect);
10526 } else {
10527 // Otherwise clear part of texture level that is not already cleared.
10528 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10529 level)) {
10530 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D",
10531 "dimensions too big");
10532 return error::kNoError;
10535 ScopedTextureUploadTimer timer(&texture_state_);
10536 glTexSubImage2D(
10537 target, level, xoffset, yoffset, width, height, format, type, data);
10538 return error::kNoError;
10541 if (!texture_state_.texsubimage_faster_than_teximage &&
10542 !texture->IsImmutable() &&
10543 !texture->HasImages()) {
10544 ScopedTextureUploadTimer timer(&texture_state_);
10545 GLenum internal_format;
10546 GLenum tex_type;
10547 texture->GetLevelType(target, level, &tex_type, &internal_format);
10548 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10549 // to look it up.
10550 glTexImage2D(
10551 target, level, internal_format, width, height, 0, format, type, data);
10552 } else {
10553 ScopedTextureUploadTimer timer(&texture_state_);
10554 glTexSubImage2D(
10555 target, level, xoffset, yoffset, width, height, format, type, data);
10557 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10559 // This may be a slow command. Exit command processing to allow for
10560 // context preemption and GPU watchdog checks.
10561 ExitCommandProcessingEarly();
10562 return error::kNoError;
10565 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
10566 const void* cmd_data) {
10567 const gles2::cmds::TexSubImage2D& c =
10568 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
10569 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10570 "width", c.width, "height", c.height);
10571 GLboolean internal = static_cast<GLboolean>(c.internal);
10572 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10573 return error::kNoError;
10575 GLenum target = static_cast<GLenum>(c.target);
10576 GLint level = static_cast<GLint>(c.level);
10577 GLint xoffset = static_cast<GLint>(c.xoffset);
10578 GLint yoffset = static_cast<GLint>(c.yoffset);
10579 GLsizei width = static_cast<GLsizei>(c.width);
10580 GLsizei height = static_cast<GLsizei>(c.height);
10581 GLenum format = static_cast<GLenum>(c.format);
10582 GLenum type = static_cast<GLenum>(c.type);
10583 uint32 data_size;
10584 if (!GLES2Util::ComputeImageDataSizes(
10585 width, height, 1, format, type, state_.unpack_alignment, &data_size,
10586 NULL, NULL)) {
10587 return error::kOutOfBounds;
10589 const void* pixels = GetSharedMemoryAs<const void*>(
10590 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10591 return DoTexSubImage2D(
10592 target, level, xoffset, yoffset, width, height, format, type, pixels);
10595 error::Error GLES2DecoderImpl::DoTexSubImage3D(
10596 GLenum target,
10597 GLint level,
10598 GLint xoffset,
10599 GLint yoffset,
10600 GLint zoffset,
10601 GLsizei width,
10602 GLsizei height,
10603 GLsizei depth,
10604 GLenum format,
10605 GLenum type,
10606 const void * data) {
10607 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10608 &state_, target);
10609 if (!texture_ref) {
10610 LOCAL_SET_GL_ERROR(
10611 GL_INVALID_ENUM, "glTexSubImage3D", "invalid target");
10614 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10615 ScopedTextureUploadTimer timer(&texture_state_);
10616 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
10617 depth, format, type, data);
10618 GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10619 if (error == GL_NO_ERROR) {
10620 // TODO(zmo): This is not 100% correct because only part of the level
10621 // image is cleared.
10622 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10625 // This may be a slow command. Exit command processing to allow for
10626 // context preemption and GPU watchdog checks.
10627 ExitCommandProcessingEarly();
10628 return error::kNoError;
10631 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
10632 const void* cmd_data) {
10633 if (!unsafe_es3_apis_enabled())
10634 return error::kUnknownCommand;
10636 const gles2::cmds::TexSubImage3D& c =
10637 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
10638 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10639 "widthXheight", c.width * c.height, "depth", c.depth);
10640 GLboolean internal = static_cast<GLboolean>(c.internal);
10641 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10642 return error::kNoError;
10644 GLenum target = static_cast<GLenum>(c.target);
10645 GLint level = static_cast<GLint>(c.level);
10646 GLint xoffset = static_cast<GLint>(c.xoffset);
10647 GLint yoffset = static_cast<GLint>(c.yoffset);
10648 GLint zoffset = static_cast<GLint>(c.zoffset);
10649 GLsizei width = static_cast<GLsizei>(c.width);
10650 GLsizei height = static_cast<GLsizei>(c.height);
10651 GLsizei depth = static_cast<GLsizei>(c.depth);
10652 GLenum format = static_cast<GLenum>(c.format);
10653 GLenum type = static_cast<GLenum>(c.type);
10654 uint32 data_size;
10655 if (!GLES2Util::ComputeImageDataSizes(
10656 width, height, depth, format, type, state_.unpack_alignment, &data_size,
10657 NULL, NULL)) {
10658 return error::kOutOfBounds;
10660 const void* pixels = GetSharedMemoryAs<const void*>(
10661 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10662 return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
10663 height, depth, format, type, pixels);
10666 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10667 uint32 immediate_data_size,
10668 const void* cmd_data) {
10669 const gles2::cmds::GetVertexAttribPointerv& c =
10670 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
10671 GLuint index = static_cast<GLuint>(c.index);
10672 GLenum pname = static_cast<GLenum>(c.pname);
10673 typedef cmds::GetVertexAttribPointerv::Result Result;
10674 Result* result = GetSharedMemoryAs<Result*>(
10675 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
10676 if (!result) {
10677 return error::kOutOfBounds;
10679 // Check that the client initialized the result.
10680 if (result->size != 0) {
10681 return error::kInvalidArguments;
10683 if (!validators_->vertex_pointer.IsValid(pname)) {
10684 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10685 "glGetVertexAttribPointerv", pname, "pname");
10686 return error::kNoError;
10688 if (index >= group_->max_vertex_attribs()) {
10689 LOCAL_SET_GL_ERROR(
10690 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
10691 return error::kNoError;
10693 result->SetNumResults(1);
10694 *result->GetData() =
10695 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
10696 return error::kNoError;
10699 template <class T>
10700 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
10701 GLint fake_location,
10702 uint32 shm_id,
10703 uint32 shm_offset,
10704 error::Error* error,
10705 GLint* real_location,
10706 GLuint* service_id,
10707 SizedResult<T>** result_pointer,
10708 GLenum* result_type,
10709 GLsizei* result_size) {
10710 DCHECK(error);
10711 DCHECK(service_id);
10712 DCHECK(result_pointer);
10713 DCHECK(result_type);
10714 DCHECK(result_size);
10715 DCHECK(real_location);
10716 *error = error::kNoError;
10717 // Make sure we have enough room for the result on failure.
10718 SizedResult<T>* result;
10719 result = GetSharedMemoryAs<SizedResult<T>*>(
10720 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
10721 if (!result) {
10722 *error = error::kOutOfBounds;
10723 return false;
10725 *result_pointer = result;
10726 // Set the result size to 0 so the client does not have to check for success.
10727 result->SetNumResults(0);
10728 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
10729 if (!program) {
10730 return false;
10732 if (!program->IsValid()) {
10733 // Program was not linked successfully. (ie, glLinkProgram)
10734 LOCAL_SET_GL_ERROR(
10735 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
10736 return false;
10738 *service_id = program->service_id();
10739 GLint array_index = -1;
10740 const Program::UniformInfo* uniform_info =
10741 program->GetUniformInfoByFakeLocation(
10742 fake_location, real_location, &array_index);
10743 if (!uniform_info) {
10744 // No such location.
10745 LOCAL_SET_GL_ERROR(
10746 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
10747 return false;
10749 GLenum type = uniform_info->type;
10750 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
10751 if (num_elements == 0) {
10752 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
10753 return false;
10755 result = GetSharedMemoryAs<SizedResult<T>*>(
10756 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
10757 if (!result) {
10758 *error = error::kOutOfBounds;
10759 return false;
10761 result->SetNumResults(num_elements);
10762 *result_size = num_elements * sizeof(T);
10763 *result_type = type;
10764 return true;
10767 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
10768 const void* cmd_data) {
10769 const gles2::cmds::GetUniformiv& c =
10770 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
10771 GLuint program = c.program;
10772 GLint fake_location = c.location;
10773 GLuint service_id;
10774 GLenum result_type;
10775 GLsizei result_size;
10776 GLint real_location = -1;
10777 Error error;
10778 cmds::GetUniformiv::Result* result;
10779 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
10780 c.params_shm_offset, &error, &real_location,
10781 &service_id, &result, &result_type,
10782 &result_size)) {
10783 glGetUniformiv(
10784 service_id, real_location, result->GetData());
10786 return error;
10789 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
10790 const void* cmd_data) {
10791 if (!unsafe_es3_apis_enabled())
10792 return error::kUnknownCommand;
10794 const gles2::cmds::GetUniformuiv& c =
10795 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
10796 GLuint program = c.program;
10797 GLint fake_location = c.location;
10798 GLuint service_id;
10799 GLenum result_type;
10800 GLsizei result_size;
10801 GLint real_location = -1;
10802 Error error;
10803 cmds::GetUniformuiv::Result* result;
10804 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
10805 c.params_shm_offset, &error, &real_location,
10806 &service_id, &result, &result_type,
10807 &result_size)) {
10808 glGetUniformuiv(
10809 service_id, real_location, result->GetData());
10811 return error;
10814 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
10815 const void* cmd_data) {
10816 const gles2::cmds::GetUniformfv& c =
10817 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
10818 GLuint program = c.program;
10819 GLint fake_location = c.location;
10820 GLuint service_id;
10821 GLint real_location = -1;
10822 Error error;
10823 cmds::GetUniformfv::Result* result;
10824 GLenum result_type;
10825 GLsizei result_size;
10826 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
10827 c.params_shm_offset, &error, &real_location,
10828 &service_id, &result, &result_type,
10829 &result_size)) {
10830 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
10831 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
10832 GLsizei num_values = result_size / sizeof(GLfloat);
10833 scoped_ptr<GLint[]> temp(new GLint[num_values]);
10834 glGetUniformiv(service_id, real_location, temp.get());
10835 GLfloat* dst = result->GetData();
10836 for (GLsizei ii = 0; ii < num_values; ++ii) {
10837 dst[ii] = (temp[ii] != 0);
10839 } else {
10840 glGetUniformfv(service_id, real_location, result->GetData());
10843 return error;
10846 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10847 uint32 immediate_data_size,
10848 const void* cmd_data) {
10849 const gles2::cmds::GetShaderPrecisionFormat& c =
10850 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
10851 GLenum shader_type = static_cast<GLenum>(c.shadertype);
10852 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
10853 typedef cmds::GetShaderPrecisionFormat::Result Result;
10854 Result* result = GetSharedMemoryAs<Result*>(
10855 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10856 if (!result) {
10857 return error::kOutOfBounds;
10859 // Check that the client initialized the result.
10860 if (result->success != 0) {
10861 return error::kInvalidArguments;
10863 if (!validators_->shader_type.IsValid(shader_type)) {
10864 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10865 "glGetShaderPrecisionFormat", shader_type, "shader_type");
10866 return error::kNoError;
10868 if (!validators_->shader_precision.IsValid(precision_type)) {
10869 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10870 "glGetShaderPrecisionFormat", precision_type, "precision_type");
10871 return error::kNoError;
10874 result->success = 1; // true
10876 GLint range[2] = { 0, 0 };
10877 GLint precision = 0;
10878 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
10880 result->min_range = range[0];
10881 result->max_range = range[1];
10882 result->precision = precision;
10884 return error::kNoError;
10887 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
10888 uint32 immediate_data_size,
10889 const void* cmd_data) {
10890 const gles2::cmds::GetAttachedShaders& c =
10891 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
10892 uint32 result_size = c.result_size;
10893 GLuint program_id = static_cast<GLuint>(c.program);
10894 Program* program = GetProgramInfoNotShader(
10895 program_id, "glGetAttachedShaders");
10896 if (!program) {
10897 return error::kNoError;
10899 typedef cmds::GetAttachedShaders::Result Result;
10900 uint32 max_count = Result::ComputeMaxResults(result_size);
10901 Result* result = GetSharedMemoryAs<Result*>(
10902 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
10903 if (!result) {
10904 return error::kOutOfBounds;
10906 // Check that the client initialized the result.
10907 if (result->size != 0) {
10908 return error::kInvalidArguments;
10910 GLsizei count = 0;
10911 glGetAttachedShaders(
10912 program->service_id(), max_count, &count, result->GetData());
10913 for (GLsizei ii = 0; ii < count; ++ii) {
10914 if (!shader_manager()->GetClientId(result->GetData()[ii],
10915 &result->GetData()[ii])) {
10916 NOTREACHED();
10917 return error::kGenericError;
10920 result->SetNumResults(count);
10921 return error::kNoError;
10924 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
10925 uint32 immediate_data_size,
10926 const void* cmd_data) {
10927 const gles2::cmds::GetActiveUniform& c =
10928 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
10929 GLuint program_id = c.program;
10930 GLuint index = c.index;
10931 uint32 name_bucket_id = c.name_bucket_id;
10932 typedef cmds::GetActiveUniform::Result Result;
10933 Result* result = GetSharedMemoryAs<Result*>(
10934 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10935 if (!result) {
10936 return error::kOutOfBounds;
10938 // Check that the client initialized the result.
10939 if (result->success != 0) {
10940 return error::kInvalidArguments;
10942 Program* program = GetProgramInfoNotShader(
10943 program_id, "glGetActiveUniform");
10944 if (!program) {
10945 return error::kNoError;
10947 const Program::UniformInfo* uniform_info =
10948 program->GetUniformInfo(index);
10949 if (!uniform_info) {
10950 LOCAL_SET_GL_ERROR(
10951 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
10952 return error::kNoError;
10954 result->success = 1; // true.
10955 result->size = uniform_info->size;
10956 result->type = uniform_info->type;
10957 Bucket* bucket = CreateBucket(name_bucket_id);
10958 bucket->SetFromString(uniform_info->name.c_str());
10959 return error::kNoError;
10962 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10963 uint32 immediate_data_size, const void* cmd_data) {
10964 if (!unsafe_es3_apis_enabled())
10965 return error::kUnknownCommand;
10966 const gles2::cmds::GetActiveUniformBlockiv& c =
10967 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
10968 GLuint program_id = c.program;
10969 GLuint index = static_cast<GLuint>(c.index);
10970 GLenum pname = static_cast<GLenum>(c.pname);
10971 Program* program = GetProgramInfoNotShader(
10972 program_id, "glGetActiveUniformBlockiv");
10973 if (!program) {
10974 return error::kNoError;
10976 GLuint service_id = program->service_id();
10977 GLint link_status = GL_FALSE;
10978 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10979 if (link_status != GL_TRUE) {
10980 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10981 "glGetActiveActiveUniformBlockiv", "program not linked");
10982 return error::kNoError;
10984 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10985 GLsizei num_values = 1;
10986 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
10987 GLint num = 0;
10988 glGetActiveUniformBlockiv(
10989 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
10990 GLenum error = glGetError();
10991 if (error != GL_NO_ERROR) {
10992 // Assume this will the same error if calling with pname.
10993 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10994 return error::kNoError;
10996 num_values = static_cast<GLsizei>(num);
10998 typedef cmds::GetActiveUniformBlockiv::Result Result;
10999 Result* result = GetSharedMemoryAs<Result*>(
11000 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
11001 GLint* params = result ? result->GetData() : NULL;
11002 if (params == NULL) {
11003 return error::kOutOfBounds;
11005 // Check that the client initialized the result.
11006 if (result->size != 0) {
11007 return error::kInvalidArguments;
11009 glGetActiveUniformBlockiv(service_id, index, pname, params);
11010 GLenum error = glGetError();
11011 if (error == GL_NO_ERROR) {
11012 result->SetNumResults(num_values);
11013 } else {
11014 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
11016 return error::kNoError;
11019 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11020 uint32 immediate_data_size, const void* cmd_data) {
11021 if (!unsafe_es3_apis_enabled())
11022 return error::kUnknownCommand;
11023 const gles2::cmds::GetActiveUniformBlockName& c =
11024 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
11025 GLuint program_id = c.program;
11026 GLuint index = c.index;
11027 uint32 name_bucket_id = c.name_bucket_id;
11028 typedef cmds::GetActiveUniformBlockName::Result Result;
11029 Result* result = GetSharedMemoryAs<Result*>(
11030 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11031 if (!result) {
11032 return error::kOutOfBounds;
11034 // Check that the client initialized the result.
11035 if (*result != 0) {
11036 return error::kInvalidArguments;
11038 Program* program = GetProgramInfoNotShader(
11039 program_id, "glGetActiveUniformBlockName");
11040 if (!program) {
11041 return error::kNoError;
11043 GLuint service_id = program->service_id();
11044 GLint link_status = GL_FALSE;
11045 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11046 if (link_status != GL_TRUE) {
11047 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11048 "glGetActiveActiveUniformBlockName", "program not linked");
11049 return error::kNoError;
11051 GLint max_length = 0;
11052 glGetProgramiv(
11053 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
11054 // Increase one so &buffer[0] is always valid.
11055 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
11056 std::vector<char> buffer(buf_size);
11057 GLsizei length = 0;
11058 glGetActiveUniformBlockName(
11059 service_id, index, buf_size, &length, &buffer[0]);
11060 if (length == 0) {
11061 *result = 0;
11062 return error::kNoError;
11064 *result = 1;
11065 Bucket* bucket = CreateBucket(name_bucket_id);
11066 DCHECK_GT(buf_size, length);
11067 DCHECK_EQ(0, buffer[length]);
11068 bucket->SetFromString(&buffer[0]);
11069 return error::kNoError;
11072 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
11073 uint32 immediate_data_size, const void* cmd_data) {
11074 if (!unsafe_es3_apis_enabled())
11075 return error::kUnknownCommand;
11076 const gles2::cmds::GetActiveUniformsiv& c =
11077 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
11078 GLuint program_id = c.program;
11079 GLenum pname = static_cast<GLenum>(c.pname);
11080 Bucket* bucket = GetBucket(c.indices_bucket_id);
11081 if (!bucket) {
11082 return error::kInvalidArguments;
11084 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
11085 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
11086 typedef cmds::GetActiveUniformsiv::Result Result;
11087 Result* result = GetSharedMemoryAs<Result*>(
11088 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
11089 GLint* params = result ? result->GetData() : NULL;
11090 if (params == NULL) {
11091 return error::kOutOfBounds;
11093 // Check that the client initialized the result.
11094 if (result->size != 0) {
11095 return error::kInvalidArguments;
11097 Program* program = GetProgramInfoNotShader(
11098 program_id, "glGetActiveUniformsiv");
11099 if (!program) {
11100 return error::kNoError;
11102 GLuint service_id = program->service_id();
11103 GLint link_status = GL_FALSE;
11104 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11105 if (link_status != GL_TRUE) {
11106 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11107 "glGetActiveUniformsiv", "program not linked");
11108 return error::kNoError;
11110 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11111 glGetActiveUniformsiv(service_id, count, indices, pname, params);
11112 GLenum error = glGetError();
11113 if (error == GL_NO_ERROR) {
11114 result->SetNumResults(count);
11115 } else {
11116 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
11118 return error::kNoError;
11121 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
11122 const void* cmd_data) {
11123 const gles2::cmds::GetActiveAttrib& c =
11124 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
11125 GLuint program_id = c.program;
11126 GLuint index = c.index;
11127 uint32 name_bucket_id = c.name_bucket_id;
11128 typedef cmds::GetActiveAttrib::Result Result;
11129 Result* result = GetSharedMemoryAs<Result*>(
11130 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11131 if (!result) {
11132 return error::kOutOfBounds;
11134 // Check that the client initialized the result.
11135 if (result->success != 0) {
11136 return error::kInvalidArguments;
11138 Program* program = GetProgramInfoNotShader(
11139 program_id, "glGetActiveAttrib");
11140 if (!program) {
11141 return error::kNoError;
11143 const Program::VertexAttrib* attrib_info =
11144 program->GetAttribInfo(index);
11145 if (!attrib_info) {
11146 LOCAL_SET_GL_ERROR(
11147 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
11148 return error::kNoError;
11150 result->success = 1; // true.
11151 result->size = attrib_info->size;
11152 result->type = attrib_info->type;
11153 Bucket* bucket = CreateBucket(name_bucket_id);
11154 bucket->SetFromString(attrib_info->name.c_str());
11155 return error::kNoError;
11158 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
11159 const void* cmd_data) {
11160 #if 1 // No binary shader support.
11161 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
11162 return error::kNoError;
11163 #else
11164 GLsizei n = static_cast<GLsizei>(c.n);
11165 if (n < 0) {
11166 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
11167 return error::kNoError;
11169 GLsizei length = static_cast<GLsizei>(c.length);
11170 if (length < 0) {
11171 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
11172 return error::kNoError;
11174 uint32 data_size;
11175 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
11176 return error::kOutOfBounds;
11178 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
11179 c.shaders_shm_id, c.shaders_shm_offset, data_size);
11180 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
11181 const void* binary = GetSharedMemoryAs<const void*>(
11182 c.binary_shm_id, c.binary_shm_offset, length);
11183 if (shaders == NULL || binary == NULL) {
11184 return error::kOutOfBounds;
11186 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11187 for (GLsizei ii = 0; ii < n; ++ii) {
11188 Shader* shader = GetShader(shaders[ii]);
11189 if (!shader) {
11190 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
11191 return error::kNoError;
11193 service_ids[ii] = shader->service_id();
11195 // TODO(gman): call glShaderBinary
11196 return error::kNoError;
11197 #endif
11200 void GLES2DecoderImpl::DoSwapBuffers() {
11201 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
11203 int this_frame_number = frame_number_++;
11204 // TRACE_EVENT for gpu tests:
11205 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11206 TRACE_EVENT_SCOPE_THREAD,
11207 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11208 "width", (is_offscreen ? offscreen_size_.width() :
11209 surface_->GetSize().width()));
11210 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11211 "offscreen", is_offscreen,
11212 "frame", this_frame_number);
11214 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11217 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
11218 "GLES2Decoder", "SwapBuffer");
11220 bool is_tracing;
11221 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11222 &is_tracing);
11223 if (is_tracing) {
11224 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
11225 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
11226 is_offscreen ? offscreen_size_ : surface_->GetSize());
11229 // If offscreen then don't actually SwapBuffers to the display. Just copy
11230 // the rendered frame to another frame buffer.
11231 if (is_offscreen) {
11232 TRACE_EVENT2("gpu", "Offscreen",
11233 "width", offscreen_size_.width(), "height", offscreen_size_.height());
11234 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
11235 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11236 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11237 // fix this.
11238 if (workarounds().needs_offscreen_buffer_workaround) {
11239 offscreen_saved_frame_buffer_->Create();
11240 glFinish();
11243 // Allocate the offscreen saved color texture.
11244 DCHECK(offscreen_saved_color_format_);
11245 offscreen_saved_color_texture_->AllocateStorage(
11246 offscreen_size_, offscreen_saved_color_format_, false);
11248 offscreen_saved_frame_buffer_->AttachRenderTexture(
11249 offscreen_saved_color_texture_.get());
11250 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
11251 if (offscreen_saved_frame_buffer_->CheckStatus() !=
11252 GL_FRAMEBUFFER_COMPLETE) {
11253 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11254 << "because offscreen saved FBO was incomplete.";
11255 MarkContextLost(error::kUnknown);
11256 group_->LoseContexts(error::kUnknown);
11257 return;
11260 // Clear the offscreen color texture.
11261 // TODO(piman): Is this still necessary?
11263 ScopedFrameBufferBinder binder(this,
11264 offscreen_saved_frame_buffer_->id());
11265 glClearColor(0, 0, 0, 0);
11266 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
11267 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
11268 glClear(GL_COLOR_BUFFER_BIT);
11269 RestoreClearState();
11273 UpdateParentTextureInfo();
11276 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
11277 return;
11278 ScopedGLErrorSuppressor suppressor(
11279 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11281 if (IsOffscreenBufferMultisampled()) {
11282 // For multisampled buffers, resolve the frame buffer.
11283 ScopedResolvedFrameBufferBinder binder(this, true, false);
11284 } else {
11285 ScopedFrameBufferBinder binder(this,
11286 offscreen_target_frame_buffer_->id());
11288 if (offscreen_target_buffer_preserved_) {
11289 // Copy the target frame buffer to the saved offscreen texture.
11290 offscreen_saved_color_texture_->Copy(
11291 offscreen_saved_color_texture_->size(),
11292 offscreen_saved_color_format_);
11293 } else {
11294 // Flip the textures in the parent context via the texture manager.
11295 if (!!offscreen_saved_color_texture_info_.get())
11296 offscreen_saved_color_texture_info_->texture()->
11297 SetServiceId(offscreen_target_color_texture_->id());
11299 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
11300 offscreen_target_frame_buffer_->AttachRenderTexture(
11301 offscreen_target_color_texture_.get());
11304 // Ensure the side effects of the copy are visible to the parent
11305 // context. There is no need to do this for ANGLE because it uses a
11306 // single D3D device for all contexts.
11307 if (!feature_info_->gl_version_info().is_angle)
11308 glFlush();
11310 } else {
11311 if (surface_->SwapBuffers() == gfx::SwapResult::SWAP_FAILED) {
11312 LOG(ERROR) << "Context lost because SwapBuffers failed.";
11313 if (!CheckResetStatus()) {
11314 MarkContextLost(error::kUnknown);
11315 group_->LoseContexts(error::kUnknown);
11320 // This may be a slow command. Exit command processing to allow for
11321 // context preemption and GPU watchdog checks.
11322 ExitCommandProcessingEarly();
11325 void GLES2DecoderImpl::DoSwapInterval(int interval) {
11326 context_->SetSwapInterval(interval);
11329 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11330 uint32 immediate_data_size,
11331 const void* cmd_data) {
11332 const gles2::cmds::EnableFeatureCHROMIUM& c =
11333 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
11334 Bucket* bucket = GetBucket(c.bucket_id);
11335 if (!bucket || bucket->size() == 0) {
11336 return error::kInvalidArguments;
11338 typedef cmds::EnableFeatureCHROMIUM::Result Result;
11339 Result* result = GetSharedMemoryAs<Result*>(
11340 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11341 if (!result) {
11342 return error::kOutOfBounds;
11344 // Check that the client initialized the result.
11345 if (*result != 0) {
11346 return error::kInvalidArguments;
11348 std::string feature_str;
11349 if (!bucket->GetAsString(&feature_str)) {
11350 return error::kInvalidArguments;
11353 // TODO(gman): make this some kind of table to function pointer thingy.
11354 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11355 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11356 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
11357 buffer_manager()->set_allow_fixed_attribs(true);
11358 // TODO(gman): decide how to remove the need for this const_cast.
11359 // I could make validators_ non const but that seems bad as this is the only
11360 // place it is needed. I could make some special friend class of validators
11361 // just to allow this to set them. That seems silly. I could refactor this
11362 // code to use the extension mechanism or the initialization attributes to
11363 // turn this feature on. Given that the only real point of this is to make
11364 // the conformance tests pass and given that there is lots of real work that
11365 // needs to be done it seems like refactoring for one to one of those
11366 // methods is a very low priority.
11367 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
11368 } else {
11369 return error::kNoError;
11372 *result = 1; // true.
11373 return error::kNoError;
11376 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11377 uint32 immediate_data_size,
11378 const void* cmd_data) {
11379 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
11380 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
11381 cmd_data);
11382 Bucket* bucket = CreateBucket(c.bucket_id);
11383 scoped_refptr<FeatureInfo> info(new FeatureInfo());
11384 info->Initialize(disallowed_features_);
11385 bucket->SetFromString(info->extensions().c_str());
11386 return error::kNoError;
11389 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11390 uint32 immediate_data_size,
11391 const void* cmd_data) {
11392 const gles2::cmds::RequestExtensionCHROMIUM& c =
11393 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
11394 Bucket* bucket = GetBucket(c.bucket_id);
11395 if (!bucket || bucket->size() == 0) {
11396 return error::kInvalidArguments;
11398 std::string feature_str;
11399 if (!bucket->GetAsString(&feature_str)) {
11400 return error::kInvalidArguments;
11403 bool desire_standard_derivatives = false;
11404 bool desire_frag_depth = false;
11405 bool desire_draw_buffers = false;
11406 bool desire_shader_texture_lod = false;
11407 if (IsWebGLContext()) {
11408 desire_standard_derivatives =
11409 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
11410 desire_frag_depth =
11411 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
11412 desire_draw_buffers =
11413 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
11414 desire_shader_texture_lod =
11415 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
11418 if (desire_standard_derivatives != derivatives_explicitly_enabled_ ||
11419 desire_frag_depth != frag_depth_explicitly_enabled_ ||
11420 desire_draw_buffers != draw_buffers_explicitly_enabled_ ||
11421 desire_shader_texture_lod != shader_texture_lod_explicitly_enabled_) {
11422 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
11423 frag_depth_explicitly_enabled_ |= desire_frag_depth;
11424 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
11425 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
11426 InitializeShaderTranslator();
11429 UpdateCapabilities();
11431 return error::kNoError;
11434 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11435 uint32 immediate_data_size,
11436 const void* cmd_data) {
11437 const gles2::cmds::GetProgramInfoCHROMIUM& c =
11438 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
11439 GLuint program_id = static_cast<GLuint>(c.program);
11440 uint32 bucket_id = c.bucket_id;
11441 Bucket* bucket = CreateBucket(bucket_id);
11442 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
11443 Program* program = NULL;
11444 program = GetProgram(program_id);
11445 if (!program || !program->IsValid()) {
11446 return error::kNoError;
11448 program->GetProgramInfo(program_manager(), bucket);
11449 return error::kNoError;
11452 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11453 uint32 immediate_data_size, const void* cmd_data) {
11454 if (!unsafe_es3_apis_enabled())
11455 return error::kUnknownCommand;
11456 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
11457 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
11458 GLuint program_id = static_cast<GLuint>(c.program);
11459 uint32 bucket_id = c.bucket_id;
11460 Bucket* bucket = CreateBucket(bucket_id);
11461 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
11462 Program* program = NULL;
11463 program = GetProgram(program_id);
11464 if (!program || !program->IsValid()) {
11465 return error::kNoError;
11467 program->GetUniformBlocks(bucket);
11468 return error::kNoError;
11471 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11472 uint32 immediate_data_size, const void* cmd_data) {
11473 if (!unsafe_es3_apis_enabled())
11474 return error::kUnknownCommand;
11475 const gles2::cmds::GetUniformsES3CHROMIUM& c =
11476 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
11477 GLuint program_id = static_cast<GLuint>(c.program);
11478 uint32 bucket_id = c.bucket_id;
11479 Bucket* bucket = CreateBucket(bucket_id);
11480 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
11481 Program* program = NULL;
11482 program = GetProgram(program_id);
11483 if (!program || !program->IsValid()) {
11484 return error::kNoError;
11486 program->GetUniformsES3(bucket);
11487 return error::kNoError;
11490 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11491 uint32 immediate_data_size,
11492 const void* cmd_data) {
11493 if (!unsafe_es3_apis_enabled())
11494 return error::kUnknownCommand;
11495 const gles2::cmds::GetTransformFeedbackVarying& c =
11496 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
11497 GLuint program_id = c.program;
11498 GLuint index = c.index;
11499 uint32 name_bucket_id = c.name_bucket_id;
11500 typedef cmds::GetTransformFeedbackVarying::Result Result;
11501 Result* result = GetSharedMemoryAs<Result*>(
11502 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11503 if (!result) {
11504 return error::kOutOfBounds;
11506 // Check that the client initialized the result.
11507 if (result->success != 0) {
11508 return error::kInvalidArguments;
11510 Program* program = GetProgramInfoNotShader(
11511 program_id, "glGetTransformFeedbackVarying");
11512 if (!program) {
11513 return error::kNoError;
11515 GLuint service_id = program->service_id();
11516 GLint link_status = GL_FALSE;
11517 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11518 if (link_status != GL_TRUE) {
11519 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11520 "glGetTransformFeedbackVarying", "program not linked");
11521 return error::kNoError;
11523 GLint max_length = 0;
11524 glGetProgramiv(
11525 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
11526 max_length = std::max(1, max_length);
11527 std::vector<char> buffer(max_length);
11528 GLsizei length = 0;
11529 GLsizei size = 0;
11530 GLenum type = 0;
11531 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11532 glGetTransformFeedbackVarying(
11533 service_id, index, max_length, &length, &size, &type, &buffer[0]);
11534 GLenum error = glGetError();
11535 if (error != GL_NO_ERROR) {
11536 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
11537 return error::kNoError;
11539 result->success = 1; // true.
11540 result->size = static_cast<int32_t>(size);
11541 result->type = static_cast<uint32_t>(type);
11542 Bucket* bucket = CreateBucket(name_bucket_id);
11543 DCHECK(length >= 0 && length < max_length);
11544 buffer[length] = '\0'; // Just to be safe.
11545 bucket->SetFromString(&buffer[0]);
11546 return error::kNoError;
11549 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11550 uint32 immediate_data_size, const void* cmd_data) {
11551 if (!unsafe_es3_apis_enabled())
11552 return error::kUnknownCommand;
11553 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
11554 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
11555 cmd_data);
11556 GLuint program_id = static_cast<GLuint>(c.program);
11557 uint32 bucket_id = c.bucket_id;
11558 Bucket* bucket = CreateBucket(bucket_id);
11559 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
11560 Program* program = NULL;
11561 program = GetProgram(program_id);
11562 if (!program || !program->IsValid()) {
11563 return error::kNoError;
11565 program->GetTransformFeedbackVaryings(bucket);
11566 return error::kNoError;
11569 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
11570 return context_lost_reason_;
11573 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11574 GLenum reset_status) const {
11575 switch (reset_status) {
11576 case GL_NO_ERROR:
11577 // TODO(kbr): improve the precision of the error code in this case.
11578 // Consider delegating to context for error code if MakeCurrent fails.
11579 return error::kUnknown;
11580 case GL_GUILTY_CONTEXT_RESET_ARB:
11581 return error::kGuilty;
11582 case GL_INNOCENT_CONTEXT_RESET_ARB:
11583 return error::kInnocent;
11584 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11585 return error::kUnknown;
11588 NOTREACHED();
11589 return error::kUnknown;
11592 bool GLES2DecoderImpl::WasContextLost() const {
11593 return context_was_lost_;
11596 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11597 return WasContextLost() && reset_by_robustness_extension_;
11600 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
11601 // Only lose the context once.
11602 if (WasContextLost())
11603 return;
11605 // Don't make GL calls in here, the context might not be current.
11606 context_lost_reason_ = reason;
11607 current_decoder_error_ = error::kLostContext;
11608 context_was_lost_ = true;
11611 bool GLES2DecoderImpl::CheckResetStatus() {
11612 DCHECK(!WasContextLost());
11613 DCHECK(context_->IsCurrent(NULL));
11615 if (IsRobustnessSupported()) {
11616 // If the reason for the call was a GL error, we can try to determine the
11617 // reset status more accurately.
11618 GLenum driver_status = glGetGraphicsResetStatusARB();
11619 if (driver_status == GL_NO_ERROR)
11620 return false;
11622 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
11623 << " context lost via ARB/EXT_robustness. Reset status = "
11624 << GLES2Util::GetStringEnum(driver_status);
11626 // Don't pretend we know which client was responsible.
11627 if (workarounds().use_virtualized_gl_contexts)
11628 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
11630 switch (driver_status) {
11631 case GL_GUILTY_CONTEXT_RESET_ARB:
11632 MarkContextLost(error::kGuilty);
11633 break;
11634 case GL_INNOCENT_CONTEXT_RESET_ARB:
11635 MarkContextLost(error::kInnocent);
11636 break;
11637 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11638 MarkContextLost(error::kUnknown);
11639 break;
11640 default:
11641 NOTREACHED();
11642 return false;
11644 reset_by_robustness_extension_ = true;
11645 return true;
11647 return false;
11650 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11651 uint32 immediate_data_size,
11652 const void* cmd_data) {
11653 return error::kUnknownCommand;
11656 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11657 uint32 immediate_data_size,
11658 const void* cmd_data) {
11659 const gles2::cmds::WaitSyncPointCHROMIUM& c =
11660 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
11661 uint32 sync_point = c.sync_point;
11662 if (wait_sync_point_callback_.is_null())
11663 return error::kNoError;
11665 return wait_sync_point_callback_.Run(sync_point) ?
11666 error::kNoError : error::kDeferCommandUntilLater;
11669 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11670 uint32 immediate_data_size,
11671 const void* cmd_data) {
11672 if (surface_->DeferDraws())
11673 return error::kDeferCommandUntilLater;
11674 if (!surface_->SetBackbufferAllocation(false))
11675 return error::kLostContext;
11676 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
11677 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
11678 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
11679 return error::kNoError;
11682 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11683 GLsizei n, const GLuint* client_ids) {
11684 for (GLsizei ii = 0; ii < n; ++ii) {
11685 if (query_manager_->GetQuery(client_ids[ii])) {
11686 return false;
11689 query_manager_->GenQueries(n, client_ids);
11690 return true;
11693 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11694 GLsizei n, const GLuint* client_ids) {
11695 for (GLsizei ii = 0; ii < n; ++ii) {
11696 query_manager_->RemoveQuery(client_ids[ii]);
11700 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
11701 if (query_manager_.get() == NULL) {
11702 return false;
11704 if (!query_manager_->ProcessPendingQueries(did_finish)) {
11705 current_decoder_error_ = error::kOutOfBounds;
11707 return query_manager_->HavePendingQueries();
11710 // Note that if there are no pending readpixels right now,
11711 // this function will call the callback immediately.
11712 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
11713 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
11714 pending_readpixel_fences_.back()->callbacks.push_back(callback);
11715 } else {
11716 callback.Run();
11720 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish) {
11721 // Note: |did_finish| guarantees that the GPU has passed the fence but
11722 // we cannot assume that GLFence::HasCompleted() will return true yet as
11723 // that's not guaranteed by all GLFence implementations.
11724 while (!pending_readpixel_fences_.empty() &&
11725 (did_finish ||
11726 pending_readpixel_fences_.front()->fence->HasCompleted())) {
11727 std::vector<base::Closure> callbacks =
11728 pending_readpixel_fences_.front()->callbacks;
11729 pending_readpixel_fences_.pop();
11730 for (size_t i = 0; i < callbacks.size(); i++) {
11731 callbacks[i].Run();
11736 bool GLES2DecoderImpl::HasMoreIdleWork() {
11737 return !pending_readpixel_fences_.empty() ||
11738 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
11741 void GLES2DecoderImpl::PerformIdleWork() {
11742 ProcessPendingReadPixels(false);
11743 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
11744 return;
11745 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
11746 ProcessFinishedAsyncTransfers();
11749 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
11750 const void* cmd_data) {
11751 const gles2::cmds::BeginQueryEXT& c =
11752 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
11753 GLenum target = static_cast<GLenum>(c.target);
11754 GLuint client_id = static_cast<GLuint>(c.id);
11755 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11756 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11758 switch (target) {
11759 case GL_COMMANDS_ISSUED_CHROMIUM:
11760 case GL_LATENCY_QUERY_CHROMIUM:
11761 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
11762 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
11763 case GL_GET_ERROR_QUERY_CHROMIUM:
11764 break;
11765 case GL_COMMANDS_COMPLETED_CHROMIUM:
11766 if (!features().chromium_sync_query) {
11767 LOCAL_SET_GL_ERROR(
11768 GL_INVALID_OPERATION, "glBeginQueryEXT",
11769 "not enabled for commands completed queries");
11770 return error::kNoError;
11772 break;
11773 case GL_SAMPLES_PASSED:
11774 case GL_ANY_SAMPLES_PASSED:
11775 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
11776 if (!features().occlusion_query_boolean) {
11777 LOCAL_SET_GL_ERROR(
11778 GL_INVALID_OPERATION, "glBeginQueryEXT",
11779 "not enabled for occlusion queries");
11780 return error::kNoError;
11782 break;
11783 case GL_TIME_ELAPSED:
11784 if (!query_manager_->GPUTimingAvailable()) {
11785 LOCAL_SET_GL_ERROR(
11786 GL_INVALID_OPERATION, "glBeginQueryEXT",
11787 "not enabled for timing queries");
11788 return error::kNoError;
11790 break;
11791 default:
11792 LOCAL_SET_GL_ERROR(
11793 GL_INVALID_ENUM, "glBeginQueryEXT",
11794 "unknown query target");
11795 return error::kNoError;
11798 if (query_manager_->GetActiveQuery(target)) {
11799 LOCAL_SET_GL_ERROR(
11800 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
11801 return error::kNoError;
11804 if (client_id == 0) {
11805 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
11806 return error::kNoError;
11809 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11810 if (!query) {
11811 if (!query_manager_->IsValidQuery(client_id)) {
11812 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11813 "glBeginQueryEXT",
11814 "id not made by glGenQueriesEXT");
11815 return error::kNoError;
11817 query = query_manager_->CreateQuery(
11818 target, client_id, sync_shm_id, sync_shm_offset);
11821 if (query->target() != target) {
11822 LOCAL_SET_GL_ERROR(
11823 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
11824 return error::kNoError;
11825 } else if (query->shm_id() != sync_shm_id ||
11826 query->shm_offset() != sync_shm_offset) {
11827 DLOG(ERROR) << "Shared memory used by query not the same as before";
11828 return error::kInvalidArguments;
11831 if (!query_manager_->BeginQuery(query)) {
11832 return error::kOutOfBounds;
11835 return error::kNoError;
11838 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
11839 const void* cmd_data) {
11840 const gles2::cmds::EndQueryEXT& c =
11841 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
11842 GLenum target = static_cast<GLenum>(c.target);
11843 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11845 QueryManager::Query* query = query_manager_->GetActiveQuery(target);
11846 if (!query) {
11847 LOCAL_SET_GL_ERROR(
11848 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
11849 return error::kNoError;
11852 if (!query_manager_->EndQuery(query, submit_count)) {
11853 return error::kOutOfBounds;
11856 query_manager_->ProcessPendingTransferQueries();
11858 return error::kNoError;
11861 error::Error GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size,
11862 const void* cmd_data) {
11863 const gles2::cmds::QueryCounterEXT& c =
11864 *static_cast<const gles2::cmds::QueryCounterEXT*>(cmd_data);
11865 GLuint client_id = static_cast<GLuint>(c.id);
11866 GLenum target = static_cast<GLenum>(c.target);
11867 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11868 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11869 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11871 switch (target) {
11872 case GL_TIMESTAMP:
11873 if (!query_manager_->GPUTimingAvailable()) {
11874 LOCAL_SET_GL_ERROR(
11875 GL_INVALID_OPERATION, "glQueryCounterEXT",
11876 "not enabled for timing queries");
11877 return error::kNoError;
11879 break;
11880 default:
11881 LOCAL_SET_GL_ERROR(
11882 GL_INVALID_ENUM, "glQueryCounterEXT",
11883 "unknown query target");
11884 return error::kNoError;
11887 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11888 if (!query) {
11889 if (!query_manager_->IsValidQuery(client_id)) {
11890 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11891 "glQueryCounterEXT",
11892 "id not made by glGenQueriesEXT");
11893 return error::kNoError;
11895 query = query_manager_->CreateQuery(
11896 target, client_id, sync_shm_id, sync_shm_offset);
11898 if (!query_manager_->QueryCounter(query, submit_count)) {
11899 return error::kOutOfBounds;
11902 return error::kNoError;
11905 error::Error GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
11906 uint32 immediate_data_size, const void* cmd_data) {
11907 const gles2::cmds::SetDisjointValueSyncCHROMIUM& c =
11908 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM*>(cmd_data);
11909 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11910 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11912 query_manager_->SetDisjointSync(sync_shm_id, sync_shm_offset);
11913 return error::kNoError;
11916 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11917 GLsizei n, const GLuint* client_ids) {
11918 for (GLsizei ii = 0; ii < n; ++ii) {
11919 if (GetVertexAttribManager(client_ids[ii])) {
11920 return false;
11924 if (!features().native_vertex_array_object) {
11925 // Emulated VAO
11926 for (GLsizei ii = 0; ii < n; ++ii) {
11927 CreateVertexAttribManager(client_ids[ii], 0, true);
11929 } else {
11930 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11932 glGenVertexArraysOES(n, service_ids.get());
11933 for (GLsizei ii = 0; ii < n; ++ii) {
11934 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
11938 return true;
11941 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11942 GLsizei n, const GLuint* client_ids) {
11943 for (GLsizei ii = 0; ii < n; ++ii) {
11944 VertexAttribManager* vao =
11945 GetVertexAttribManager(client_ids[ii]);
11946 if (vao && !vao->IsDeleted()) {
11947 if (state_.vertex_attrib_manager.get() == vao) {
11948 DoBindVertexArrayOES(0);
11950 RemoveVertexAttribManager(client_ids[ii]);
11955 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
11956 VertexAttribManager* vao = NULL;
11957 if (client_id != 0) {
11958 vao = GetVertexAttribManager(client_id);
11959 if (!vao) {
11960 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11961 // only allows names that have been previously generated. As such, we do
11962 // not generate new names here.
11963 LOCAL_SET_GL_ERROR(
11964 GL_INVALID_OPERATION,
11965 "glBindVertexArrayOES", "bad vertex array id.");
11966 current_decoder_error_ = error::kNoError;
11967 return;
11969 } else {
11970 vao = state_.default_vertex_attrib_manager.get();
11973 // Only set the VAO state if it's changed
11974 if (state_.vertex_attrib_manager.get() != vao) {
11975 state_.vertex_attrib_manager = vao;
11976 if (!features().native_vertex_array_object) {
11977 EmulateVertexArrayState();
11978 } else {
11979 GLuint service_id = vao->service_id();
11980 glBindVertexArrayOES(service_id);
11985 // Used when OES_vertex_array_object isn't natively supported
11986 void GLES2DecoderImpl::EmulateVertexArrayState() {
11987 // Setup the Vertex attribute state
11988 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
11989 RestoreStateForAttrib(vv, true);
11992 // Setup the element buffer
11993 Buffer* element_array_buffer =
11994 state_.vertex_attrib_manager->element_array_buffer();
11995 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
11996 element_array_buffer ? element_array_buffer->service_id() : 0);
11999 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
12000 const VertexAttribManager* vao =
12001 GetVertexAttribManager(client_id);
12002 return vao && vao->IsValid() && !vao->IsDeleted();
12005 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id) {
12006 GLuint service_id = 0;
12007 return path_manager()->GetPath(client_id, &service_id) &&
12008 glIsPathNV(service_id) == GL_TRUE;
12011 #if defined(OS_MACOSX)
12012 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
12013 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
12014 texture_id);
12015 if (it != texture_to_io_surface_map_.end()) {
12016 // Found a previous IOSurface bound to this texture; release it.
12017 IOSurfaceRef surface = it->second;
12018 CFRelease(surface);
12019 texture_to_io_surface_map_.erase(it);
12022 #endif
12024 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12025 GLenum target, GLsizei width, GLsizei height,
12026 GLuint io_surface_id, GLuint plane) {
12027 #if defined(OS_MACOSX)
12028 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
12029 LOCAL_SET_GL_ERROR(
12030 GL_INVALID_OPERATION,
12031 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12032 return;
12035 if (target != GL_TEXTURE_RECTANGLE_ARB) {
12036 // This might be supported in the future, and if we could require
12037 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12038 // could delete a lot of code. For now, perform strict validation so we
12039 // know what's going on.
12040 LOCAL_SET_GL_ERROR(
12041 GL_INVALID_OPERATION,
12042 "glTexImageIOSurface2DCHROMIUM",
12043 "requires TEXTURE_RECTANGLE_ARB target");
12044 return;
12047 // Default target might be conceptually valid, but disallow it to avoid
12048 // accidents.
12049 TextureRef* texture_ref =
12050 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12051 if (!texture_ref) {
12052 LOCAL_SET_GL_ERROR(
12053 GL_INVALID_OPERATION,
12054 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12055 return;
12058 // Look up the new IOSurface. Note that because of asynchrony
12059 // between processes this might fail; during live resizing the
12060 // plugin process might allocate and release an IOSurface before
12061 // this process gets a chance to look it up. Hold on to any old
12062 // IOSurface in this case.
12063 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
12064 if (!surface) {
12065 LOCAL_SET_GL_ERROR(
12066 GL_INVALID_OPERATION,
12067 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12068 return;
12071 // Release any IOSurface previously bound to this texture.
12072 ReleaseIOSurfaceForTexture(texture_ref->service_id());
12074 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12075 texture_to_io_surface_map_.insert(
12076 std::make_pair(texture_ref->service_id(), surface));
12078 CGLContextObj context =
12079 static_cast<CGLContextObj>(context_->GetHandle());
12081 CGLError err = CGLTexImageIOSurface2D(
12082 context,
12083 target,
12084 GL_RGBA,
12085 width,
12086 height,
12087 GL_BGRA,
12088 GL_UNSIGNED_INT_8_8_8_8_REV,
12089 surface,
12090 plane);
12092 if (err != kCGLNoError) {
12093 LOCAL_SET_GL_ERROR(
12094 GL_INVALID_OPERATION,
12095 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12096 return;
12099 texture_manager()->SetLevelInfo(
12100 texture_ref, target, 0, GL_RGBA, width, height, 1, 0, GL_BGRA,
12101 GL_UNSIGNED_INT_8_8_8_8_REV, gfx::Rect(width, height));
12103 #else
12104 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12105 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12106 #endif
12109 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
12110 switch (internalformat) {
12111 case GL_R8:
12112 case GL_R8_SNORM:
12113 case GL_R16F:
12114 case GL_R32F:
12115 return GL_RED;
12116 case GL_R8UI:
12117 case GL_R8I:
12118 case GL_R16UI:
12119 case GL_R16I:
12120 case GL_R32UI:
12121 case GL_R32I:
12122 return GL_RED_INTEGER;
12123 case GL_RG8:
12124 case GL_RG8_SNORM:
12125 case GL_RG16F:
12126 case GL_RG32F:
12127 return GL_RG;
12128 case GL_RG8UI:
12129 case GL_RG8I:
12130 case GL_RG16UI:
12131 case GL_RG16I:
12132 case GL_RG32UI:
12133 case GL_RG32I:
12134 return GL_RG_INTEGER;
12135 case GL_ATC_RGB_AMD:
12136 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
12137 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
12138 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
12139 case GL_ETC1_RGB8_OES:
12140 case GL_RGB8:
12141 case GL_R11F_G11F_B10F:
12142 case GL_RGB565:
12143 case GL_RGB8_SNORM:
12144 case GL_RGB9_E5:
12145 case GL_RGB16F:
12146 case GL_RGB32F:
12147 return GL_RGB;
12148 case GL_RGB8UI:
12149 case GL_RGB8I:
12150 case GL_RGB16UI:
12151 case GL_RGB16I:
12152 case GL_RGB32UI:
12153 case GL_RGB32I:
12154 return GL_RGB_INTEGER;
12155 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
12156 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
12157 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
12158 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
12159 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
12160 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
12161 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
12162 case GL_RGBA8:
12163 case GL_SRGB8_ALPHA8:
12164 case GL_RGBA8_SNORM:
12165 case GL_RGBA4:
12166 case GL_RGB5_A1:
12167 case GL_RGB10_A2:
12168 case GL_RGBA16F:
12169 case GL_RGBA32F:
12170 return GL_RGBA;
12171 case GL_RGBA8UI:
12172 case GL_RGBA8I:
12173 case GL_RGB10_A2UI:
12174 case GL_RGBA16UI:
12175 case GL_RGBA16I:
12176 case GL_RGBA32UI:
12177 case GL_RGBA32I:
12178 return GL_RGBA_INTEGER;
12179 case GL_DEPTH_COMPONENT16:
12180 case GL_DEPTH_COMPONENT24:
12181 case GL_DEPTH_COMPONENT32F:
12182 return GL_DEPTH_COMPONENT;
12183 case GL_DEPTH24_STENCIL8:
12184 case GL_DEPTH32F_STENCIL8:
12185 return GL_DEPTH_STENCIL;
12186 case GL_LUMINANCE8_ALPHA8_EXT:
12187 return GL_LUMINANCE_ALPHA;
12188 case GL_LUMINANCE8_EXT:
12189 return GL_LUMINANCE;
12190 case GL_ALPHA8_EXT:
12191 return GL_ALPHA;
12192 case GL_ALPHA32F_EXT:
12193 return GL_ALPHA;
12194 case GL_LUMINANCE32F_EXT:
12195 return GL_LUMINANCE;
12196 case GL_LUMINANCE_ALPHA32F_EXT:
12197 return GL_LUMINANCE_ALPHA;
12198 case GL_ALPHA16F_EXT:
12199 return GL_ALPHA;
12200 case GL_LUMINANCE16F_EXT:
12201 return GL_LUMINANCE;
12202 case GL_LUMINANCE_ALPHA16F_EXT:
12203 return GL_LUMINANCE_ALPHA;
12204 case GL_BGRA8_EXT:
12205 return GL_BGRA_EXT;
12206 default:
12207 return GL_NONE;
12211 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12212 const char* function_name,
12213 GLenum target,
12214 TextureRef* source_texture_ref,
12215 TextureRef* dest_texture_ref,
12216 GLenum dest_internal_format) {
12217 if (!source_texture_ref || !dest_texture_ref) {
12218 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12219 return false;
12222 if (GL_TEXTURE_2D != target) {
12223 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12224 "invalid texture target");
12225 return false;
12228 Texture* source_texture = source_texture_ref->texture();
12229 Texture* dest_texture = dest_texture_ref->texture();
12230 if (source_texture == dest_texture) {
12231 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12232 "source and destination textures are the same");
12233 return false;
12236 if (dest_texture->target() != GL_TEXTURE_2D ||
12237 (source_texture->target() != GL_TEXTURE_2D &&
12238 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12239 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12240 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12241 "invalid texture target binding");
12242 return false;
12245 GLenum source_type = 0;
12246 GLenum source_internal_format = 0;
12247 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12248 &source_internal_format);
12250 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12251 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12252 // renderable on some platforms.
12253 bool valid_dest_format = dest_internal_format == GL_RGB ||
12254 dest_internal_format == GL_RGBA ||
12255 dest_internal_format == GL_BGRA_EXT;
12256 bool valid_source_format =
12257 source_internal_format == GL_R8 || source_internal_format == GL_ALPHA ||
12258 source_internal_format == GL_RGB || source_internal_format == GL_RGBA ||
12259 source_internal_format == GL_LUMINANCE ||
12260 source_internal_format == GL_LUMINANCE_ALPHA ||
12261 source_internal_format == GL_BGRA_EXT;
12262 if (!valid_source_format || !valid_dest_format) {
12263 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12264 "invalid internal format");
12265 return false;
12267 return true;
12270 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12271 const char* function_name,
12272 GLenum target,
12273 TextureRef* source_texture_ref,
12274 TextureRef* dest_texture_ref) {
12275 if (!source_texture_ref || !dest_texture_ref) {
12276 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12277 return false;
12280 if (GL_TEXTURE_2D != target) {
12281 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12282 "invalid texture target");
12283 return false;
12286 Texture* source_texture = source_texture_ref->texture();
12287 Texture* dest_texture = dest_texture_ref->texture();
12288 if (source_texture == dest_texture) {
12289 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12290 "source and destination textures are the same");
12291 return false;
12294 if (dest_texture->target() != GL_TEXTURE_2D ||
12295 (source_texture->target() != GL_TEXTURE_2D &&
12296 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12297 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12298 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12299 "invalid texture target binding");
12300 return false;
12303 GLenum source_type = 0;
12304 GLenum source_internal_format = 0;
12305 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12306 &source_internal_format);
12308 bool valid_format =
12309 source_internal_format == GL_ATC_RGB_AMD ||
12310 source_internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD ||
12311 source_internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
12312 source_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ||
12313 source_internal_format == GL_ETC1_RGB8_OES;
12315 if (!valid_format) {
12316 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12317 "invalid internal format");
12318 return false;
12321 return true;
12324 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12325 GLenum target,
12326 GLuint source_id,
12327 GLuint dest_id,
12328 GLenum internal_format,
12329 GLenum dest_type,
12330 GLboolean unpack_flip_y,
12331 GLboolean unpack_premultiply_alpha,
12332 GLboolean unpack_unmultiply_alpha) {
12333 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12335 TextureRef* source_texture_ref = GetTexture(source_id);
12336 TextureRef* dest_texture_ref = GetTexture(dest_id);
12337 Texture* source_texture = source_texture_ref->texture();
12338 Texture* dest_texture = dest_texture_ref->texture();
12339 int source_width = 0;
12340 int source_height = 0;
12341 gfx::GLImage* image =
12342 source_texture->GetLevelImage(source_texture->target(), 0);
12343 if (image) {
12344 gfx::Size size = image->GetSize();
12345 source_width = size.width();
12346 source_height = size.height();
12347 if (source_width <= 0 || source_height <= 0) {
12348 LOCAL_SET_GL_ERROR(
12349 GL_INVALID_VALUE,
12350 "glCopyTextureChromium", "invalid image size");
12351 return;
12353 } else {
12354 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12355 &source_width, &source_height, nullptr)) {
12356 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12357 "glCopyTextureChromium",
12358 "source texture has no level 0");
12359 return;
12362 // Check that this type of texture is allowed.
12363 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12364 source_width, source_height, 1)) {
12365 LOCAL_SET_GL_ERROR(
12366 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
12367 return;
12371 GLenum source_type = 0;
12372 GLenum source_internal_format = 0;
12373 source_texture->GetLevelType(
12374 source_texture->target(), 0, &source_type, &source_internal_format);
12376 if (dest_texture->IsImmutable()) {
12377 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
12378 "texture is immutable");
12379 return;
12382 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
12383 source_texture_ref, dest_texture_ref,
12384 internal_format)) {
12385 return;
12388 // Clear the source texture if necessary.
12389 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12390 source_texture->target(), 0)) {
12391 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
12392 "dimensions too big");
12393 return;
12396 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12397 // needed because it takes 10s of milliseconds to initialize.
12398 if (!copy_texture_CHROMIUM_.get()) {
12399 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12400 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12401 copy_texture_CHROMIUM_->Initialize(this);
12402 RestoreCurrentFramebufferBindings();
12403 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12404 return;
12407 GLenum dest_type_previous = dest_type;
12408 GLenum dest_internal_format = internal_format;
12409 int dest_width = 0;
12410 int dest_height = 0;
12411 bool dest_level_defined = dest_texture->GetLevelSize(
12412 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12414 if (dest_level_defined) {
12415 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
12416 &dest_internal_format);
12419 // Resize the destination texture to the dimensions of the source texture.
12420 if (!dest_level_defined || dest_width != source_width ||
12421 dest_height != source_height ||
12422 dest_internal_format != internal_format ||
12423 dest_type_previous != dest_type) {
12424 // Ensure that the glTexImage2D succeeds.
12425 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12426 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12427 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
12428 0, internal_format, dest_type, NULL);
12429 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12430 if (error != GL_NO_ERROR) {
12431 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12432 return;
12435 texture_manager()->SetLevelInfo(
12436 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
12437 source_height, 1, 0, internal_format, dest_type,
12438 gfx::Rect(source_width, source_height));
12439 } else {
12440 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12441 true);
12444 ScopedModifyPixels modify(dest_texture_ref);
12446 // Try using GLImage::CopyTexSubImage when possible.
12447 bool unpack_premultiply_alpha_change =
12448 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12449 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12450 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12451 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12452 gfx::Rect(0, 0, source_width, source_height))) {
12453 return;
12457 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12459 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12460 // before presenting.
12461 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12462 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12463 // instead of using kIdentityMatrix crbug.com/226218.
12464 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12465 this, source_texture->target(), source_texture->service_id(),
12466 dest_texture->service_id(), source_width, source_height,
12467 unpack_flip_y == GL_TRUE,
12468 unpack_premultiply_alpha == GL_TRUE,
12469 unpack_unmultiply_alpha == GL_TRUE,
12470 kIdentityMatrix);
12471 } else {
12472 copy_texture_CHROMIUM_->DoCopyTexture(
12473 this, source_texture->target(), source_texture->service_id(),
12474 source_internal_format, dest_texture->service_id(), internal_format,
12475 source_width, source_height,
12476 unpack_flip_y == GL_TRUE,
12477 unpack_premultiply_alpha == GL_TRUE,
12478 unpack_unmultiply_alpha == GL_TRUE);
12481 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12484 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12485 GLenum target,
12486 GLuint source_id,
12487 GLuint dest_id,
12488 GLint xoffset,
12489 GLint yoffset,
12490 GLint x,
12491 GLint y,
12492 GLsizei width,
12493 GLsizei height,
12494 GLboolean unpack_flip_y,
12495 GLboolean unpack_premultiply_alpha,
12496 GLboolean unpack_unmultiply_alpha) {
12497 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12499 TextureRef* source_texture_ref = GetTexture(source_id);
12500 TextureRef* dest_texture_ref = GetTexture(dest_id);
12501 Texture* source_texture = source_texture_ref->texture();
12502 Texture* dest_texture = dest_texture_ref->texture();
12503 int source_width = 0;
12504 int source_height = 0;
12505 gfx::GLImage* image =
12506 source_texture->GetLevelImage(source_texture->target(), 0);
12507 if (image) {
12508 gfx::Size size = image->GetSize();
12509 source_width = size.width();
12510 source_height = size.height();
12511 if (source_width <= 0 || source_height <= 0) {
12512 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12513 "invalid image size");
12514 return;
12516 } else {
12517 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12518 &source_width, &source_height, nullptr)) {
12519 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12520 "source texture has no level 0");
12521 return;
12524 // Check that this type of texture is allowed.
12525 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12526 source_width, source_height, 1)) {
12527 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12528 "source texture bad dimensions");
12529 return;
12533 GLenum source_type = 0;
12534 GLenum source_internal_format = 0;
12535 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12536 &source_internal_format);
12537 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12538 width, height, 1, source_type)) {
12539 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12540 "source texture bad dimensions.");
12541 return;
12544 GLenum dest_type = 0;
12545 GLenum dest_internal_format = 0;
12546 bool dest_level_defined = dest_texture->GetLevelType(
12547 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12548 if (!dest_level_defined) {
12549 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
12550 "destination texture is not defined");
12551 return;
12553 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12554 yoffset, 0, width, height, 1, dest_type)) {
12555 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12556 "destination texture bad dimensions.");
12557 return;
12560 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
12561 source_texture_ref, dest_texture_ref,
12562 dest_internal_format)) {
12563 return;
12566 // Clear the source texture if necessary.
12567 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12568 source_texture->target(), 0)) {
12569 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12570 "source texture dimensions too big");
12571 return;
12574 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12575 // needed because it takes 10s of milliseconds to initialize.
12576 if (!copy_texture_CHROMIUM_.get()) {
12577 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12578 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12579 copy_texture_CHROMIUM_->Initialize(this);
12580 RestoreCurrentFramebufferBindings();
12581 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
12582 return;
12585 int dest_width = 0;
12586 int dest_height = 0;
12587 bool ok = dest_texture->GetLevelSize(
12588 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12589 DCHECK(ok);
12590 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12591 height != dest_height) {
12592 gfx::Rect cleared_rect;
12593 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
12594 gfx::Rect(xoffset, yoffset, width, height),
12595 &cleared_rect)) {
12596 DCHECK_GE(cleared_rect.size().GetArea(),
12597 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
12598 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
12599 cleared_rect);
12600 } else {
12601 // Otherwise clear part of texture level that is not already cleared.
12602 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12603 0)) {
12604 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12605 "destination texture dimensions too big");
12606 return;
12609 } else {
12610 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12611 true);
12614 ScopedModifyPixels modify(dest_texture_ref);
12616 // Try using GLImage::CopyTexSubImage when possible.
12617 bool unpack_premultiply_alpha_change =
12618 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12619 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12620 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12621 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12622 gfx::Rect(x, y, width, height))) {
12623 return;
12627 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12629 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12630 // crbug.com/226218.
12631 copy_texture_CHROMIUM_->DoCopySubTexture(
12632 this, source_texture->target(), source_texture->service_id(),
12633 source_internal_format, dest_texture->service_id(), dest_internal_format,
12634 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
12635 source_width, source_height,
12636 unpack_flip_y == GL_TRUE,
12637 unpack_premultiply_alpha == GL_TRUE,
12638 unpack_unmultiply_alpha == GL_TRUE);
12640 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12643 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target,
12644 GLuint source_id,
12645 GLuint dest_id) {
12646 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12648 TextureRef* source_texture_ref = GetTexture(source_id);
12649 TextureRef* dest_texture_ref = GetTexture(dest_id);
12650 Texture* source_texture = source_texture_ref->texture();
12651 Texture* dest_texture = dest_texture_ref->texture();
12652 int source_width = 0;
12653 int source_height = 0;
12654 gfx::GLImage* image =
12655 source_texture->GetLevelImage(source_texture->target(), 0);
12656 if (image) {
12657 gfx::Size size = image->GetSize();
12658 source_width = size.width();
12659 source_height = size.height();
12660 if (source_width <= 0 || source_height <= 0) {
12661 LOCAL_SET_GL_ERROR(
12662 GL_INVALID_VALUE,
12663 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12664 return;
12666 } else {
12667 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12668 &source_width, &source_height, nullptr)) {
12669 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12670 "glCompressedCopyTextureCHROMIUM",
12671 "source texture has no level 0");
12672 return;
12675 // Check that this type of texture is allowed.
12676 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12677 source_width, source_height, 1)) {
12678 LOCAL_SET_GL_ERROR(
12679 GL_INVALID_VALUE, "glCompressedCopyTextureCHROMIUM",
12680 "Bad dimensions");
12681 return;
12685 GLenum source_type = 0;
12686 GLenum source_internal_format = 0;
12687 source_texture->GetLevelType(
12688 source_texture->target(), 0, &source_type, &source_internal_format);
12690 if (dest_texture->IsImmutable()) {
12691 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12692 "glCompressedCopyTextureCHROMIUM",
12693 "texture is immutable");
12694 return;
12697 if (!ValidateCompressedCopyTextureCHROMIUM(
12698 "glCompressedCopyTextureCHROMIUM",
12699 target,
12700 source_texture_ref, dest_texture_ref)) {
12701 return;
12704 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12705 // needed because it takes 10s of milliseconds to initialize.
12706 if (!copy_texture_CHROMIUM_.get()) {
12707 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12708 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12709 copy_texture_CHROMIUM_->Initialize(this);
12710 RestoreCurrentFramebufferBindings();
12711 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12712 return;
12715 // Clear the source texture if necessary.
12716 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12717 source_texture->target(), 0)) {
12718 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopyTextureCHROMIUM",
12719 "dimensions too big");
12720 return;
12723 ScopedTextureBinder binder(
12724 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
12726 ScopedModifyPixels modify(dest_texture_ref);
12728 // Try using GLImage::CopyTexImage when possible.
12729 if (image) {
12730 GLenum dest_type = 0;
12731 GLenum dest_internal_format = 0;
12732 int dest_width = 0;
12733 int dest_height = 0;
12734 bool dest_level_defined = dest_texture->GetLevelSize(
12735 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12737 if (dest_level_defined) {
12738 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
12739 &dest_internal_format);
12742 // Resize the destination texture to the dimensions of the source texture.
12743 if (!dest_level_defined || dest_width != source_width ||
12744 dest_height != source_height ||
12745 dest_internal_format != source_internal_format) {
12746 GLsizei source_size = 0;
12748 bool did_get_size = GetCompressedTexSizeInBytes(
12749 "glCompressedCopyTextureCHROMIUM", source_width, source_height,
12750 1, source_internal_format, &source_size);
12751 DCHECK(did_get_size);
12753 // Ensure that the glCompressedTexImage2D succeeds.
12754 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12755 glCompressedTexImage2D(GL_TEXTURE_2D, 0, source_internal_format,
12756 source_width, source_height, 0, source_size,
12757 NULL);
12758 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12759 if (error != GL_NO_ERROR) {
12760 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12761 return;
12764 texture_manager()->SetLevelInfo(
12765 dest_texture_ref, GL_TEXTURE_2D, 0, source_internal_format,
12766 source_width, source_height, 1, 0, source_internal_format,
12767 source_type, gfx::Rect(source_width, source_height));
12768 } else {
12769 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12770 true);
12773 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12774 gfx::Rect(0, 0, source_width, source_height))) {
12775 return;
12779 TRACE_EVENT0(
12780 "gpu",
12781 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12783 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12785 // As a fallback, copy into a non-compressed GL_RGBA texture.
12786 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12787 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height,
12788 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
12789 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12790 if (error != GL_NO_ERROR) {
12791 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12792 return;
12795 texture_manager()->SetLevelInfo(
12796 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, source_width,
12797 source_height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12798 gfx::Rect(source_width, source_height));
12800 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12801 // before presenting.
12802 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12803 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12804 // instead of using kIdentityMatrix crbug.com/226218.
12805 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12806 this, source_texture->target(), source_texture->service_id(),
12807 dest_texture->service_id(), source_width, source_height,
12808 false, false, false, kIdentityMatrix);
12809 } else {
12810 copy_texture_CHROMIUM_->DoCopyTexture(
12811 this, source_texture->target(), source_texture->service_id(),
12812 source_internal_format, dest_texture->service_id(), GL_RGBA,
12813 source_width, source_height, false, false, false);
12816 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12819 void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target,
12820 GLuint source_id,
12821 GLuint dest_id,
12822 GLint xoffset,
12823 GLint yoffset,
12824 GLint x,
12825 GLint y,
12826 GLsizei width,
12827 GLsizei height) {
12828 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM");
12830 TextureRef* source_texture_ref = GetTexture(source_id);
12831 TextureRef* dest_texture_ref = GetTexture(dest_id);
12832 Texture* source_texture = source_texture_ref->texture();
12833 Texture* dest_texture = dest_texture_ref->texture();
12834 int source_width = 0;
12835 int source_height = 0;
12836 gfx::GLImage* image =
12837 source_texture->GetLevelImage(source_texture->target(), 0);
12838 if (image) {
12839 gfx::Size size = image->GetSize();
12840 source_width = size.width();
12841 source_height = size.height();
12842 if (source_width <= 0 || source_height <= 0) {
12843 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12844 "invalid image size");
12845 return;
12847 } else {
12848 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12849 &source_width, &source_height, nullptr)) {
12850 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12851 "source texture has no level 0");
12852 return;
12855 // Check that this type of texture is allowed.
12856 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12857 source_width, source_height, 1)) {
12858 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12859 "source texture bad dimensions");
12860 return;
12864 GLenum source_type = 0;
12865 GLenum source_internal_format = 0;
12866 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12867 &source_internal_format);
12868 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12869 width, height, 1, source_type)) {
12870 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12871 "source texture bad dimensions.");
12872 return;
12875 GLenum dest_type = 0;
12876 GLenum dest_internal_format = 0;
12877 bool dest_level_defined = dest_texture->GetLevelType(
12878 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12879 if (!dest_level_defined) {
12880 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12881 "glCompressedCopySubTextureCHROMIUM",
12882 "destination texture is not defined");
12883 return;
12885 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12886 yoffset, 0, width, height, 1, dest_type)) {
12887 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12888 "destination texture bad dimensions.");
12889 return;
12892 if (!ValidateCompressedCopyTextureCHROMIUM(
12893 "glCompressedCopySubTextureCHROMIUM", target, source_texture_ref,
12894 dest_texture_ref)) {
12895 return;
12898 if (!ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
12899 source_texture->target(), 0, x, y, 0,
12900 width, height, 1,
12901 source_internal_format,
12902 source_texture) ||
12903 !ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
12904 dest_texture->target(), 0,
12905 xoffset, yoffset, 0, width, height, 1,
12906 dest_internal_format,
12907 dest_texture)) {
12908 return;
12911 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12912 // needed because it takes 10s of milliseconds to initialize.
12913 if (!copy_texture_CHROMIUM_.get()) {
12914 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopySubTextureCHROMIUM");
12915 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12916 copy_texture_CHROMIUM_->Initialize(this);
12917 RestoreCurrentFramebufferBindings();
12918 if (LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM") !=
12919 GL_NO_ERROR) {
12920 return;
12924 // Clear the source texture if necessary.
12925 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12926 source_texture->target(), 0)) {
12927 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopySubTextureCHROMIUM",
12928 "source texture dimensions too big");
12929 return;
12932 int dest_width = 0;
12933 int dest_height = 0;
12934 bool ok = dest_texture->GetLevelSize(
12935 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12936 DCHECK(ok);
12937 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12938 height != dest_height) {
12939 gfx::Rect cleared_rect;
12940 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
12941 gfx::Rect(xoffset, yoffset, width, height),
12942 &cleared_rect)) {
12943 DCHECK_GE(cleared_rect.size().GetArea(),
12944 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
12945 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
12946 cleared_rect);
12947 } else {
12948 // Otherwise clear part of texture level that is not already cleared.
12949 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12950 0)) {
12951 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY,
12952 "glCompressedCopySubTextureCHROMIUM",
12953 "destination texture dimensions too big");
12954 return;
12957 } else {
12958 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12959 true);
12962 ScopedTextureBinder binder(
12963 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
12965 ScopedModifyPixels modify(dest_texture_ref);
12967 // Try using GLImage::CopyTexSubImage when possible.
12968 if (image) {
12969 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12970 gfx::Rect(x, y, width, height))) {
12971 return;
12975 TRACE_EVENT0(
12976 "gpu",
12977 "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback");
12979 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12981 // As a fallback, copy into a non-compressed GL_RGBA texture.
12982 if (dest_internal_format != GL_RGBA) {
12983 // To preserve the contents of the original destination texture we must
12984 // first copy the original destination texture to a temporary storage, then
12985 // copy it back to the original destination texture.
12986 GLuint tmp_service_id;
12987 glGenTextures(1, &tmp_service_id);
12988 DCHECK_NE(0u, tmp_service_id);
12990 glBindTexture(GL_TEXTURE_2D, tmp_service_id);
12992 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12993 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA,
12994 GL_UNSIGNED_BYTE, NULL);
12995 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
12996 if (error != GL_NO_ERROR)
12997 return;
12999 copy_texture_CHROMIUM_->DoCopyTexture(
13000 this, dest_texture->target(), dest_texture->service_id(),
13001 dest_internal_format, tmp_service_id, GL_RGBA,
13002 dest_width, dest_height, false, false, false);
13004 // Redefine destination texture to use RGBA.
13005 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
13006 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13007 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA,
13008 GL_UNSIGNED_BYTE, NULL);
13009 error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13010 if (error != GL_NO_ERROR)
13011 return;
13013 texture_manager()->SetLevelInfo(
13014 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height,
13015 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(dest_width, dest_height));
13017 copy_texture_CHROMIUM_->DoCopyTexture(
13018 this, GL_TEXTURE_2D, tmp_service_id, GL_RGBA,
13019 dest_texture->service_id(), GL_RGBA,
13020 dest_width, dest_height, false, false, false);
13022 glDeleteTextures(1, &tmp_service_id);
13025 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13026 // crbug.com/226218.
13027 copy_texture_CHROMIUM_->DoCopySubTexture(
13028 this, source_texture->target(), source_texture->service_id(),
13029 source_internal_format, dest_texture->service_id(), GL_RGBA,
13030 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
13031 source_width, source_height, false, false, false);
13033 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13036 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
13037 switch (internalformat) {
13038 case GL_R8:
13039 return GL_UNSIGNED_BYTE;
13040 case GL_R8_SNORM:
13041 return GL_BYTE;
13042 case GL_R16F:
13043 return GL_HALF_FLOAT;
13044 case GL_R32F:
13045 return GL_FLOAT;
13046 case GL_R8UI:
13047 return GL_UNSIGNED_BYTE;
13048 case GL_R8I:
13049 return GL_BYTE;
13050 case GL_R16UI:
13051 return GL_UNSIGNED_SHORT;
13052 case GL_R16I:
13053 return GL_SHORT;
13054 case GL_R32UI:
13055 return GL_UNSIGNED_INT;
13056 case GL_R32I:
13057 return GL_INT;
13058 case GL_RG8:
13059 return GL_UNSIGNED_BYTE;
13060 case GL_RG8_SNORM:
13061 return GL_BYTE;
13062 case GL_RG16F:
13063 return GL_HALF_FLOAT;
13064 case GL_RG32F:
13065 return GL_FLOAT;
13066 case GL_RG8UI:
13067 return GL_UNSIGNED_BYTE;
13068 case GL_RG8I:
13069 return GL_BYTE;
13070 case GL_RG16UI:
13071 return GL_UNSIGNED_SHORT;
13072 case GL_RG16I:
13073 return GL_SHORT;
13074 case GL_RG32UI:
13075 return GL_UNSIGNED_INT;
13076 case GL_RG32I:
13077 return GL_INT;
13078 case GL_RGB8:
13079 case GL_SRGB8:
13080 return GL_UNSIGNED_BYTE;
13081 case GL_R11F_G11F_B10F:
13082 return GL_UNSIGNED_INT_10F_11F_11F_REV;
13083 case GL_RGB565:
13084 return GL_UNSIGNED_SHORT_5_6_5;
13085 case GL_RGB8_SNORM:
13086 return GL_BYTE;
13087 case GL_RGB9_E5:
13088 return GL_UNSIGNED_INT_5_9_9_9_REV;
13089 case GL_RGB16F:
13090 return GL_HALF_FLOAT;
13091 case GL_RGB32F:
13092 return GL_FLOAT;
13093 case GL_RGB8UI:
13094 return GL_UNSIGNED_BYTE;
13095 case GL_RGB8I:
13096 return GL_BYTE;
13097 case GL_RGB16UI:
13098 return GL_UNSIGNED_SHORT;
13099 case GL_RGB16I:
13100 return GL_SHORT;
13101 case GL_RGB32UI:
13102 return GL_UNSIGNED_INT;
13103 case GL_RGB32I:
13104 return GL_INT;
13105 case GL_RGBA8:
13106 return GL_UNSIGNED_BYTE;
13107 case GL_SRGB8_ALPHA8:
13108 return GL_UNSIGNED_BYTE;
13109 case GL_RGBA8_SNORM:
13110 return GL_BYTE;
13111 case GL_RGBA4:
13112 return GL_UNSIGNED_SHORT_4_4_4_4;
13113 case GL_RGB10_A2:
13114 return GL_UNSIGNED_INT_2_10_10_10_REV;
13115 case GL_RGB5_A1:
13116 return GL_UNSIGNED_SHORT_5_5_5_1;
13117 case GL_RGBA16F:
13118 return GL_HALF_FLOAT;
13119 case GL_RGBA32F:
13120 return GL_FLOAT;
13121 case GL_RGBA8UI:
13122 return GL_UNSIGNED_BYTE;
13123 case GL_RGBA8I:
13124 return GL_BYTE;
13125 case GL_RGB10_A2UI:
13126 return GL_UNSIGNED_INT_2_10_10_10_REV;
13127 case GL_RGBA16UI:
13128 return GL_UNSIGNED_SHORT;
13129 case GL_RGBA16I:
13130 return GL_SHORT;
13131 case GL_RGBA32I:
13132 return GL_INT;
13133 case GL_RGBA32UI:
13134 return GL_UNSIGNED_INT;
13135 case GL_DEPTH_COMPONENT16:
13136 return GL_UNSIGNED_SHORT;
13137 case GL_DEPTH_COMPONENT24:
13138 return GL_UNSIGNED_INT;
13139 case GL_DEPTH_COMPONENT32F:
13140 return GL_FLOAT;
13141 case GL_DEPTH24_STENCIL8:
13142 return GL_UNSIGNED_INT_24_8;
13143 case GL_DEPTH32F_STENCIL8:
13144 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
13145 case GL_LUMINANCE8_ALPHA8_EXT:
13146 return GL_UNSIGNED_BYTE;
13147 case GL_LUMINANCE8_EXT:
13148 return GL_UNSIGNED_BYTE;
13149 case GL_ALPHA8_EXT:
13150 return GL_UNSIGNED_BYTE;
13151 case GL_ALPHA32F_EXT:
13152 return GL_FLOAT;
13153 case GL_LUMINANCE32F_EXT:
13154 return GL_FLOAT;
13155 case GL_LUMINANCE_ALPHA32F_EXT:
13156 return GL_FLOAT;
13157 case GL_ALPHA16F_EXT:
13158 return GL_HALF_FLOAT_OES;
13159 case GL_LUMINANCE16F_EXT:
13160 return GL_HALF_FLOAT_OES;
13161 case GL_LUMINANCE_ALPHA16F_EXT:
13162 return GL_HALF_FLOAT_OES;
13163 case GL_BGRA8_EXT:
13164 return GL_UNSIGNED_BYTE;
13165 default:
13166 return GL_NONE;
13170 void GLES2DecoderImpl::DoTexStorage2DEXT(
13171 GLenum target,
13172 GLint levels,
13173 GLenum internal_format,
13174 GLsizei width,
13175 GLsizei height) {
13176 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
13177 "width", width, "height", height);
13178 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
13179 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
13180 LOCAL_SET_GL_ERROR(
13181 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
13182 return;
13184 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13185 &state_, target);
13186 if (!texture_ref) {
13187 LOCAL_SET_GL_ERROR(
13188 GL_INVALID_OPERATION,
13189 "glTexStorage2DEXT", "unknown texture for target");
13190 return;
13192 Texture* texture = texture_ref->texture();
13193 if (texture->IsAttachedToFramebuffer()) {
13194 framebuffer_state_.clear_state_dirty = true;
13196 if (texture->IsImmutable()) {
13197 LOCAL_SET_GL_ERROR(
13198 GL_INVALID_OPERATION,
13199 "glTexStorage2DEXT", "texture is immutable");
13200 return;
13203 GLenum format = ExtractFormatFromStorageFormat(internal_format);
13204 GLenum type = ExtractTypeFromStorageFormat(internal_format);
13207 GLsizei level_width = width;
13208 GLsizei level_height = height;
13209 uint32 estimated_size = 0;
13210 for (int ii = 0; ii < levels; ++ii) {
13211 uint32 level_size = 0;
13212 if (!GLES2Util::ComputeImageDataSizes(
13213 level_width, level_height, 1, format, type, state_.unpack_alignment,
13214 &estimated_size, NULL, NULL) ||
13215 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
13216 LOCAL_SET_GL_ERROR(
13217 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
13218 return;
13220 level_width = std::max(1, level_width >> 1);
13221 level_height = std::max(1, level_height >> 1);
13223 if (!EnsureGPUMemoryAvailable(estimated_size)) {
13224 LOCAL_SET_GL_ERROR(
13225 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
13226 return;
13230 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13231 glTexStorage2DEXT(target, levels, internal_format, width, height);
13232 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13233 if (error == GL_NO_ERROR) {
13234 GLsizei level_width = width;
13235 GLsizei level_height = height;
13237 GLenum cur_format = feature_info_->IsES3Enabled() ?
13238 internal_format : format;
13239 for (int ii = 0; ii < levels; ++ii) {
13240 if (target == GL_TEXTURE_CUBE_MAP) {
13241 for (int jj = 0; jj < 6; ++jj) {
13242 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj;
13243 texture_manager()->SetLevelInfo(texture_ref, face, ii, cur_format,
13244 level_width, level_height, 1, 0,
13245 format, type, gfx::Rect());
13247 } else {
13248 texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format,
13249 level_width, level_height, 1, 0,
13250 format, type, gfx::Rect());
13252 level_width = std::max(1, level_width >> 1);
13253 level_height = std::max(1, level_height >> 1);
13255 texture->SetImmutable(true);
13259 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13260 uint32 immediate_data_size,
13261 const void* cmd_data) {
13262 return error::kUnknownCommand;
13265 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
13266 const GLbyte* data) {
13267 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13268 "context", logger_.GetLogPrefix(),
13269 "mailbox[0]", static_cast<unsigned char>(data[0]));
13271 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13272 &state_, target);
13273 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
13276 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
13277 GLenum target, const GLbyte* data) {
13278 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13279 "context", logger_.GetLogPrefix(),
13280 "mailbox[0]", static_cast<unsigned char>(data[0]));
13282 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
13283 target, data);
13286 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
13287 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
13288 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13289 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
13290 "mailbox that was not generated by "
13291 "GenMailboxCHROMIUM.";
13293 if (!texture_ref) {
13294 LOCAL_SET_GL_ERROR(
13295 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
13296 return;
13299 Texture* produced = texture_manager()->Produce(texture_ref);
13300 if (!produced) {
13301 LOCAL_SET_GL_ERROR(
13302 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
13303 return;
13306 if (produced->target() != target) {
13307 LOCAL_SET_GL_ERROR(
13308 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
13309 return;
13312 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
13315 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
13316 const GLbyte* data) {
13317 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13318 "context", logger_.GetLogPrefix(),
13319 "mailbox[0]", static_cast<unsigned char>(data[0]));
13320 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13321 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13322 "mailbox that was not generated by "
13323 "GenMailboxCHROMIUM.";
13325 scoped_refptr<TextureRef> texture_ref =
13326 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13327 if (!texture_ref.get()) {
13328 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13329 "glConsumeTextureCHROMIUM",
13330 "unknown texture for target");
13331 return;
13333 GLuint client_id = texture_ref->client_id();
13334 if (!client_id) {
13335 LOCAL_SET_GL_ERROR(
13336 GL_INVALID_OPERATION,
13337 "glConsumeTextureCHROMIUM", "unknown texture for target");
13338 return;
13340 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13341 if (!texture) {
13342 LOCAL_SET_GL_ERROR(
13343 GL_INVALID_OPERATION,
13344 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13345 return;
13347 if (texture->target() != target) {
13348 LOCAL_SET_GL_ERROR(
13349 GL_INVALID_OPERATION,
13350 "glConsumeTextureCHROMIUM", "invalid target");
13351 return;
13354 DeleteTexturesHelper(1, &client_id);
13355 texture_ref = texture_manager()->Consume(client_id, texture);
13356 glBindTexture(target, texture_ref->service_id());
13358 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
13359 unit.bind_target = target;
13360 switch (target) {
13361 case GL_TEXTURE_2D:
13362 unit.bound_texture_2d = texture_ref;
13363 break;
13364 case GL_TEXTURE_CUBE_MAP:
13365 unit.bound_texture_cube_map = texture_ref;
13366 break;
13367 case GL_TEXTURE_EXTERNAL_OES:
13368 unit.bound_texture_external_oes = texture_ref;
13369 break;
13370 case GL_TEXTURE_RECTANGLE_ARB:
13371 unit.bound_texture_rectangle_arb = texture_ref;
13372 break;
13373 default:
13374 NOTREACHED(); // Validation should prevent us getting here.
13375 break;
13379 void GLES2DecoderImpl::EnsureTextureForClientId(
13380 GLenum target,
13381 GLuint client_id) {
13382 TextureRef* texture_ref = GetTexture(client_id);
13383 if (!texture_ref) {
13384 GLuint service_id;
13385 glGenTextures(1, &service_id);
13386 DCHECK_NE(0u, service_id);
13387 texture_ref = CreateTexture(client_id, service_id);
13388 texture_manager()->SetTarget(texture_ref, target);
13389 glBindTexture(target, service_id);
13390 RestoreCurrentTextureBindings(&state_, target);
13394 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13395 // provided is associated with a service_id/TextureRef for consistency, even if
13396 // the resulting texture is incomplete.
13397 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13398 uint32_t immediate_data_size,
13399 const void* cmd_data) {
13400 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
13401 *static_cast<
13402 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
13403 cmd_data);
13404 GLenum target = static_cast<GLenum>(c.target);
13405 uint32_t data_size;
13406 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
13407 return error::kOutOfBounds;
13409 if (data_size > immediate_data_size) {
13410 return error::kOutOfBounds;
13412 const GLbyte* mailbox =
13413 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
13414 if (!validators_->texture_bind_target.IsValid(target)) {
13415 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13416 "glCreateAndConsumeTextureCHROMIUM", target, "target");
13417 return error::kNoError;
13419 if (mailbox == NULL) {
13420 return error::kOutOfBounds;
13422 uint32_t client_id = c.client_id;
13423 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
13424 return error::kNoError;
13427 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
13428 const GLbyte* data, GLuint client_id) {
13429 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13430 "context", logger_.GetLogPrefix(),
13431 "mailbox[0]", static_cast<unsigned char>(data[0]));
13432 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13433 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13434 "passed a mailbox that was not "
13435 "generated by GenMailboxCHROMIUM.";
13437 TextureRef* texture_ref = GetTexture(client_id);
13438 if (texture_ref) {
13439 // No need to call EnsureTextureForClientId here, the client_id already has
13440 // an associated texture.
13441 LOCAL_SET_GL_ERROR(
13442 GL_INVALID_OPERATION,
13443 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13444 return;
13446 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13447 if (!texture) {
13448 EnsureTextureForClientId(target, client_id);
13449 LOCAL_SET_GL_ERROR(
13450 GL_INVALID_OPERATION,
13451 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13452 return;
13455 if (texture->target() != target) {
13456 EnsureTextureForClientId(target, client_id);
13457 LOCAL_SET_GL_ERROR(
13458 GL_INVALID_OPERATION,
13459 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13460 return;
13463 texture_ref = texture_manager()->Consume(client_id, texture);
13466 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
13467 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
13468 return valuebuffer && valuebuffer->IsValid();
13471 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
13472 GLuint client_id) {
13473 Valuebuffer* valuebuffer = NULL;
13474 if (client_id != 0) {
13475 valuebuffer = GetValuebuffer(client_id);
13476 if (!valuebuffer) {
13477 if (!group_->bind_generates_resource()) {
13478 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
13479 "id not generated by glBindValuebufferCHROMIUM");
13480 return;
13483 // It's a new id so make a valuebuffer for it.
13484 CreateValuebuffer(client_id);
13485 valuebuffer = GetValuebuffer(client_id);
13487 valuebuffer->MarkAsValid();
13489 state_.bound_valuebuffer = valuebuffer;
13492 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
13493 GLenum subscription) {
13494 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13495 return;
13497 state_.bound_valuebuffer.get()->AddSubscription(subscription);
13500 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
13501 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13502 return;
13504 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
13507 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
13508 GLenum target,
13509 GLenum subscription) {
13510 if (!CheckCurrentValuebufferForSubscription(
13511 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
13512 return;
13514 if (!CheckSubscriptionTarget(location, subscription,
13515 "glPopulateSubscribedValuesCHROMIUM")) {
13516 return;
13518 const ValueState* state =
13519 state_.bound_valuebuffer.get()->GetState(subscription);
13520 if (state) {
13521 switch (subscription) {
13522 case GL_MOUSE_POSITION_CHROMIUM:
13523 DoUniform2iv(location, 1, state->int_value);
13524 break;
13525 default:
13526 NOTREACHED() << "Unhandled uniform subscription target "
13527 << subscription;
13528 break;
13533 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13534 GLsizei length, const GLchar* marker) {
13535 if (!marker) {
13536 marker = "";
13538 debug_marker_manager_.SetMarker(
13539 length ? std::string(marker, length) : std::string(marker));
13542 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13543 GLsizei /*length*/, const GLchar* /*marker*/) {
13546 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13549 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13550 GLenum target, GLint image_id) {
13551 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13553 if (target == GL_TEXTURE_CUBE_MAP) {
13554 LOCAL_SET_GL_ERROR(
13555 GL_INVALID_ENUM,
13556 "glBindTexImage2DCHROMIUM", "invalid target");
13557 return;
13560 // Default target might be conceptually valid, but disallow it to avoid
13561 // accidents.
13562 TextureRef* texture_ref =
13563 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13564 if (!texture_ref) {
13565 LOCAL_SET_GL_ERROR(
13566 GL_INVALID_OPERATION,
13567 "glBindTexImage2DCHROMIUM", "no texture bound");
13568 return;
13571 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13572 if (!gl_image) {
13573 LOCAL_SET_GL_ERROR(
13574 GL_INVALID_OPERATION,
13575 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13576 return;
13580 ScopedGLErrorSuppressor suppressor(
13581 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13582 if (!gl_image->BindTexImage(target)) {
13583 LOCAL_SET_GL_ERROR(
13584 GL_INVALID_OPERATION,
13585 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13586 return;
13590 gfx::Size size = gl_image->GetSize();
13591 texture_manager()->SetLevelInfo(
13592 texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(),
13593 size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE,
13594 gfx::Rect(size));
13595 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
13598 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13599 GLenum target, GLint image_id) {
13600 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13602 // Default target might be conceptually valid, but disallow it to avoid
13603 // accidents.
13604 TextureRef* texture_ref =
13605 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13606 if (!texture_ref) {
13607 LOCAL_SET_GL_ERROR(
13608 GL_INVALID_OPERATION,
13609 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13610 return;
13613 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13614 if (!gl_image) {
13615 LOCAL_SET_GL_ERROR(
13616 GL_INVALID_OPERATION,
13617 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13618 return;
13621 // Do nothing when image is not currently bound.
13622 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
13623 return;
13626 ScopedGLErrorSuppressor suppressor(
13627 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13628 gl_image->ReleaseTexImage(target);
13631 texture_manager()->SetLevelInfo(
13632 texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0,
13633 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect());
13636 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13637 uint32 immediate_data_size,
13638 const void* cmd_data) {
13639 const gles2::cmds::TraceBeginCHROMIUM& c =
13640 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
13641 Bucket* category_bucket = GetBucket(c.category_bucket_id);
13642 Bucket* name_bucket = GetBucket(c.name_bucket_id);
13643 if (!category_bucket || category_bucket->size() == 0 ||
13644 !name_bucket || name_bucket->size() == 0) {
13645 return error::kInvalidArguments;
13648 std::string category_name;
13649 std::string trace_name;
13650 if (!category_bucket->GetAsString(&category_name) ||
13651 !name_bucket->GetAsString(&trace_name)) {
13652 return error::kInvalidArguments;
13655 debug_marker_manager_.PushGroup(trace_name);
13656 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
13657 LOCAL_SET_GL_ERROR(
13658 GL_INVALID_OPERATION,
13659 "glTraceBeginCHROMIUM", "unable to create begin trace");
13660 return error::kNoError;
13662 return error::kNoError;
13665 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13666 debug_marker_manager_.PopGroup();
13667 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
13668 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13669 "glTraceEndCHROMIUM", "no trace begin found");
13670 return;
13674 void GLES2DecoderImpl::DoDrawBuffersEXT(
13675 GLsizei count, const GLenum* bufs) {
13676 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
13677 LOCAL_SET_GL_ERROR(
13678 GL_INVALID_VALUE,
13679 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13680 return;
13683 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
13684 if (framebuffer) {
13685 for (GLsizei i = 0; i < count; ++i) {
13686 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
13687 bufs[i] != GL_NONE) {
13688 LOCAL_SET_GL_ERROR(
13689 GL_INVALID_OPERATION,
13690 "glDrawBuffersEXT",
13691 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13692 return;
13695 glDrawBuffersARB(count, bufs);
13696 framebuffer->SetDrawBuffers(count, bufs);
13697 } else { // backbuffer
13698 if (count > 1 ||
13699 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
13700 LOCAL_SET_GL_ERROR(
13701 GL_INVALID_OPERATION,
13702 "glDrawBuffersEXT",
13703 "more than one buffer or bufs not GL_NONE or GL_BACK");
13704 return;
13706 GLenum mapped_buf = bufs[0];
13707 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13708 bufs[0] == GL_BACK) {
13709 mapped_buf = GL_COLOR_ATTACHMENT0;
13711 glDrawBuffersARB(count, &mapped_buf);
13712 back_buffer_draw_buffer_ = bufs[0];
13716 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
13717 MarkContextLost(GetContextLostReasonFromResetStatus(current));
13718 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
13719 reset_by_robustness_extension_ = true;
13722 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13723 // On Adreno Android devices we need to use a workaround to force caches to
13724 // clear.
13725 if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) {
13726 context_->ReleaseCurrent(nullptr);
13727 context_->MakeCurrent(surface_.get());
13731 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
13732 const GLfloat* matrix) {
13733 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13734 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13735 if (!features().chromium_path_rendering) {
13736 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13737 "glMatrixLoadfCHROMIUM",
13738 "function not available");
13739 return;
13742 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13743 ? state_.projection_matrix
13744 : state_.modelview_matrix;
13745 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
13746 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13747 // since the values of the _NV and _CHROMIUM tokens match.
13748 glMatrixLoadfEXT(matrix_mode, matrix);
13751 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
13752 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13753 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13755 if (!features().chromium_path_rendering) {
13756 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13757 "glMatrixLoadIdentityCHROMIUM",
13758 "function not available");
13759 return;
13762 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13763 ? state_.projection_matrix
13764 : state_.modelview_matrix;
13765 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
13766 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13767 // since the values of the _NV and _CHROMIUM tokens match.
13768 glMatrixLoadIdentityEXT(matrix_mode);
13771 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13772 const char* function_name,
13773 TextureRef* texture_ref,
13774 GLenum target,
13775 GLint level,
13776 const void * data) {
13777 // We only support async uploads to 2D textures for now.
13778 if (GL_TEXTURE_2D != target) {
13779 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
13780 return false;
13782 // We only support uploads to level zero for now.
13783 if (level != 0) {
13784 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
13785 return false;
13787 // A transfer buffer must be bound, even for asyncTexImage2D.
13788 if (data == NULL) {
13789 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
13790 return false;
13792 // We only support one async transfer in progress.
13793 if (!texture_ref ||
13794 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
13795 LOCAL_SET_GL_ERROR(
13796 GL_INVALID_OPERATION,
13797 function_name, "transfer already in progress");
13798 return false;
13800 return true;
13803 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13804 uint32 async_upload_token,
13805 uint32 sync_data_shm_id,
13806 uint32 sync_data_shm_offset) {
13807 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
13808 if (!buffer.get() ||
13809 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
13810 return base::Closure();
13812 AsyncMemoryParams mem_params(buffer,
13813 sync_data_shm_offset,
13814 sizeof(AsyncUploadSync));
13816 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
13817 new AsyncUploadTokenCompletionObserver(async_upload_token));
13819 return base::Bind(
13820 &AsyncPixelTransferManager::AsyncNotifyCompletion,
13821 base::Unretained(GetAsyncPixelTransferManager()),
13822 mem_params,
13823 observer);
13826 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13827 uint32 immediate_data_size,
13828 const void* cmd_data) {
13829 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
13830 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
13831 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13832 GLenum target = static_cast<GLenum>(c.target);
13833 GLint level = static_cast<GLint>(c.level);
13834 GLenum internal_format = static_cast<GLenum>(c.internalformat);
13835 GLsizei width = static_cast<GLsizei>(c.width);
13836 GLsizei height = static_cast<GLsizei>(c.height);
13837 GLint border = static_cast<GLint>(c.border);
13838 GLenum format = static_cast<GLenum>(c.format);
13839 GLenum type = static_cast<GLenum>(c.type);
13840 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
13841 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
13842 uint32 pixels_size;
13843 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13844 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13845 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13847 base::ScopedClosureRunner scoped_completion_callback;
13848 if (async_upload_token) {
13849 base::Closure completion_closure =
13850 AsyncUploadTokenCompletionClosure(async_upload_token,
13851 sync_data_shm_id,
13852 sync_data_shm_offset);
13853 if (completion_closure.is_null())
13854 return error::kInvalidArguments;
13856 scoped_completion_callback.Reset(completion_closure);
13859 // TODO(epenner): Move this and copies of this memory validation
13860 // into ValidateTexImage2D step.
13861 if (!GLES2Util::ComputeImageDataSizes(
13862 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
13863 NULL, NULL)) {
13864 return error::kOutOfBounds;
13866 const void* pixels = NULL;
13867 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
13868 pixels = GetSharedMemoryAs<const void*>(
13869 pixels_shm_id, pixels_shm_offset, pixels_size);
13870 if (!pixels) {
13871 return error::kOutOfBounds;
13875 TextureManager::DoTexImageArguments args = {
13876 target, level, internal_format, width, height, 1, border, format, type,
13877 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
13878 TextureRef* texture_ref;
13879 // All the normal glTexSubImage2D validation.
13880 if (!texture_manager()->ValidateTexImage(
13881 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
13882 return error::kNoError;
13885 // Extra async validation.
13886 Texture* texture = texture_ref->texture();
13887 if (!ValidateAsyncTransfer(
13888 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
13889 return error::kNoError;
13891 // Don't allow async redefinition of a textures.
13892 if (texture->IsDefined()) {
13893 LOCAL_SET_GL_ERROR(
13894 GL_INVALID_OPERATION,
13895 "glAsyncTexImage2DCHROMIUM", "already defined");
13896 return error::kNoError;
13899 if (!EnsureGPUMemoryAvailable(pixels_size)) {
13900 LOCAL_SET_GL_ERROR(
13901 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
13902 return error::kNoError;
13905 // Setup the parameters.
13906 AsyncTexImage2DParams tex_params = {
13907 target, level, static_cast<GLenum>(internal_format),
13908 width, height, border, format, type};
13909 AsyncMemoryParams mem_params(
13910 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
13912 // Set up the async state if needed, and make the texture
13913 // immutable so the async state stays valid. The level info
13914 // is set up lazily when the transfer completes.
13915 AsyncPixelTransferDelegate* delegate =
13916 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
13917 tex_params);
13918 texture->SetImmutable(true);
13920 delegate->AsyncTexImage2D(
13921 tex_params,
13922 mem_params,
13923 base::Bind(&TextureManager::SetLevelInfoFromParams,
13924 // The callback is only invoked if the transfer delegate still
13925 // exists, which implies through manager->texture_ref->state
13926 // ownership that both of these pointers are valid.
13927 base::Unretained(texture_manager()),
13928 base::Unretained(texture_ref),
13929 tex_params));
13930 return error::kNoError;
13933 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13934 uint32 immediate_data_size,
13935 const void* cmd_data) {
13936 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
13937 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
13938 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13939 GLenum target = static_cast<GLenum>(c.target);
13940 GLint level = static_cast<GLint>(c.level);
13941 GLint xoffset = static_cast<GLint>(c.xoffset);
13942 GLint yoffset = static_cast<GLint>(c.yoffset);
13943 GLsizei width = static_cast<GLsizei>(c.width);
13944 GLsizei height = static_cast<GLsizei>(c.height);
13945 GLenum format = static_cast<GLenum>(c.format);
13946 GLenum type = static_cast<GLenum>(c.type);
13947 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13948 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13949 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13951 base::ScopedClosureRunner scoped_completion_callback;
13952 if (async_upload_token) {
13953 base::Closure completion_closure =
13954 AsyncUploadTokenCompletionClosure(async_upload_token,
13955 sync_data_shm_id,
13956 sync_data_shm_offset);
13957 if (completion_closure.is_null())
13958 return error::kInvalidArguments;
13960 scoped_completion_callback.Reset(completion_closure);
13963 // TODO(epenner): Move this and copies of this memory validation
13964 // into ValidateTexSubImage2D step.
13965 uint32 data_size;
13966 if (!GLES2Util::ComputeImageDataSizes(
13967 width, height, 1, format, type, state_.unpack_alignment, &data_size,
13968 NULL, NULL)) {
13969 return error::kOutOfBounds;
13971 const void* pixels = GetSharedMemoryAs<const void*>(
13972 c.data_shm_id, c.data_shm_offset, data_size);
13974 // All the normal glTexSubImage2D validation.
13975 error::Error error = error::kNoError;
13976 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
13977 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
13978 return error;
13981 // Extra async validation.
13982 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13983 &state_, target);
13984 Texture* texture = texture_ref->texture();
13985 if (!ValidateAsyncTransfer(
13986 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
13987 return error::kNoError;
13989 // Guarantee async textures are always 'cleared' as follows:
13990 // - AsyncTexImage2D can not redefine an existing texture
13991 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13992 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13993 // - Textures become immutable after an async call.
13994 // This way we know in all cases that an async texture is always clear.
13995 if (!texture->SafeToRenderFrom()) {
13996 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
13997 target, level)) {
13998 LOCAL_SET_GL_ERROR(
13999 GL_OUT_OF_MEMORY,
14000 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
14001 return error::kNoError;
14005 // Setup the parameters.
14006 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
14007 width, height, format, type};
14008 AsyncMemoryParams mem_params(
14009 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
14010 AsyncPixelTransferDelegate* delegate =
14011 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
14012 if (!delegate) {
14013 // TODO(epenner): We may want to enforce exclusive use
14014 // of async APIs in which case this should become an error,
14015 // (the texture should have been async defined).
14016 AsyncTexImage2DParams define_params = {target, level,
14017 0, 0, 0, 0, 0, 0};
14018 texture->GetLevelSize(
14019 target, level, &define_params.width, &define_params.height, nullptr);
14020 texture->GetLevelType(
14021 target, level, &define_params.type, &define_params.internal_format);
14022 // Set up the async state if needed, and make the texture
14023 // immutable so the async state stays valid.
14024 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
14025 texture_ref, define_params);
14026 texture->SetImmutable(true);
14029 delegate->AsyncTexSubImage2D(tex_params, mem_params);
14030 return error::kNoError;
14033 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
14034 uint32 immediate_data_size,
14035 const void* cmd_data) {
14036 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
14037 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
14038 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
14039 GLenum target = static_cast<GLenum>(c.target);
14041 if (GL_TEXTURE_2D != target) {
14042 LOCAL_SET_GL_ERROR(
14043 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
14044 return error::kNoError;
14046 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
14047 &state_, target);
14048 if (!texture_ref) {
14049 LOCAL_SET_GL_ERROR(
14050 GL_INVALID_OPERATION,
14051 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
14052 return error::kNoError;
14054 AsyncPixelTransferDelegate* delegate =
14055 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
14056 if (!delegate) {
14057 LOCAL_SET_GL_ERROR(
14058 GL_INVALID_OPERATION,
14059 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
14060 return error::kNoError;
14062 delegate->WaitForTransferCompletion();
14063 ProcessFinishedAsyncTransfers();
14064 return error::kNoError;
14067 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
14068 uint32 immediate_data_size,
14069 const void* data) {
14070 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
14072 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
14073 ProcessFinishedAsyncTransfers();
14074 return error::kNoError;
14077 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
14078 uint32_t immediate_data_size, const void* cmd_data) {
14079 if (!unsafe_es3_apis_enabled())
14080 return error::kUnknownCommand;
14081 const gles2::cmds::UniformBlockBinding& c =
14082 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
14083 GLuint client_id = c.program;
14084 GLuint index = static_cast<GLuint>(c.index);
14085 GLuint binding = static_cast<GLuint>(c.binding);
14086 Program* program = GetProgramInfoNotShader(
14087 client_id, "glUniformBlockBinding");
14088 if (!program) {
14089 return error::kNoError;
14091 GLuint service_id = program->service_id();
14092 glUniformBlockBinding(service_id, index, binding);
14093 return error::kNoError;
14096 error::Error GLES2DecoderImpl::HandleClientWaitSync(
14097 uint32_t immediate_data_size, const void* cmd_data) {
14098 if (!unsafe_es3_apis_enabled())
14099 return error::kUnknownCommand;
14100 const gles2::cmds::ClientWaitSync& c =
14101 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
14102 GLuint sync = static_cast<GLuint>(c.sync);
14103 GLbitfield flags = static_cast<GLbitfield>(c.flags);
14104 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
14105 typedef cmds::ClientWaitSync::Result Result;
14106 Result* result_dst = GetSharedMemoryAs<Result*>(
14107 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
14108 if (!result_dst) {
14109 return error::kOutOfBounds;
14111 if (*result_dst != GL_WAIT_FAILED) {
14112 return error::kInvalidArguments;
14114 GLsync service_sync = 0;
14115 if (!group_->GetSyncServiceId(sync, &service_sync)) {
14116 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
14117 return error::kNoError;
14119 *result_dst = glClientWaitSync(service_sync, flags, timeout);
14120 return error::kNoError;
14123 error::Error GLES2DecoderImpl::HandleWaitSync(
14124 uint32_t immediate_data_size, const void* cmd_data) {
14125 if (!unsafe_es3_apis_enabled())
14126 return error::kUnknownCommand;
14127 const gles2::cmds::WaitSync& c =
14128 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
14129 GLuint sync = static_cast<GLuint>(c.sync);
14130 GLbitfield flags = static_cast<GLbitfield>(c.flags);
14131 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
14132 GLsync service_sync = 0;
14133 if (!group_->GetSyncServiceId(sync, &service_sync)) {
14134 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
14135 return error::kNoError;
14137 glWaitSync(service_sync, flags, timeout);
14138 return error::kNoError;
14141 error::Error GLES2DecoderImpl::HandleGetInternalformativ(
14142 uint32_t immediate_data_size, const void* cmd_data) {
14143 if (!unsafe_es3_apis_enabled())
14144 return error::kUnknownCommand;
14145 const gles2::cmds::GetInternalformativ& c =
14146 *static_cast<const gles2::cmds::GetInternalformativ*>(cmd_data);
14147 GLenum target = static_cast<GLenum>(c.target);
14148 GLenum format = static_cast<GLenum>(c.format);
14149 GLenum pname = static_cast<GLenum>(c.pname);
14150 if (!validators_->render_buffer_target.IsValid(target)) {
14151 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target, "target");
14152 return error::kNoError;
14154 if (!validators_->render_buffer_format.IsValid(format)) {
14155 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format, "format");
14156 return error::kNoError;
14158 if (!validators_->internal_format_parameter.IsValid(pname)) {
14159 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname, "pname");
14160 return error::kNoError;
14162 typedef cmds::GetInternalformativ::Result Result;
14163 GLsizei num_values = 0;
14164 switch (pname) {
14165 case GL_NUM_SAMPLE_COUNTS:
14166 num_values = 1;
14167 break;
14168 case GL_SAMPLES:
14170 GLint value = 0;
14171 glGetInternalformativ(target, format, GL_NUM_SAMPLE_COUNTS, 1, &value);
14172 num_values = static_cast<GLsizei>(value);
14174 break;
14175 default:
14176 NOTREACHED();
14177 break;
14179 Result* result = GetSharedMemoryAs<Result*>(
14180 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
14181 GLint* params = result ? result->GetData() : NULL;
14182 if (params == NULL) {
14183 return error::kOutOfBounds;
14185 // Check that the client initialized the result.
14186 if (result->size != 0) {
14187 return error::kInvalidArguments;
14189 glGetInternalformativ(target, format, pname, num_values, params);
14190 result->SetNumResults(num_values);
14191 return error::kNoError;
14194 error::Error GLES2DecoderImpl::HandleMapBufferRange(
14195 uint32_t immediate_data_size, const void* cmd_data) {
14196 if (!unsafe_es3_apis_enabled()) {
14197 return error::kUnknownCommand;
14199 const gles2::cmds::MapBufferRange& c =
14200 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
14201 GLenum target = static_cast<GLenum>(c.target);
14202 GLbitfield access = static_cast<GLbitfield>(c.access);
14203 GLintptr offset = static_cast<GLintptr>(c.offset);
14204 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
14206 typedef cmds::MapBufferRange::Result Result;
14207 Result* result = GetSharedMemoryAs<Result*>(
14208 c.result_shm_id, c.result_shm_offset, sizeof(*result));
14209 if (!result) {
14210 return error::kOutOfBounds;
14212 if (*result != 0) {
14213 *result = 0;
14214 return error::kInvalidArguments;
14216 int8_t* mem =
14217 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
14218 if (!mem) {
14219 return error::kOutOfBounds;
14222 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
14223 if ((access & mask) == mask) {
14224 // TODO(zmo): To be on the safe side, always map
14225 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
14226 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
14227 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
14229 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14230 // undefined behaviors.
14231 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
14232 if ((access & mask) == mask) {
14233 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
14234 "incompatible access bits");
14235 return error::kNoError;
14237 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
14238 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
14239 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14240 access = (access | GL_MAP_READ_BIT);
14242 void* ptr = glMapBufferRange(target, offset, size, access);
14243 if (ptr == nullptr) {
14244 return error::kNoError;
14246 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14247 DCHECK(buffer);
14248 buffer->SetMappedRange(offset, size, access, ptr,
14249 GetSharedMemoryBuffer(c.data_shm_id));
14250 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14251 memcpy(mem, ptr, size);
14253 *result = 1;
14254 return error::kNoError;
14257 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
14258 uint32_t immediate_data_size, const void* cmd_data) {
14259 if (!unsafe_es3_apis_enabled()) {
14260 return error::kUnknownCommand;
14262 const gles2::cmds::UnmapBuffer& c =
14263 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
14264 GLenum target = static_cast<GLenum>(c.target);
14266 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14267 if (!buffer) {
14268 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
14269 return error::kNoError;
14271 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
14272 if (!mapped_range) {
14273 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
14274 "buffer is unmapped");
14275 return error::kNoError;
14277 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
14278 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
14279 GL_MAP_FLUSH_EXPLICIT_BIT) {
14280 // If we don't need to write back, or explict flush is required, no copying
14281 // back is needed.
14282 } else {
14283 void* mem = mapped_range->GetShmPointer();
14284 if (!mem) {
14285 return error::kOutOfBounds;
14287 DCHECK(mapped_range->pointer);
14288 memcpy(mapped_range->pointer, mem, mapped_range->size);
14290 buffer->RemoveMappedRange();
14291 GLboolean rt = glUnmapBuffer(target);
14292 if (rt == GL_FALSE) {
14293 // At this point, we have already done the necessary validation, so
14294 // GL_FALSE indicates data corruption.
14295 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14296 // the second unmap could still return GL_FALSE. For now, we simply lose
14297 // the contexts in the share group.
14298 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14299 // Need to lose current context before broadcasting!
14300 MarkContextLost(error::kGuilty);
14301 group_->LoseContexts(error::kInnocent);
14302 return error::kLostContext;
14304 return error::kNoError;
14307 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14308 TextureRef* texture_ref) {
14309 Texture* texture = texture_ref->texture();
14310 DoDidUseTexImageIfNeeded(texture, texture->target());
14313 // Note that GL_LOST_CONTEXT is specific to GLES.
14314 // For desktop GL we have to query the reset status proactively.
14315 void GLES2DecoderImpl::OnContextLostError() {
14316 if (!WasContextLost()) {
14317 // Need to lose current context before broadcasting!
14318 CheckResetStatus();
14319 group_->LoseContexts(error::kUnknown);
14320 reset_by_robustness_extension_ = true;
14324 void GLES2DecoderImpl::OnOutOfMemoryError() {
14325 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
14326 error::ContextLostReason other = error::kOutOfMemory;
14327 if (CheckResetStatus()) {
14328 other = error::kUnknown;
14329 } else {
14330 // Need to lose current context before broadcasting!
14331 MarkContextLost(error::kOutOfMemory);
14333 group_->LoseContexts(other);
14337 error::Error GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14338 uint32 immediate_data_size,
14339 const void* cmd_data) {
14340 static const char kFunctionName[] = "glGenPathsCHROMIUM";
14341 const gles2::cmds::GenPathsCHROMIUM& c =
14342 *static_cast<const gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
14343 if (!features().chromium_path_rendering) {
14344 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14345 "function not available");
14346 return error::kNoError;
14349 GLsizei range = static_cast<GLsizei>(c.range);
14350 if (range < 0) {
14351 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14352 return error::kNoError;
14355 GLuint first_client_id = static_cast<GLuint>(c.first_client_id);
14356 if (first_client_id == 0)
14357 return error::kInvalidArguments;
14359 if (range == 0)
14360 return error::kNoError;
14362 if (!GenPathsCHROMIUMHelper(first_client_id, range))
14363 return error::kInvalidArguments;
14365 return error::kNoError;
14367 error::Error GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14368 uint32_t immediate_data_size,
14369 const void* cmd_data) {
14370 static const char kFunctionName[] = "glDeletePathsCHROMIUM";
14371 const gles2::cmds::DeletePathsCHROMIUM& c =
14372 *static_cast<const gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
14373 if (!features().chromium_path_rendering) {
14374 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14375 "function not available");
14376 return error::kNoError;
14379 GLsizei range = static_cast<GLsizei>(c.range);
14380 if (range < 0) {
14381 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14382 return error::kNoError;
14385 if (range == 0)
14386 return error::kNoError;
14388 GLuint first_client_id = c.first_client_id;
14389 // first_client_id can be 0, because non-existing path ids are skipped.
14391 if (!DeletePathsCHROMIUMHelper(first_client_id, range))
14392 return error::kInvalidArguments;
14394 return error::kNoError;
14397 error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14398 uint32 immediate_data_size,
14399 const void* cmd_data) {
14400 static const char kFunctionName[] = "glPathCommandsCHROMIUM";
14401 const gles2::cmds::PathCommandsCHROMIUM& c =
14402 *static_cast<const gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
14403 if (!features().chromium_path_rendering) {
14404 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14405 "function not available");
14406 return error::kNoError;
14409 GLuint service_id = 0;
14410 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14411 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14412 "invalid path name");
14413 return error::kNoError;
14416 GLsizei num_commands = static_cast<GLsizei>(c.numCommands);
14417 if (num_commands < 0) {
14418 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCommands < 0");
14419 return error::kNoError;
14422 GLsizei num_coords = static_cast<uint32>(c.numCoords);
14423 if (num_coords < 0) {
14424 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCoords < 0");
14425 return error::kNoError;
14428 GLenum coord_type = static_cast<uint32>(c.coordType);
14429 if (!validators_->path_coord_type.IsValid(static_cast<GLint>(coord_type))) {
14430 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid coordType");
14431 return error::kNoError;
14434 const GLubyte* commands = NULL;
14435 base::CheckedNumeric<GLsizei> num_coords_expected = 0;
14437 if (num_commands > 0) {
14438 uint32 commands_shm_id = static_cast<uint32>(c.commands_shm_id);
14439 uint32 commands_shm_offset = static_cast<uint32>(c.commands_shm_offset);
14440 if (commands_shm_id != 0 || commands_shm_offset != 0)
14441 commands = GetSharedMemoryAs<const GLubyte*>(
14442 commands_shm_id, commands_shm_offset, num_commands);
14444 if (!commands)
14445 return error::kOutOfBounds;
14447 for (GLsizei i = 0; i < num_commands; ++i) {
14448 switch (commands[i]) {
14449 case GL_CLOSE_PATH_CHROMIUM:
14450 // Close has no coords.
14451 break;
14452 case GL_MOVE_TO_CHROMIUM:
14453 // Fallthrough.
14454 case GL_LINE_TO_CHROMIUM:
14455 num_coords_expected += 2;
14456 break;
14457 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
14458 num_coords_expected += 4;
14459 break;
14460 case GL_CUBIC_CURVE_TO_CHROMIUM:
14461 num_coords_expected += 6;
14462 break;
14463 case GL_CONIC_CURVE_TO_CHROMIUM:
14464 num_coords_expected += 5;
14465 break;
14466 default:
14467 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid command");
14468 return error::kNoError;
14473 if (!num_coords_expected.IsValid() ||
14474 num_coords != num_coords_expected.ValueOrDie()) {
14475 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14476 "numCoords does not match commands");
14477 return error::kNoError;
14480 const void* coords = NULL;
14482 if (num_coords > 0) {
14483 uint32 coords_size = 0;
14484 uint32 coord_type_size =
14485 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
14486 if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size))
14487 return error::kOutOfBounds;
14489 uint32 coords_shm_id = static_cast<uint32>(c.coords_shm_id);
14490 uint32 coords_shm_offset = static_cast<uint32>(c.coords_shm_offset);
14491 if (coords_shm_id != 0 || coords_shm_offset != 0)
14492 coords = GetSharedMemoryAs<const void*>(coords_shm_id, coords_shm_offset,
14493 coords_size);
14495 if (!coords)
14496 return error::kOutOfBounds;
14499 glPathCommandsNV(service_id, num_commands, commands, num_coords, coord_type,
14500 coords);
14502 return error::kNoError;
14505 error::Error GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14506 uint32 immediate_data_size,
14507 const void* cmd_data) {
14508 static const char kFunctionName[] = "glPathParameterfCHROMIUM";
14509 const gles2::cmds::PathParameterfCHROMIUM& c =
14510 *static_cast<const gles2::cmds::PathParameterfCHROMIUM*>(cmd_data);
14511 if (!features().chromium_path_rendering) {
14512 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14513 "function not available");
14514 return error::kNoError;
14516 GLuint service_id = 0;
14517 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14518 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14519 "invalid path name");
14520 return error::kNoError;
14523 GLenum pname = static_cast<GLenum>(c.pname);
14524 GLfloat value = static_cast<GLfloat>(c.value);
14525 bool hasValueError = false;
14527 switch (pname) {
14528 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14529 case GL_PATH_MITER_LIMIT_CHROMIUM:
14530 hasValueError = std::isnan(value) || !std::isfinite(value) || value < 0;
14531 break;
14532 case GL_PATH_STROKE_BOUND_CHROMIUM:
14533 value = std::max(std::min(1.0f, value), 0.0f);
14534 break;
14535 case GL_PATH_END_CAPS_CHROMIUM:
14536 hasValueError = !validators_->path_parameter_cap_values.IsValid(
14537 static_cast<GLint>(value));
14538 break;
14539 case GL_PATH_JOIN_STYLE_CHROMIUM:
14540 hasValueError = !validators_->path_parameter_join_values.IsValid(
14541 static_cast<GLint>(value));
14542 break;
14543 default:
14544 DCHECK(!validators_->path_parameter.IsValid(pname));
14545 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14546 return error::kNoError;
14548 DCHECK(validators_->path_parameter.IsValid(pname));
14550 if (hasValueError) {
14551 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14552 return error::kNoError;
14555 glPathParameterfNV(service_id, pname, value);
14556 return error::kNoError;
14559 error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14560 uint32 immediate_data_size,
14561 const void* cmd_data) {
14562 static const char kFunctionName[] = "glPathParameteriCHROMIUM";
14563 const gles2::cmds::PathParameteriCHROMIUM& c =
14564 *static_cast<const gles2::cmds::PathParameteriCHROMIUM*>(cmd_data);
14565 if (!features().chromium_path_rendering) {
14566 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14567 "function not available");
14568 return error::kNoError;
14570 GLuint service_id = 0;
14571 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14572 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14573 "invalid path name");
14574 return error::kNoError;
14577 GLenum pname = static_cast<GLenum>(c.pname);
14578 GLint value = static_cast<GLint>(c.value);
14579 bool hasValueError = false;
14581 switch (pname) {
14582 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14583 case GL_PATH_MITER_LIMIT_CHROMIUM:
14584 hasValueError = value < 0;
14585 break;
14586 case GL_PATH_STROKE_BOUND_CHROMIUM:
14587 value = std::max(std::min(1, value), 0);
14588 break;
14589 case GL_PATH_END_CAPS_CHROMIUM:
14590 hasValueError = !validators_->path_parameter_cap_values.IsValid(value);
14591 break;
14592 case GL_PATH_JOIN_STYLE_CHROMIUM:
14593 hasValueError = !validators_->path_parameter_join_values.IsValid(value);
14594 break;
14595 default:
14596 DCHECK(!validators_->path_parameter.IsValid(pname));
14597 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14598 return error::kNoError;
14600 DCHECK(validators_->path_parameter.IsValid(pname));
14602 if (hasValueError) {
14603 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14604 return error::kNoError;
14607 glPathParameteriNV(service_id, pname, value);
14608 return error::kNoError;
14611 error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14612 uint32 immediate_data_size,
14613 const void* cmd_data) {
14614 static const char kFunctionName[] = "glStencilFillPathCHROMIUM";
14615 const gles2::cmds::StencilFillPathCHROMIUM& c =
14616 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(cmd_data);
14617 if (!features().chromium_path_rendering) {
14618 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14619 "function not available");
14620 return error::kNoError;
14622 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14623 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14624 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14625 return error::kNoError;
14627 GLuint mask = static_cast<GLuint>(c.mask);
14628 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14629 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14630 GLES2Util::IsNPOT(mask + 1)) {
14631 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14632 "mask + 1 is not power of two");
14633 return error::kNoError;
14635 GLuint service_id = 0;
14636 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14637 // "If /path/ does not name an existing path object, the command does
14638 // nothing (and no error is generated)."
14639 // This holds for other rendering functions, too.
14640 return error::kNoError;
14642 ApplyDirtyState();
14643 glStencilFillPathNV(service_id, fill_mode, mask);
14644 return error::kNoError;
14647 error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14648 uint32 immediate_data_size,
14649 const void* cmd_data) {
14650 static const char kFunctionName[] = "glStencilStrokePathCHROMIUM";
14651 const gles2::cmds::StencilStrokePathCHROMIUM& c =
14652 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data);
14653 if (!features().chromium_path_rendering) {
14654 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14655 "function not available");
14656 return error::kNoError;
14658 GLuint service_id = 0;
14659 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14660 return error::kNoError;
14662 GLint reference = static_cast<GLint>(c.reference);
14663 GLuint mask = static_cast<GLuint>(c.mask);
14664 ApplyDirtyState();
14665 glStencilStrokePathNV(service_id, reference, mask);
14666 return error::kNoError;
14669 error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14670 uint32 immediate_data_size,
14671 const void* cmd_data) {
14672 static const char kFunctionName[] = "glCoverFillPathCHROMIUM";
14673 const gles2::cmds::CoverFillPathCHROMIUM& c =
14674 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data);
14675 if (!features().chromium_path_rendering) {
14676 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14677 "function not available");
14678 return error::kNoError;
14680 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14681 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14682 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14683 return error::kNoError;
14685 GLuint service_id = 0;
14686 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14687 return error::kNoError;
14689 ApplyDirtyState();
14690 glCoverFillPathNV(service_id, cover_mode);
14691 return error::kNoError;
14694 error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14695 uint32 immediate_data_size,
14696 const void* cmd_data) {
14697 static const char kFunctionName[] = "glCoverStrokePathCHROMIUM";
14698 const gles2::cmds::CoverStrokePathCHROMIUM& c =
14699 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data);
14700 if (!features().chromium_path_rendering) {
14701 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14702 "function not available");
14703 return error::kNoError;
14705 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14706 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14707 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14708 return error::kNoError;
14710 GLuint service_id = 0;
14711 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14712 return error::kNoError;
14714 ApplyDirtyState();
14715 glCoverStrokePathNV(service_id, cover_mode);
14716 return error::kNoError;
14719 error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14720 uint32 immediate_data_size,
14721 const void* cmd_data) {
14722 static const char kFunctionName[] = "glStencilThenCoverFillPathCHROMIUM";
14723 const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
14724 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
14725 cmd_data);
14726 if (!features().chromium_path_rendering) {
14727 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14728 "function not available");
14729 return error::kNoError;
14731 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14732 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14733 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14734 return error::kNoError;
14736 GLuint mask = static_cast<GLuint>(c.mask);
14737 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14738 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14739 GLES2Util::IsNPOT(mask + 1)) {
14740 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14741 "mask + 1 is not power of two");
14742 return error::kNoError;
14744 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14745 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14746 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14747 return error::kNoError;
14749 GLuint service_id = 0;
14750 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14751 return error::kNoError;
14753 ApplyDirtyState();
14754 glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode);
14755 return error::kNoError;
14758 error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14759 uint32 immediate_data_size,
14760 const void* cmd_data) {
14761 static const char kFunctionName[] = "glStencilThenCoverStrokePathCHROMIUM";
14762 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
14763 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
14764 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 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14771 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14772 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14773 return error::kNoError;
14775 GLuint service_id = 0;
14776 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14777 return error::kNoError;
14779 GLint reference = static_cast<GLint>(c.reference);
14780 GLuint mask = static_cast<GLuint>(c.mask);
14781 ApplyDirtyState();
14782 glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode);
14783 return error::kNoError;
14786 // Include the auto-generated part of this file. We split this because it means
14787 // we can easily edit the non-auto generated parts right here in this file
14788 // instead of having to edit some template or the code generator.
14789 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14791 } // namespace gles2
14792 } // namespace gpu