Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob5cab02c2b9239947c08b85474b8e1bf022be22af
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/numerics/safe_math.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/trace_event/trace_event.h"
24 #include "base/trace_event/trace_event_synthetic_delay.h"
25 #include "build/build_config.h"
26 #define GLES2_GPU_SERVICE 1
27 #include "gpu/command_buffer/common/debug_marker_manager.h"
28 #include "gpu/command_buffer/common/gles2_cmd_format.h"
29 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
30 #include "gpu/command_buffer/common/mailbox.h"
31 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
32 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
33 #include "gpu/command_buffer/service/buffer_manager.h"
34 #include "gpu/command_buffer/service/context_group.h"
35 #include "gpu/command_buffer/service/context_state.h"
36 #include "gpu/command_buffer/service/error_state.h"
37 #include "gpu/command_buffer/service/feature_info.h"
38 #include "gpu/command_buffer/service/framebuffer_manager.h"
39 #include "gpu/command_buffer/service/gl_utils.h"
40 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
41 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
42 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
43 #include "gpu/command_buffer/service/gpu_state_tracer.h"
44 #include "gpu/command_buffer/service/gpu_switches.h"
45 #include "gpu/command_buffer/service/gpu_tracer.h"
46 #include "gpu/command_buffer/service/image_manager.h"
47 #include "gpu/command_buffer/service/logger.h"
48 #include "gpu/command_buffer/service/mailbox_manager.h"
49 #include "gpu/command_buffer/service/memory_tracking.h"
50 #include "gpu/command_buffer/service/path_manager.h"
51 #include "gpu/command_buffer/service/program_manager.h"
52 #include "gpu/command_buffer/service/query_manager.h"
53 #include "gpu/command_buffer/service/renderbuffer_manager.h"
54 #include "gpu/command_buffer/service/shader_manager.h"
55 #include "gpu/command_buffer/service/shader_translator.h"
56 #include "gpu/command_buffer/service/texture_manager.h"
57 #include "gpu/command_buffer/service/valuebuffer_manager.h"
58 #include "gpu/command_buffer/service/vertex_array_manager.h"
59 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
60 #include "third_party/smhasher/src/City.h"
61 #include "ui/gfx/geometry/point.h"
62 #include "ui/gfx/geometry/rect.h"
63 #include "ui/gfx/geometry/size.h"
64 #include "ui/gfx/overlay_transform.h"
65 #include "ui/gl/gl_bindings.h"
66 #include "ui/gl/gl_context.h"
67 #include "ui/gl/gl_fence.h"
68 #include "ui/gl/gl_image.h"
69 #include "ui/gl/gl_implementation.h"
70 #include "ui/gl/gl_surface.h"
71 #include "ui/gl/gpu_timing.h"
73 #if defined(OS_MACOSX)
74 #include <IOSurface/IOSurface.h>
75 // Note that this must be included after gl_bindings.h to avoid conflicts.
76 #include <OpenGL/CGLIOSurface.h>
77 #endif
79 namespace gpu {
80 namespace gles2 {
82 namespace {
84 const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
85 const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
86 const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
87 const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
89 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
90 0.0f, 1.0f, 0.0f, 0.0f,
91 0.0f, 0.0f, 1.0f, 0.0f,
92 0.0f, 0.0f, 0.0f, 1.0f};
94 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
95 GLint rangeMax,
96 GLint precision) {
97 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
100 void GetShaderPrecisionFormatImpl(GLenum shader_type,
101 GLenum precision_type,
102 GLint* range, GLint* precision) {
103 switch (precision_type) {
104 case GL_LOW_INT:
105 case GL_MEDIUM_INT:
106 case GL_HIGH_INT:
107 // These values are for a 32-bit twos-complement integer format.
108 range[0] = 31;
109 range[1] = 30;
110 *precision = 0;
111 break;
112 case GL_LOW_FLOAT:
113 case GL_MEDIUM_FLOAT:
114 case GL_HIGH_FLOAT:
115 // These values are for an IEEE single-precision floating-point format.
116 range[0] = 127;
117 range[1] = 127;
118 *precision = 23;
119 break;
120 default:
121 NOTREACHED();
122 break;
125 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
126 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
127 // This function is sometimes defined even though it's really just
128 // a stub, so we need to set range and precision as if it weren't
129 // defined before calling it.
130 // On Mac OS with some GPUs, calling this generates a
131 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
132 // platforms.
133 glGetShaderPrecisionFormat(shader_type, precision_type,
134 range, precision);
136 // TODO(brianderson): Make the following official workarounds.
138 // Some drivers have bugs where they report the ranges as a negative number.
139 // Taking the absolute value here shouldn't hurt because negative numbers
140 // aren't expected anyway.
141 range[0] = abs(range[0]);
142 range[1] = abs(range[1]);
144 // If the driver reports a precision for highp float that isn't actually
145 // highp, don't pretend like it's supported because shader compilation will
146 // fail anyway.
147 if (precision_type == GL_HIGH_FLOAT &&
148 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
149 range[0] = 0;
150 range[1] = 0;
151 *precision = 0;
156 gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
157 switch (plane_transform) {
158 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
159 return gfx::OVERLAY_TRANSFORM_NONE;
160 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
161 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
162 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
163 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
164 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
165 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
166 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
168 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
170 default:
171 return gfx::OVERLAY_TRANSFORM_INVALID;
175 template <typename MANAGER_TYPE, typename OBJECT_TYPE>
176 GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) {
177 DCHECK(manager);
178 GLuint client_id = 0;
179 if (object) {
180 manager->GetClientId(object->service_id(), &client_id);
182 return client_id;
185 struct Vec4f {
186 explicit Vec4f(const Vec4& data) {
187 data.GetValues(v);
190 GLfloat v[4];
193 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
194 // contains the other rectangle or shares an edge with the other rectangle.
195 bool CombineAdjacentRects(const gfx::Rect& rect1,
196 const gfx::Rect& rect2,
197 gfx::Rect* result) {
198 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
199 if (rect1.IsEmpty() || rect2.Contains(rect1)) {
200 *result = rect2;
201 return true;
204 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
205 if (rect2.IsEmpty() || rect1.Contains(rect2)) {
206 *result = rect1;
207 return true;
210 // Return the union of |rect1| and |rect2| if they share an edge.
211 if (rect1.SharesEdgeWith(rect2)) {
212 *result = gfx::UnionRects(rect1, rect2);
213 return true;
216 // Return false if it's not possible to combine |rect1| and |rect2|.
217 return false;
220 } // namespace
222 class GLES2DecoderImpl;
224 // Local versions of the SET_GL_ERROR macros
225 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
226 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
227 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
228 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
229 function_name, value, label)
230 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
231 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
232 function_name, pname)
233 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
234 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
235 function_name)
236 #define LOCAL_PEEK_GL_ERROR(function_name) \
237 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
238 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
239 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
240 #define LOCAL_PERFORMANCE_WARNING(msg) \
241 PerformanceWarning(__FILE__, __LINE__, msg)
242 #define LOCAL_RENDER_WARNING(msg) \
243 RenderWarning(__FILE__, __LINE__, msg)
245 // Check that certain assumptions the code makes are true. There are places in
246 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
247 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
248 // a few others) are 32bits. If they are not 32bits the code will have to change
249 // to call those GL functions with service side memory and then copy the results
250 // to shared memory, converting the sizes.
251 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
252 "GLint should be the same size as uint32");
253 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
254 "GLsizei should be the same size as uint32");
255 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
256 "GLfloat should be the same size as float");
258 // TODO(kbr): the use of this anonymous namespace core dumps the
259 // linker on Mac OS X 10.6 when the symbol ordering file is used
260 // namespace {
262 // Returns the address of the first byte after a struct.
263 template <typename T>
264 const void* AddressAfterStruct(const T& pod) {
265 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
268 // Returns the address of the frst byte after the struct or NULL if size >
269 // immediate_data_size.
270 template <typename RETURN_TYPE, typename COMMAND_TYPE>
271 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
272 uint32 size,
273 uint32 immediate_data_size) {
274 return (size <= immediate_data_size) ?
275 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
276 NULL;
279 // Computes the data size for certain gl commands like glUniform.
280 bool ComputeDataSize(
281 GLuint count,
282 size_t size,
283 unsigned int elements_per_unit,
284 uint32* dst) {
285 uint32 value;
286 if (!SafeMultiplyUint32(count, size, &value)) {
287 return false;
289 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
290 return false;
292 *dst = value;
293 return true;
296 // Return true if a character belongs to the ASCII subset as defined in
297 // GLSL ES 1.0 spec section 3.1.
298 static bool CharacterIsValidForGLES(unsigned char c) {
299 // Printing characters are valid except " $ ` @ \ ' DEL.
300 if (c >= 32 && c <= 126 &&
301 c != '"' &&
302 c != '$' &&
303 c != '`' &&
304 c != '@' &&
305 c != '\\' &&
306 c != '\'') {
307 return true;
309 // Horizontal tab, line feed, vertical tab, form feed, carriage return
310 // are also valid.
311 if (c >= 9 && c <= 13) {
312 return true;
315 return false;
318 static bool StringIsValidForGLES(const char* str) {
319 for (; *str; ++str) {
320 if (!CharacterIsValidForGLES(*str)) {
321 return false;
324 return true;
327 // This class prevents any GL errors that occur when it is in scope from
328 // being reported to the client.
329 class ScopedGLErrorSuppressor {
330 public:
331 explicit ScopedGLErrorSuppressor(
332 const char* function_name, ErrorState* error_state);
333 ~ScopedGLErrorSuppressor();
334 private:
335 const char* function_name_;
336 ErrorState* error_state_;
337 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
340 // Temporarily changes a decoder's bound texture and restore it when this
341 // object goes out of scope. Also temporarily switches to using active texture
342 // unit zero in case the client has changed that to something invalid.
343 class ScopedTextureBinder {
344 public:
345 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
346 ~ScopedTextureBinder();
348 private:
349 ContextState* state_;
350 GLenum target_;
351 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
354 // Temporarily changes a decoder's bound render buffer and restore it when this
355 // object goes out of scope.
356 class ScopedRenderBufferBinder {
357 public:
358 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
359 ~ScopedRenderBufferBinder();
361 private:
362 ContextState* state_;
363 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
366 // Temporarily changes a decoder's bound frame buffer and restore it when this
367 // object goes out of scope.
368 class ScopedFrameBufferBinder {
369 public:
370 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
371 ~ScopedFrameBufferBinder();
373 private:
374 GLES2DecoderImpl* decoder_;
375 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
378 // Temporarily changes a decoder's bound frame buffer to a resolved version of
379 // the multisampled offscreen render buffer if that buffer is multisampled, and,
380 // if it is bound or enforce_internal_framebuffer is true. If internal is
381 // true, the resolved framebuffer is not visible to the parent.
382 class ScopedResolvedFrameBufferBinder {
383 public:
384 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
385 bool enforce_internal_framebuffer,
386 bool internal);
387 ~ScopedResolvedFrameBufferBinder();
389 private:
390 GLES2DecoderImpl* decoder_;
391 bool resolve_and_bind_;
392 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
395 class ScopedModifyPixels {
396 public:
397 explicit ScopedModifyPixels(TextureRef* ref);
398 ~ScopedModifyPixels();
400 private:
401 TextureRef* ref_;
404 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
405 if (ref_)
406 ref_->texture()->OnWillModifyPixels();
409 ScopedModifyPixels::~ScopedModifyPixels() {
410 if (ref_)
411 ref_->texture()->OnDidModifyPixels();
414 class ScopedRenderTo {
415 public:
416 explicit ScopedRenderTo(Framebuffer* framebuffer);
417 ~ScopedRenderTo();
419 private:
420 const Framebuffer* framebuffer_;
423 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
424 : framebuffer_(framebuffer) {
425 if (framebuffer)
426 framebuffer_->OnWillRenderTo();
429 ScopedRenderTo::~ScopedRenderTo() {
430 if (framebuffer_)
431 framebuffer_->OnDidRenderTo();
434 // Encapsulates an OpenGL texture.
435 class BackTexture {
436 public:
437 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
438 ~BackTexture();
440 // Create a new render texture.
441 void Create();
443 // Set the initial size and format of a render texture or resize it.
444 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
446 // Copy the contents of the currently bound frame buffer.
447 void Copy(const gfx::Size& size, GLenum format);
449 // Destroy the render texture. This must be explicitly called before
450 // destroying this object.
451 void Destroy();
453 // Invalidate the texture. This can be used when a context is lost and it is
454 // not possible to make it current in order to free the resource.
455 void Invalidate();
457 GLuint id() const {
458 return id_;
461 gfx::Size size() const {
462 return size_;
465 private:
466 MemoryTypeTracker memory_tracker_;
467 ContextState* state_;
468 size_t bytes_allocated_;
469 GLuint id_;
470 gfx::Size size_;
471 DISALLOW_COPY_AND_ASSIGN(BackTexture);
474 // Encapsulates an OpenGL render buffer of any format.
475 class BackRenderbuffer {
476 public:
477 explicit BackRenderbuffer(
478 RenderbufferManager* renderbuffer_manager,
479 MemoryTracker* memory_tracker,
480 ContextState* state);
481 ~BackRenderbuffer();
483 // Create a new render buffer.
484 void Create();
486 // Set the initial size and format of a render buffer or resize it.
487 bool AllocateStorage(const FeatureInfo* feature_info,
488 const gfx::Size& size,
489 GLenum format,
490 GLsizei samples);
492 // Destroy the render buffer. This must be explicitly called before destroying
493 // this object.
494 void Destroy();
496 // Invalidate the render buffer. This can be used when a context is lost and
497 // it is not possible to make it current in order to free the resource.
498 void Invalidate();
500 GLuint id() const {
501 return id_;
504 private:
505 RenderbufferManager* renderbuffer_manager_;
506 MemoryTypeTracker memory_tracker_;
507 ContextState* state_;
508 size_t bytes_allocated_;
509 GLuint id_;
510 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
513 // Encapsulates an OpenGL frame buffer.
514 class BackFramebuffer {
515 public:
516 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
517 ~BackFramebuffer();
519 // Create a new frame buffer.
520 void Create();
522 // Attach a color render buffer to a frame buffer.
523 void AttachRenderTexture(BackTexture* texture);
525 // Attach a render buffer to a frame buffer. Note that this unbinds any
526 // currently bound frame buffer.
527 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
529 // Destroy the frame buffer. This must be explicitly called before destroying
530 // this object.
531 void Destroy();
533 // Invalidate the frame buffer. This can be used when a context is lost and it
534 // is not possible to make it current in order to free the resource.
535 void Invalidate();
537 // See glCheckFramebufferStatusEXT.
538 GLenum CheckStatus();
540 GLuint id() const {
541 return id_;
544 private:
545 GLES2DecoderImpl* decoder_;
546 GLuint id_;
547 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
550 struct FenceCallback {
551 FenceCallback()
552 : fence(gfx::GLFence::Create()) {
553 DCHECK(fence);
555 std::vector<base::Closure> callbacks;
556 scoped_ptr<gfx::GLFence> fence;
559 class AsyncUploadTokenCompletionObserver
560 : public AsyncPixelTransferCompletionObserver {
561 public:
562 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
563 : async_upload_token_(async_upload_token) {
566 void DidComplete(const AsyncMemoryParams& mem_params) override {
567 DCHECK(mem_params.buffer().get());
568 void* data = mem_params.GetDataAddress();
569 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
570 sync->SetAsyncUploadToken(async_upload_token_);
573 private:
574 ~AsyncUploadTokenCompletionObserver() override {}
576 uint32 async_upload_token_;
578 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
581 // } // anonymous namespace.
583 // static
584 const unsigned int GLES2Decoder::kDefaultStencilMask =
585 static_cast<unsigned int>(-1);
587 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
588 uint32* service_texture_id) {
589 return false;
592 GLES2Decoder::GLES2Decoder()
593 : initialized_(false),
594 debug_(false),
595 log_commands_(false),
596 unsafe_es3_apis_enabled_(false) {
599 GLES2Decoder::~GLES2Decoder() {
602 void GLES2Decoder::BeginDecoding() {}
604 void GLES2Decoder::EndDecoding() {}
606 // This class implements GLES2Decoder so we don't have to expose all the GLES2
607 // cmd stuff to outside this class.
608 class GLES2DecoderImpl : public GLES2Decoder,
609 public FramebufferManager::TextureDetachObserver,
610 public ErrorStateClient {
611 public:
612 explicit GLES2DecoderImpl(ContextGroup* group);
613 ~GLES2DecoderImpl() override;
615 // Overridden from AsyncAPIInterface.
616 Error DoCommand(unsigned int command,
617 unsigned int arg_count,
618 const void* args) override;
620 error::Error DoCommands(unsigned int num_commands,
621 const void* buffer,
622 int num_entries,
623 int* entries_processed) override;
625 template <bool DebugImpl>
626 error::Error DoCommandsImpl(unsigned int num_commands,
627 const void* buffer,
628 int num_entries,
629 int* entries_processed);
631 // Overridden from AsyncAPIInterface.
632 const char* GetCommandName(unsigned int command_id) const override;
634 // Overridden from GLES2Decoder.
635 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
636 const scoped_refptr<gfx::GLContext>& context,
637 bool offscreen,
638 const gfx::Size& offscreen_size,
639 const DisallowedFeatures& disallowed_features,
640 const std::vector<int32>& attribs) override;
641 void Destroy(bool have_context) override;
642 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
643 void ProduceFrontBuffer(const Mailbox& mailbox) override;
644 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
645 void UpdateParentTextureInfo();
646 bool MakeCurrent() override;
647 GLES2Util* GetGLES2Util() override { return &util_; }
648 gfx::GLContext* GetGLContext() override { return context_.get(); }
649 ContextGroup* GetContextGroup() override { return group_.get(); }
650 Capabilities GetCapabilities() override;
651 void RestoreState(const ContextState* prev_state) override;
653 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
654 void RestoreAllTextureUnitBindings(
655 const ContextState* prev_state) const override {
656 state_.RestoreAllTextureUnitBindings(prev_state);
658 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
659 state_.RestoreActiveTextureUnitBinding(target);
661 void RestoreBufferBindings() const override {
662 state_.RestoreBufferBindings();
664 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
665 void RestoreProgramBindings() const override {
666 state_.RestoreProgramBindings();
668 void RestoreTextureUnitBindings(unsigned unit) const override {
669 state_.RestoreTextureUnitBindings(unit, NULL);
671 void RestoreFramebufferBindings() const override;
672 void RestoreRenderbufferBindings() override;
673 void RestoreTextureState(unsigned service_id) const override;
675 void ClearAllAttributes() const override;
676 void RestoreAllAttributes() const override;
678 QueryManager* GetQueryManager() override { return query_manager_.get(); }
679 VertexArrayManager* GetVertexArrayManager() override {
680 return vertex_array_manager_.get();
682 ImageManager* GetImageManager() override { return image_manager_.get(); }
684 ValuebufferManager* GetValuebufferManager() override {
685 return valuebuffer_manager();
688 bool ProcessPendingQueries(bool did_finish) override;
690 bool HasMoreIdleWork() override;
691 void PerformIdleWork() override;
693 void WaitForReadPixels(base::Closure callback) override;
695 void SetResizeCallback(
696 const base::Callback<void(gfx::Size, float)>& callback) override;
698 Logger* GetLogger() override;
700 void BeginDecoding() override;
701 void EndDecoding() override;
703 ErrorState* GetErrorState() override;
704 const ContextState* GetContextState() override { return &state_; }
706 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
707 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
709 AsyncPixelTransferManager* GetAsyncPixelTransferManager() override;
710 void ResetAsyncPixelTransferManagerForTest() override;
711 void SetAsyncPixelTransferManagerForTest(
712 AsyncPixelTransferManager* manager) override;
713 void SetIgnoreCachedStateForTest(bool ignore) override;
714 void ProcessFinishedAsyncTransfers();
716 bool GetServiceTextureId(uint32 client_texture_id,
717 uint32* service_texture_id) override;
719 uint32 GetTextureUploadCount() override;
720 base::TimeDelta GetTotalTextureUploadTime() override;
721 base::TimeDelta GetTotalProcessingCommandsTime() override;
722 void AddProcessingCommandsTime(base::TimeDelta) override;
724 // Restores the current state to the user's settings.
725 void RestoreCurrentFramebufferBindings();
727 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
728 void ApplyDirtyState();
730 // These check the state of the currently bound framebuffer or the
731 // backbuffer if no framebuffer is bound.
732 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
733 // check with all attached and enabled color attachments.
734 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
735 bool BoundFramebufferHasDepthAttachment();
736 bool BoundFramebufferHasStencilAttachment();
738 error::ContextLostReason GetContextLostReason() override;
740 // Overridden from FramebufferManager::TextureDetachObserver:
741 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
743 // Overriden from ErrorStateClient.
744 void OnContextLostError() override;
745 void OnOutOfMemoryError() override;
747 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
748 void EnsureRenderbufferBound();
750 // Helpers to facilitate calling into compatible extensions.
751 static void RenderbufferStorageMultisampleHelper(
752 const FeatureInfo* feature_info,
753 GLenum target,
754 GLsizei samples,
755 GLenum internal_format,
756 GLsizei width,
757 GLsizei height);
759 void BlitFramebufferHelper(GLint srcX0,
760 GLint srcY0,
761 GLint srcX1,
762 GLint srcY1,
763 GLint dstX0,
764 GLint dstY0,
765 GLint dstX1,
766 GLint dstY1,
767 GLbitfield mask,
768 GLenum filter);
770 private:
771 friend class ScopedFrameBufferBinder;
772 friend class ScopedResolvedFrameBufferBinder;
773 friend class BackFramebuffer;
775 // Initialize or re-initialize the shader translator.
776 bool InitializeShaderTranslator();
778 void UpdateCapabilities();
780 // Helpers for the glGen and glDelete functions.
781 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
782 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
783 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
784 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
785 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
786 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
787 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
788 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
789 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
790 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
791 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
792 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
793 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
794 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
795 bool GenPathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
796 bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
798 // Helper for async upload token completion notification callback.
799 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
800 uint32 sync_data_shm_id,
801 uint32 sync_data_shm_offset);
805 // Workarounds
806 void OnFboChanged() const;
807 void OnUseFramebuffer() const;
809 error::ContextLostReason GetContextLostReasonFromResetStatus(
810 GLenum reset_status) const;
812 // TODO(gman): Cache these pointers?
813 BufferManager* buffer_manager() {
814 return group_->buffer_manager();
817 RenderbufferManager* renderbuffer_manager() {
818 return group_->renderbuffer_manager();
821 FramebufferManager* framebuffer_manager() {
822 return group_->framebuffer_manager();
825 ValuebufferManager* valuebuffer_manager() {
826 return group_->valuebuffer_manager();
829 PathManager* path_manager() { return group_->path_manager(); }
831 ProgramManager* program_manager() {
832 return group_->program_manager();
835 ShaderManager* shader_manager() {
836 return group_->shader_manager();
839 ShaderTranslatorCache* shader_translator_cache() {
840 return group_->shader_translator_cache();
843 const TextureManager* texture_manager() const {
844 return group_->texture_manager();
847 TextureManager* texture_manager() {
848 return group_->texture_manager();
851 MailboxManager* mailbox_manager() {
852 return group_->mailbox_manager();
855 ImageManager* image_manager() { return image_manager_.get(); }
857 VertexArrayManager* vertex_array_manager() {
858 return vertex_array_manager_.get();
861 MemoryTracker* memory_tracker() {
862 return group_->memory_tracker();
865 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
866 MemoryTracker* tracker = memory_tracker();
867 if (tracker) {
868 return tracker->EnsureGPUMemoryAvailable(estimated_size);
870 return true;
873 bool IsWebGLContext() const {
874 return webgl_version_ == 1 || webgl_version_ == 2;
877 bool IsOffscreenBufferMultisampled() const {
878 return offscreen_target_samples_ > 1;
881 // Creates a Texture for the given texture.
882 TextureRef* CreateTexture(
883 GLuint client_id, GLuint service_id) {
884 return texture_manager()->CreateTexture(client_id, service_id);
887 // Gets the texture info for the given texture. Returns NULL if none exists.
888 TextureRef* GetTexture(GLuint client_id) const {
889 return texture_manager()->GetTexture(client_id);
892 // Deletes the texture info for the given texture.
893 void RemoveTexture(GLuint client_id) {
894 texture_manager()->RemoveTexture(client_id);
897 // Get the size (in pixels) of the currently bound frame buffer (either FBO
898 // or regular back buffer).
899 gfx::Size GetBoundReadFrameBufferSize();
901 // Get the format of the currently bound frame buffer (either FBO or regular
902 // back buffer)
903 GLenum GetBoundReadFrameBufferTextureType();
904 GLenum GetBoundReadFrameBufferInternalFormat();
905 GLenum GetBoundDrawFrameBufferInternalFormat();
907 // Wrapper for CompressedTexImage2D commands.
908 error::Error DoCompressedTexImage2D(
909 GLenum target,
910 GLint level,
911 GLenum internal_format,
912 GLsizei width,
913 GLsizei height,
914 GLint border,
915 GLsizei image_size,
916 const void* data);
918 // Wrapper for CompressedTexImage3D commands.
919 error::Error DoCompressedTexImage3D(
920 GLenum target,
921 GLint level,
922 GLenum internal_format,
923 GLsizei width,
924 GLsizei height,
925 GLsizei depth,
926 GLint border,
927 GLsizei image_size,
928 const void* data);
930 // Wrapper for CompressedTexSubImage2D.
931 void DoCompressedTexSubImage2D(
932 GLenum target,
933 GLint level,
934 GLint xoffset,
935 GLint yoffset,
936 GLsizei width,
937 GLsizei height,
938 GLenum format,
939 GLsizei imageSize,
940 const void * data);
942 // Wrapper for CompressedTexSubImage3D.
943 void DoCompressedTexSubImage3D(
944 GLenum target,
945 GLint level,
946 GLint xoffset,
947 GLint yoffset,
948 GLint zoffset,
949 GLsizei width,
950 GLsizei height,
951 GLsizei depth,
952 GLenum format,
953 GLsizei image_size,
954 const void* data);
956 // Wrapper for CopyTexImage2D.
957 void DoCopyTexImage2D(
958 GLenum target,
959 GLint level,
960 GLenum internal_format,
961 GLint x,
962 GLint y,
963 GLsizei width,
964 GLsizei height,
965 GLint border);
967 // Wrapper for SwapBuffers.
968 void DoSwapBuffers();
970 // Wrapper for SwapInterval.
971 void DoSwapInterval(int interval);
973 // Wrapper for CopyTexSubImage2D.
974 void DoCopyTexSubImage2D(
975 GLenum target,
976 GLint level,
977 GLint xoffset,
978 GLint yoffset,
979 GLint x,
980 GLint y,
981 GLsizei width,
982 GLsizei height);
984 // Validation for TexSubImage2D.
985 bool ValidateTexSubImage2D(
986 error::Error* error,
987 const char* function_name,
988 GLenum target,
989 GLint level,
990 GLint xoffset,
991 GLint yoffset,
992 GLsizei width,
993 GLsizei height,
994 GLenum format,
995 GLenum type,
996 const void * data);
998 // Wrapper for TexSubImage2D.
999 error::Error DoTexSubImage2D(
1000 GLenum target,
1001 GLint level,
1002 GLint xoffset,
1003 GLint yoffset,
1004 GLsizei width,
1005 GLsizei height,
1006 GLenum format,
1007 GLenum type,
1008 const void * data);
1010 // Wrapper for TexSubImage3D.
1011 error::Error DoTexSubImage3D(
1012 GLenum target,
1013 GLint level,
1014 GLint xoffset,
1015 GLint yoffset,
1016 GLint zoffset,
1017 GLsizei width,
1018 GLsizei height,
1019 GLsizei depth,
1020 GLenum format,
1021 GLenum type,
1022 const void * data);
1024 // Extra validation for async tex(Sub)Image2D.
1025 bool ValidateAsyncTransfer(
1026 const char* function_name,
1027 TextureRef* texture_ref,
1028 GLenum target,
1029 GLint level,
1030 const void * data);
1032 // Wrapper for TexImageIOSurface2DCHROMIUM.
1033 void DoTexImageIOSurface2DCHROMIUM(
1034 GLenum target,
1035 GLsizei width,
1036 GLsizei height,
1037 GLuint io_surface_id,
1038 GLuint plane);
1040 void DoCopyTextureCHROMIUM(GLenum target,
1041 GLuint source_id,
1042 GLuint dest_id,
1043 GLenum internal_format,
1044 GLenum dest_type,
1045 GLboolean unpack_flip_y,
1046 GLboolean unpack_premultiply_alpha,
1047 GLboolean unpack_unmultiply_alpha);
1049 void DoCopySubTextureCHROMIUM(GLenum target,
1050 GLuint source_id,
1051 GLuint dest_id,
1052 GLint xoffset,
1053 GLint yoffset,
1054 GLint x,
1055 GLint y,
1056 GLsizei width,
1057 GLsizei height,
1058 GLboolean unpack_flip_y,
1059 GLboolean unpack_premultiply_alpha,
1060 GLboolean unpack_unmultiply_alpha);
1062 void DoCompressedCopyTextureCHROMIUM(GLenum target,
1063 GLuint source_id,
1064 GLuint dest_id);
1066 // Wrapper for TexStorage2DEXT.
1067 void DoTexStorage2DEXT(
1068 GLenum target,
1069 GLint levels,
1070 GLenum internal_format,
1071 GLsizei width,
1072 GLsizei height);
1074 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
1075 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
1076 const GLbyte* key);
1077 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
1078 GLenum target, const GLbyte* data);
1080 void EnsureTextureForClientId(GLenum target, GLuint client_id);
1081 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
1082 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
1083 GLuint client_id);
1085 bool DoIsValuebufferCHROMIUM(GLuint client_id);
1086 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
1087 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
1088 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
1089 void DoUniformValueBufferCHROMIUM(GLint location,
1090 GLenum target,
1091 GLenum subscription);
1093 void DoBindTexImage2DCHROMIUM(
1094 GLenum target,
1095 GLint image_id);
1096 void DoReleaseTexImage2DCHROMIUM(
1097 GLenum target,
1098 GLint image_id);
1100 void DoTraceEndCHROMIUM(void);
1102 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1104 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1106 void DoFlushDriverCachesCHROMIUM(void);
1108 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1109 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1111 // Creates a Program for the given program.
1112 Program* CreateProgram(
1113 GLuint client_id, GLuint service_id) {
1114 return program_manager()->CreateProgram(client_id, service_id);
1117 // Gets the program info for the given program. Returns NULL if none exists.
1118 Program* GetProgram(GLuint client_id) {
1119 return program_manager()->GetProgram(client_id);
1122 #if defined(NDEBUG)
1123 void LogClientServiceMapping(
1124 const char* /* function_name */,
1125 GLuint /* client_id */,
1126 GLuint /* service_id */) {
1128 template<typename T>
1129 void LogClientServiceForInfo(
1130 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1132 #else
1133 void LogClientServiceMapping(
1134 const char* function_name, GLuint client_id, GLuint service_id) {
1135 if (service_logging_) {
1136 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1137 << ": client_id = " << client_id
1138 << ", service_id = " << service_id;
1141 template<typename T>
1142 void LogClientServiceForInfo(
1143 T* info, GLuint client_id, const char* function_name) {
1144 if (info) {
1145 LogClientServiceMapping(function_name, client_id, info->service_id());
1148 #endif
1150 // Gets the program info for the given program. If it's not a program
1151 // generates a GL error. Returns NULL if not program.
1152 Program* GetProgramInfoNotShader(
1153 GLuint client_id, const char* function_name) {
1154 Program* program = GetProgram(client_id);
1155 if (!program) {
1156 if (GetShader(client_id)) {
1157 LOCAL_SET_GL_ERROR(
1158 GL_INVALID_OPERATION, function_name, "shader passed for program");
1159 } else {
1160 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1163 LogClientServiceForInfo(program, client_id, function_name);
1164 return program;
1168 // Creates a Shader for the given shader.
1169 Shader* CreateShader(
1170 GLuint client_id,
1171 GLuint service_id,
1172 GLenum shader_type) {
1173 return shader_manager()->CreateShader(
1174 client_id, service_id, shader_type);
1177 // Gets the shader info for the given shader. Returns NULL if none exists.
1178 Shader* GetShader(GLuint client_id) {
1179 return shader_manager()->GetShader(client_id);
1182 // Gets the shader info for the given shader. If it's not a shader generates a
1183 // GL error. Returns NULL if not shader.
1184 Shader* GetShaderInfoNotProgram(
1185 GLuint client_id, const char* function_name) {
1186 Shader* shader = GetShader(client_id);
1187 if (!shader) {
1188 if (GetProgram(client_id)) {
1189 LOCAL_SET_GL_ERROR(
1190 GL_INVALID_OPERATION, function_name, "program passed for shader");
1191 } else {
1192 LOCAL_SET_GL_ERROR(
1193 GL_INVALID_VALUE, function_name, "unknown shader");
1196 LogClientServiceForInfo(shader, client_id, function_name);
1197 return shader;
1200 // Creates a buffer info for the given buffer.
1201 void CreateBuffer(GLuint client_id, GLuint service_id) {
1202 return buffer_manager()->CreateBuffer(client_id, service_id);
1205 // Gets the buffer info for the given buffer.
1206 Buffer* GetBuffer(GLuint client_id) {
1207 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1208 return buffer;
1211 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1212 // on glDeleteBuffers so we can make sure the user does not try to render
1213 // with deleted buffers.
1214 void RemoveBuffer(GLuint client_id);
1216 // Creates a framebuffer info for the given framebuffer.
1217 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1218 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1221 // Gets the framebuffer info for the given framebuffer.
1222 Framebuffer* GetFramebuffer(GLuint client_id) {
1223 return framebuffer_manager()->GetFramebuffer(client_id);
1226 // Removes the framebuffer info for the given framebuffer.
1227 void RemoveFramebuffer(GLuint client_id) {
1228 framebuffer_manager()->RemoveFramebuffer(client_id);
1231 // Creates a renderbuffer info for the given renderbuffer.
1232 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1233 return renderbuffer_manager()->CreateRenderbuffer(
1234 client_id, service_id);
1237 // Gets the renderbuffer info for the given renderbuffer.
1238 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1239 return renderbuffer_manager()->GetRenderbuffer(client_id);
1242 // Removes the renderbuffer info for the given renderbuffer.
1243 void RemoveRenderbuffer(GLuint client_id) {
1244 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1247 // Creates a valuebuffer info for the given valuebuffer.
1248 void CreateValuebuffer(GLuint client_id) {
1249 return valuebuffer_manager()->CreateValuebuffer(client_id);
1252 // Gets the valuebuffer info for a given valuebuffer.
1253 Valuebuffer* GetValuebuffer(GLuint client_id) {
1254 return valuebuffer_manager()->GetValuebuffer(client_id);
1257 // Removes the valuebuffer info for the given valuebuffer.
1258 void RemoveValuebuffer(GLuint client_id) {
1259 valuebuffer_manager()->RemoveValuebuffer(client_id);
1262 // Gets the vertex attrib manager for the given vertex array.
1263 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1264 VertexAttribManager* info =
1265 vertex_array_manager()->GetVertexAttribManager(client_id);
1266 return info;
1269 // Removes the vertex attrib manager for the given vertex array.
1270 void RemoveVertexAttribManager(GLuint client_id) {
1271 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1274 // Creates a vertex attrib manager for the given vertex array.
1275 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1276 GLuint client_id,
1277 GLuint service_id,
1278 bool client_visible) {
1279 return vertex_array_manager()->CreateVertexAttribManager(
1280 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1283 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1284 void DoBindUniformLocationCHROMIUM(
1285 GLuint client_id, GLint location, const char* name);
1287 error::Error GetAttribLocationHelper(
1288 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1289 const std::string& name_str);
1291 error::Error GetUniformLocationHelper(
1292 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1293 const std::string& name_str);
1295 error::Error GetFragDataLocationHelper(
1296 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1297 const std::string& name_str);
1299 // Wrapper for glShaderSource.
1300 void DoShaderSource(
1301 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1303 // Wrapper for glTransformFeedbackVaryings.
1304 void DoTransformFeedbackVaryings(
1305 GLuint client_program_id, GLsizei count, const char* const* varyings,
1306 GLenum buffer_mode);
1308 // Clear any textures used by the current program.
1309 bool ClearUnclearedTextures();
1311 // Clears any uncleared attachments attached to the given frame buffer.
1312 // Returns false if there was a generated GL error.
1313 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1315 // overridden from GLES2Decoder
1316 bool ClearLevel(Texture* texture,
1317 unsigned target,
1318 int level,
1319 unsigned format,
1320 unsigned type,
1321 int xoffset,
1322 int yoffset,
1323 int width,
1324 int height) override;
1326 // Restore all GL state that affects clearing.
1327 void RestoreClearState();
1329 // Remembers the state of some capabilities.
1330 // Returns: true if glEnable/glDisable should actually be called.
1331 bool SetCapabilityState(GLenum cap, bool enabled);
1333 // Check that the currently bound framebuffers are valid.
1334 // Generates GL error if not.
1335 bool CheckBoundFramebuffersValid(const char* func_name);
1337 // Check that the currently bound read framebuffer has a color image
1338 // attached. Generates GL error if not.
1339 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1341 // Check that the currently bound read framebuffer's color image
1342 // isn't the target texture of the glCopyTex{Sub}Image2D.
1343 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1345 // Check if a framebuffer meets our requirements.
1346 bool CheckFramebufferValid(
1347 Framebuffer* framebuffer,
1348 GLenum target,
1349 const char* func_name);
1351 // Check if the current valuebuffer exists and is valid. If not generates
1352 // the appropriate GL error. Returns true if the current valuebuffer is in
1353 // a usable state.
1354 bool CheckCurrentValuebuffer(const char* function_name);
1356 // Check if the current valuebuffer exists and is valiud and that the
1357 // value buffer is actually subscribed to the given subscription
1358 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1359 const char* function_name);
1361 // Check if the location can be used for the given subscription target. If not
1362 // generates the appropriate GL error. Returns true if the location is usable
1363 bool CheckSubscriptionTarget(GLint location,
1364 GLenum subscription,
1365 const char* function_name);
1367 // Checks if the current program exists and is valid. If not generates the
1368 // appropriate GL error. Returns true if the current program is in a usable
1369 // state.
1370 bool CheckCurrentProgram(const char* function_name);
1372 // Checks if the current program exists and is valid and that location is not
1373 // -1. If the current program is not valid generates the appropriate GL
1374 // error. Returns true if the current program is in a usable state and
1375 // location is not -1.
1376 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1378 // Checks if the current program samples a texture that is also the color
1379 // image of the current bound framebuffer, i.e., the source and destination
1380 // of the draw operation are the same.
1381 bool CheckDrawingFeedbackLoops();
1383 // Checks if |api_type| is valid for the given uniform
1384 // If the api type is not valid generates the appropriate GL
1385 // error. Returns true if |api_type| is valid for the uniform
1386 bool CheckUniformForApiType(const Program::UniformInfo* info,
1387 const char* function_name,
1388 Program::UniformApiType api_type);
1390 // Gets the type of a uniform for a location in the current program. Sets GL
1391 // errors if the current program is not valid. Returns true if the current
1392 // program is valid and the location exists. Adjusts count so it
1393 // does not overflow the uniform.
1394 bool PrepForSetUniformByLocation(GLint fake_location,
1395 const char* function_name,
1396 Program::UniformApiType api_type,
1397 GLint* real_location,
1398 GLenum* type,
1399 GLsizei* count);
1401 // Gets the service id for any simulated backbuffer fbo.
1402 GLuint GetBackbufferServiceId() const;
1404 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1405 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1407 // Helper for glGetVertexAttrib
1408 void GetVertexAttribHelper(
1409 const VertexAttrib* attrib, GLenum pname, GLint* param);
1411 // Wrapper for glActiveTexture
1412 void DoActiveTexture(GLenum texture_unit);
1414 // Wrapper for glAttachShader
1415 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1417 // Wrapper for glBindBuffer since we need to track the current targets.
1418 void DoBindBuffer(GLenum target, GLuint buffer);
1420 // Wrapper for glBindFramebuffer since we need to track the current targets.
1421 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1423 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1424 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1426 // Wrapper for glBindTexture since we need to track the current targets.
1427 void DoBindTexture(GLenum target, GLuint texture);
1429 // Wrapper for glBindVertexArrayOES
1430 void DoBindVertexArrayOES(GLuint array);
1431 void EmulateVertexArrayState();
1433 // Wrapper for glBlitFramebufferCHROMIUM.
1434 void DoBlitFramebufferCHROMIUM(
1435 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1436 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1437 GLbitfield mask, GLenum filter);
1439 // Wrapper for glBufferSubData.
1440 void DoBufferSubData(
1441 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1443 // Wrapper for glCheckFramebufferStatus
1444 GLenum DoCheckFramebufferStatus(GLenum target);
1446 // Wrapper for glClear
1447 error::Error DoClear(GLbitfield mask);
1449 // Wrappers for various state.
1450 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1451 void DoSampleCoverage(GLclampf value, GLboolean invert);
1453 // Wrapper for glCompileShader.
1454 void DoCompileShader(GLuint shader);
1456 // Wrapper for glDetachShader
1457 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1459 // Wrapper for glDisable
1460 void DoDisable(GLenum cap);
1462 // Wrapper for glDisableVertexAttribArray.
1463 void DoDisableVertexAttribArray(GLuint index);
1465 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1466 // attachments.
1467 void DoDiscardFramebufferEXT(GLenum target,
1468 GLsizei numAttachments,
1469 const GLenum* attachments);
1471 // Wrapper for glEnable
1472 void DoEnable(GLenum cap);
1474 // Wrapper for glEnableVertexAttribArray.
1475 void DoEnableVertexAttribArray(GLuint index);
1477 // Wrapper for glFinish.
1478 void DoFinish();
1480 // Wrapper for glFlush.
1481 void DoFlush();
1483 // Wrapper for glFramebufferRenderbufffer.
1484 void DoFramebufferRenderbuffer(
1485 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1486 GLuint renderbuffer);
1488 // Wrapper for glFramebufferTexture2D.
1489 void DoFramebufferTexture2D(
1490 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1491 GLint level);
1493 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1494 void DoFramebufferTexture2DMultisample(
1495 GLenum target, GLenum attachment, GLenum textarget,
1496 GLuint texture, GLint level, GLsizei samples);
1498 // Common implementation for both DoFramebufferTexture2D wrappers.
1499 void DoFramebufferTexture2DCommon(const char* name,
1500 GLenum target, GLenum attachment, GLenum textarget,
1501 GLuint texture, GLint level, GLsizei samples);
1503 // Wrapper for glFramebufferTextureLayer.
1504 void DoFramebufferTextureLayer(
1505 GLenum target, GLenum attachment, GLuint texture, GLint level,
1506 GLint layer);
1508 // Wrapper for glGenerateMipmap
1509 void DoGenerateMipmap(GLenum target);
1511 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1512 // to account for different pname values defined in different extension
1513 // variants.
1514 GLenum AdjustGetPname(GLenum pname);
1516 // Wrapper for DoGetBooleanv.
1517 void DoGetBooleanv(GLenum pname, GLboolean* params);
1519 // Wrapper for DoGetFloatv.
1520 void DoGetFloatv(GLenum pname, GLfloat* params);
1522 // Wrapper for glGetFramebufferAttachmentParameteriv.
1523 void DoGetFramebufferAttachmentParameteriv(
1524 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1526 // Wrapper for glGetInteger64v.
1527 void DoGetInteger64v(GLenum pname, GLint64* params);
1529 // Wrapper for glGetIntegerv.
1530 void DoGetIntegerv(GLenum pname, GLint* params);
1532 // Gets the max value in a range in a buffer.
1533 GLuint DoGetMaxValueInBufferCHROMIUM(
1534 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1536 // Wrapper for glGetBufferParameteriv.
1537 void DoGetBufferParameteriv(
1538 GLenum target, GLenum pname, GLint* params);
1540 // Wrapper for glGetProgramiv.
1541 void DoGetProgramiv(
1542 GLuint program_id, GLenum pname, GLint* params);
1544 // Wrapper for glRenderbufferParameteriv.
1545 void DoGetRenderbufferParameteriv(
1546 GLenum target, GLenum pname, GLint* params);
1548 // Wrapper for glGetShaderiv
1549 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1551 // Wrappers for glGetTexParameter.
1552 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1553 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1554 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1556 // Wrappers for glGetVertexAttrib.
1557 template <typename T>
1558 void DoGetVertexAttribImpl(GLuint index, GLenum pname, T* params);
1559 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
1560 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
1561 void DoGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
1562 void DoGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
1564 // Wrappers for glIsXXX functions.
1565 bool DoIsEnabled(GLenum cap);
1566 bool DoIsBuffer(GLuint client_id);
1567 bool DoIsFramebuffer(GLuint client_id);
1568 bool DoIsProgram(GLuint client_id);
1569 bool DoIsRenderbuffer(GLuint client_id);
1570 bool DoIsShader(GLuint client_id);
1571 bool DoIsTexture(GLuint client_id);
1572 bool DoIsVertexArrayOES(GLuint client_id);
1573 bool DoIsPathCHROMIUM(GLuint client_id);
1575 // Wrapper for glLinkProgram
1576 void DoLinkProgram(GLuint program);
1578 // Wrapper for glRenderbufferStorage.
1579 void DoRenderbufferStorage(
1580 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1582 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1583 void DoRenderbufferStorageMultisampleCHROMIUM(
1584 GLenum target, GLsizei samples, GLenum internalformat,
1585 GLsizei width, GLsizei height);
1587 // Handler for glRenderbufferStorageMultisampleEXT
1588 // (multisampled_render_to_texture).
1589 void DoRenderbufferStorageMultisampleEXT(
1590 GLenum target, GLsizei samples, GLenum internalformat,
1591 GLsizei width, GLsizei height);
1593 // Common validation for multisample extensions.
1594 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1595 GLenum internalformat,
1596 GLsizei width,
1597 GLsizei height);
1599 // Verifies that the currently bound multisample renderbuffer is valid
1600 // Very slow! Only done on platforms with driver bugs that return invalid
1601 // buffers under memory pressure
1602 bool VerifyMultisampleRenderbufferIntegrity(
1603 GLuint renderbuffer, GLenum format);
1605 // Wrapper for glReleaseShaderCompiler.
1606 void DoReleaseShaderCompiler() { }
1608 // Wrappers for glSamplerParameter*v functions.
1609 void DoSamplerParameterfv(
1610 GLuint sampler, GLenum pname, const GLfloat* params);
1611 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1613 // Wrappers for glTexParameter functions.
1614 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1615 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1616 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1617 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1619 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1620 // spec only these 2 functions can be used to set sampler uniforms.
1621 void DoUniform1i(GLint fake_location, GLint v0);
1622 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1623 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1624 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1625 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1627 // Wrappers for glUniformfv because some drivers don't correctly accept
1628 // bool uniforms.
1629 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1630 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1631 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1632 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1634 void DoUniformMatrix2fv(
1635 GLint fake_location, GLsizei count, GLboolean transpose,
1636 const GLfloat* value);
1637 void DoUniformMatrix3fv(
1638 GLint fake_location, GLsizei count, GLboolean transpose,
1639 const GLfloat* value);
1640 void DoUniformMatrix4fv(
1641 GLint fake_location, GLsizei count, GLboolean transpose,
1642 const GLfloat* value);
1644 template <typename T>
1645 bool SetVertexAttribValue(
1646 const char* function_name, GLuint index, const T* value);
1648 // Wrappers for glVertexAttrib??
1649 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1650 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1651 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1652 void DoVertexAttrib4f(
1653 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1654 void DoVertexAttrib1fv(GLuint index, const GLfloat* v);
1655 void DoVertexAttrib2fv(GLuint index, const GLfloat* v);
1656 void DoVertexAttrib3fv(GLuint index, const GLfloat* v);
1657 void DoVertexAttrib4fv(GLuint index, const GLfloat* v);
1658 void DoVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
1659 void DoVertexAttribI4iv(GLuint index, const GLint* v);
1660 void DoVertexAttribI4ui(
1661 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
1662 void DoVertexAttribI4uiv(GLuint index, const GLuint* v);
1664 // Wrapper for glViewport
1665 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1667 // Wrapper for glUseProgram
1668 void DoUseProgram(GLuint program);
1670 // Wrapper for glValidateProgram.
1671 void DoValidateProgram(GLuint program_client_id);
1673 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1674 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1675 void DoPopGroupMarkerEXT(void);
1677 // Gets the number of values that will be returned by glGetXXX. Returns
1678 // false if pname is unknown.
1679 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1681 // Checks if the current program and vertex attributes are valid for drawing.
1682 bool IsDrawValid(
1683 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1684 GLsizei primcount);
1686 // Returns true if successful, simulated will be true if attrib0 was
1687 // simulated.
1688 bool SimulateAttrib0(
1689 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1690 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1692 // If an image is bound to texture, this will call Will/DidUseTexImage
1693 // if needed.
1694 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1695 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1697 // Returns false if textures were replaced.
1698 bool PrepareTexturesForRender();
1699 void RestoreStateForTextures();
1701 // Returns true if GL_FIXED attribs were simulated.
1702 bool SimulateFixedAttribs(
1703 const char* function_name,
1704 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1705 void RestoreStateForSimulatedFixedAttribs();
1707 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1708 // cases (primcount is always 1 for non-instanced).
1709 error::Error DoDrawArrays(
1710 const char* function_name,
1711 bool instanced, GLenum mode, GLint first, GLsizei count,
1712 GLsizei primcount);
1713 error::Error DoDrawElements(
1714 const char* function_name,
1715 bool instanced, GLenum mode, GLsizei count, GLenum type,
1716 int32 offset, GLsizei primcount);
1718 GLenum GetBindTargetForSamplerType(GLenum type) {
1719 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1720 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1721 switch (type) {
1722 case GL_SAMPLER_2D:
1723 return GL_TEXTURE_2D;
1724 case GL_SAMPLER_CUBE:
1725 return GL_TEXTURE_CUBE_MAP;
1726 case GL_SAMPLER_EXTERNAL_OES:
1727 return GL_TEXTURE_EXTERNAL_OES;
1728 case GL_SAMPLER_2D_RECT_ARB:
1729 return GL_TEXTURE_RECTANGLE_ARB;
1732 NOTREACHED();
1733 return 0;
1736 // Gets the framebuffer info for a particular target.
1737 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1738 Framebuffer* framebuffer = NULL;
1739 switch (target) {
1740 case GL_FRAMEBUFFER:
1741 case GL_DRAW_FRAMEBUFFER_EXT:
1742 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1743 break;
1744 case GL_READ_FRAMEBUFFER_EXT:
1745 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1746 break;
1747 default:
1748 NOTREACHED();
1749 break;
1751 return framebuffer;
1754 Renderbuffer* GetRenderbufferInfoForTarget(
1755 GLenum target) {
1756 Renderbuffer* renderbuffer = NULL;
1757 switch (target) {
1758 case GL_RENDERBUFFER:
1759 renderbuffer = state_.bound_renderbuffer.get();
1760 break;
1761 default:
1762 NOTREACHED();
1763 break;
1765 return renderbuffer;
1768 // Validates the program and location for a glGetUniform call and returns
1769 // a SizeResult setup to receive the result. Returns true if glGetUniform
1770 // should be called.
1771 template <class T>
1772 bool GetUniformSetup(GLuint program,
1773 GLint fake_location,
1774 uint32 shm_id,
1775 uint32 shm_offset,
1776 error::Error* error,
1777 GLint* real_location,
1778 GLuint* service_id,
1779 SizedResult<T>** result,
1780 GLenum* result_type,
1781 GLsizei* result_size);
1783 bool WasContextLost() const override;
1784 bool WasContextLostByRobustnessExtension() const override;
1785 void MarkContextLost(error::ContextLostReason reason) override;
1786 bool CheckResetStatus();
1788 #if defined(OS_MACOSX)
1789 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1790 #endif
1792 bool GetCompressedTexSizeInBytes(
1793 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1794 GLenum format, GLsizei* size_in_bytes);
1796 bool ValidateCompressedTexDimensions(
1797 const char* function_name, GLenum target, GLint level,
1798 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1799 bool ValidateCompressedTexFuncData(
1800 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1801 GLenum format, GLsizei size);
1802 bool ValidateCompressedTexSubDimensions(
1803 const char* function_name,
1804 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1805 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1806 Texture* texture);
1807 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1808 GLenum target,
1809 TextureRef* source_texture_ref,
1810 TextureRef* dest_texture_ref,
1811 GLenum dest_internal_format);
1812 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name,
1813 GLenum target,
1814 TextureRef* source_texture_ref,
1815 TextureRef* dest_texture_ref);
1817 void RenderWarning(const char* filename, int line, const std::string& msg);
1818 void PerformanceWarning(
1819 const char* filename, int line, const std::string& msg);
1821 const FeatureInfo::FeatureFlags& features() const {
1822 return feature_info_->feature_flags();
1825 const FeatureInfo::Workarounds& workarounds() const {
1826 return feature_info_->workarounds();
1829 bool ShouldDeferDraws() {
1830 return !offscreen_target_frame_buffer_.get() &&
1831 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1832 surface_->DeferDraws();
1835 bool ShouldDeferReads() {
1836 return !offscreen_target_frame_buffer_.get() &&
1837 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1838 surface_->DeferDraws();
1841 bool IsRobustnessSupported() {
1842 return has_robustness_extension_ &&
1843 context_->WasAllocatedUsingRobustnessExtension();
1846 error::Error WillAccessBoundFramebufferForDraw() {
1847 if (ShouldDeferDraws())
1848 return error::kDeferCommandUntilLater;
1849 if (!offscreen_target_frame_buffer_.get() &&
1850 !framebuffer_state_.bound_draw_framebuffer.get() &&
1851 !surface_->SetBackbufferAllocation(true))
1852 return error::kLostContext;
1853 return error::kNoError;
1856 error::Error WillAccessBoundFramebufferForRead() {
1857 if (ShouldDeferReads())
1858 return error::kDeferCommandUntilLater;
1859 if (!offscreen_target_frame_buffer_.get() &&
1860 !framebuffer_state_.bound_read_framebuffer.get() &&
1861 !surface_->SetBackbufferAllocation(true))
1862 return error::kLostContext;
1863 return error::kNoError;
1866 // Set remaining commands to process to 0 to force DoCommands to return
1867 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1868 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1870 void ProcessPendingReadPixels(bool did_finish);
1871 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1873 // Generate a member function prototype for each command in an automated and
1874 // typesafe way.
1875 #define GLES2_CMD_OP(name) \
1876 Error Handle##name(uint32 immediate_data_size, const void* data);
1878 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1880 #undef GLES2_CMD_OP
1882 // The GL context this decoder renders to on behalf of the client.
1883 scoped_refptr<gfx::GLSurface> surface_;
1884 scoped_refptr<gfx::GLContext> context_;
1886 // The ContextGroup for this decoder uses to track resources.
1887 scoped_refptr<ContextGroup> group_;
1889 DebugMarkerManager debug_marker_manager_;
1890 Logger logger_;
1892 // All the state for this context.
1893 ContextState state_;
1895 // Current width and height of the offscreen frame buffer.
1896 gfx::Size offscreen_size_;
1898 // Util to help with GL.
1899 GLES2Util util_;
1901 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1902 GLuint attrib_0_buffer_id_;
1904 // The value currently in attrib_0.
1905 Vec4 attrib_0_value_;
1907 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1908 bool attrib_0_buffer_matches_value_;
1910 // The size of attrib 0.
1911 GLsizei attrib_0_size_;
1913 // The buffer used to simulate GL_FIXED attribs.
1914 GLuint fixed_attrib_buffer_id_;
1916 // The size of fiixed attrib buffer.
1917 GLsizei fixed_attrib_buffer_size_;
1919 // The offscreen frame buffer that the client renders to. With EGL, the
1920 // depth and stencil buffers are separate. With regular GL there is a single
1921 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1922 // offscreen_target_stencil_render_buffer_ is unused.
1923 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1924 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1925 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1926 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1927 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1928 GLenum offscreen_target_color_format_;
1929 GLenum offscreen_target_depth_format_;
1930 GLenum offscreen_target_stencil_format_;
1931 GLsizei offscreen_target_samples_;
1932 GLboolean offscreen_target_buffer_preserved_;
1934 // The copy that is saved when SwapBuffers is called.
1935 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1936 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1937 scoped_refptr<TextureRef>
1938 offscreen_saved_color_texture_info_;
1940 // The copy that is used as the destination for multi-sample resolves.
1941 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1942 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1943 GLenum offscreen_saved_color_format_;
1945 scoped_ptr<QueryManager> query_manager_;
1947 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1949 scoped_ptr<ImageManager> image_manager_;
1951 base::Callback<void(gfx::Size, float)> resize_callback_;
1953 WaitSyncPointCallback wait_sync_point_callback_;
1955 ShaderCacheCallback shader_cache_callback_;
1957 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1959 // The format of the back buffer_
1960 GLenum back_buffer_color_format_;
1961 bool back_buffer_has_depth_;
1962 bool back_buffer_has_stencil_;
1964 bool surfaceless_;
1966 // Backbuffer attachments that are currently undefined.
1967 uint32 backbuffer_needs_clear_bits_;
1969 // The current decoder error communicates the decoder error through command
1970 // processing functions that do not return the error value. Should be set only
1971 // if not returning an error.
1972 error::Error current_decoder_error_;
1974 bool use_shader_translator_;
1975 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
1976 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
1978 DisallowedFeatures disallowed_features_;
1980 // Cached from ContextGroup
1981 const Validators* validators_;
1982 scoped_refptr<FeatureInfo> feature_info_;
1984 int frame_number_;
1986 // Number of commands remaining to be processed in DoCommands().
1987 int commands_to_process_;
1989 bool has_robustness_extension_;
1990 error::ContextLostReason context_lost_reason_;
1991 bool context_was_lost_;
1992 bool reset_by_robustness_extension_;
1993 bool supports_post_sub_buffer_;
1995 // Indicates whether this is a context for WebGL1, WebGL2, or others.
1996 // 0: other types
1997 // 1: WebGL 1
1998 // 2: WebGL 2
1999 unsigned webgl_version_;
2001 // These flags are used to override the state of the shared feature_info_
2002 // member. Because the same FeatureInfo instance may be shared among many
2003 // contexts, the assumptions on the availablity of extensions in WebGL
2004 // contexts may be broken. These flags override the shared state to preserve
2005 // WebGL semantics.
2006 bool derivatives_explicitly_enabled_;
2007 bool frag_depth_explicitly_enabled_;
2008 bool draw_buffers_explicitly_enabled_;
2009 bool shader_texture_lod_explicitly_enabled_;
2011 bool compile_shader_always_succeeds_;
2013 // An optional behaviour to lose the context and group when OOM.
2014 bool lose_context_when_out_of_memory_;
2016 // Log extra info.
2017 bool service_logging_;
2019 #if defined(OS_MACOSX)
2020 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
2021 TextureToIOSurfaceMap texture_to_io_surface_map_;
2022 #endif
2024 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
2025 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
2027 // Cached values of the currently assigned viewport dimensions.
2028 GLsizei viewport_max_width_;
2029 GLsizei viewport_max_height_;
2031 // Command buffer stats.
2032 base::TimeDelta total_processing_commands_time_;
2034 // States related to each manager.
2035 DecoderTextureState texture_state_;
2036 DecoderFramebufferState framebuffer_state_;
2038 scoped_ptr<GPUTracer> gpu_tracer_;
2039 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
2040 const unsigned char* cb_command_trace_category_;
2041 const unsigned char* gpu_decoder_category_;
2042 int gpu_trace_level_;
2043 bool gpu_trace_commands_;
2044 bool gpu_debug_commands_;
2046 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
2048 // Used to validate multisample renderbuffers if needed
2049 GLuint validation_texture_;
2050 GLuint validation_fbo_multisample_;
2051 GLuint validation_fbo_;
2053 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
2054 uint32 immediate_data_size,
2055 const void* data);
2057 // A struct to hold info about each command.
2058 struct CommandInfo {
2059 CmdHandler cmd_handler;
2060 uint8 arg_flags; // How to handle the arguments for this command
2061 uint8 cmd_flags; // How to handle this command
2062 uint16 arg_count; // How many arguments are expected for this command.
2065 // A table of CommandInfo for all the commands.
2066 static const CommandInfo command_info[kNumCommands - kStartPoint];
2068 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
2071 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
2072 #define GLES2_CMD_OP(name) \
2074 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2075 cmds::name::cmd_flags, \
2076 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2078 , /* NOLINT */
2079 GLES2_COMMAND_LIST(GLES2_CMD_OP)
2080 #undef GLES2_CMD_OP
2083 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2084 const char* function_name, ErrorState* error_state)
2085 : function_name_(function_name),
2086 error_state_(error_state) {
2087 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
2090 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2091 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
2094 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
2095 TextureUnit& info = state->texture_units[0];
2096 GLuint last_id;
2097 scoped_refptr<TextureRef> texture_ref;
2098 switch (target) {
2099 case GL_TEXTURE_2D:
2100 texture_ref = info.bound_texture_2d;
2101 break;
2102 case GL_TEXTURE_CUBE_MAP:
2103 texture_ref = info.bound_texture_cube_map;
2104 break;
2105 case GL_TEXTURE_EXTERNAL_OES:
2106 texture_ref = info.bound_texture_external_oes;
2107 break;
2108 case GL_TEXTURE_RECTANGLE_ARB:
2109 texture_ref = info.bound_texture_rectangle_arb;
2110 break;
2111 default:
2112 NOTREACHED();
2113 break;
2115 if (texture_ref.get()) {
2116 last_id = texture_ref->service_id();
2117 } else {
2118 last_id = 0;
2121 glBindTexture(target, last_id);
2122 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2125 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2126 GLuint id,
2127 GLenum target)
2128 : state_(state),
2129 target_(target) {
2130 ScopedGLErrorSuppressor suppressor(
2131 "ScopedTextureBinder::ctor", state_->GetErrorState());
2133 // TODO(apatrick): Check if there are any other states that need to be reset
2134 // before binding a new texture.
2135 glActiveTexture(GL_TEXTURE0);
2136 glBindTexture(target, id);
2139 ScopedTextureBinder::~ScopedTextureBinder() {
2140 ScopedGLErrorSuppressor suppressor(
2141 "ScopedTextureBinder::dtor", state_->GetErrorState());
2142 RestoreCurrentTextureBindings(state_, target_);
2145 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2146 GLuint id)
2147 : state_(state) {
2148 ScopedGLErrorSuppressor suppressor(
2149 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2150 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2153 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2154 ScopedGLErrorSuppressor suppressor(
2155 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2156 state_->RestoreRenderbufferBindings();
2159 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2160 GLuint id)
2161 : decoder_(decoder) {
2162 ScopedGLErrorSuppressor suppressor(
2163 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2164 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2165 decoder->OnFboChanged();
2168 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2169 ScopedGLErrorSuppressor suppressor(
2170 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2171 decoder_->RestoreCurrentFramebufferBindings();
2174 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2175 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2176 : decoder_(decoder) {
2177 resolve_and_bind_ = (
2178 decoder_->offscreen_target_frame_buffer_.get() &&
2179 decoder_->IsOffscreenBufferMultisampled() &&
2180 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2181 enforce_internal_framebuffer));
2182 if (!resolve_and_bind_)
2183 return;
2185 ScopedGLErrorSuppressor suppressor(
2186 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2187 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2188 decoder_->offscreen_target_frame_buffer_->id());
2189 GLuint targetid;
2190 if (internal) {
2191 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2192 decoder_->offscreen_resolved_frame_buffer_.reset(
2193 new BackFramebuffer(decoder_));
2194 decoder_->offscreen_resolved_frame_buffer_->Create();
2195 decoder_->offscreen_resolved_color_texture_.reset(
2196 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2197 decoder_->offscreen_resolved_color_texture_->Create();
2199 DCHECK(decoder_->offscreen_saved_color_format_);
2200 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2201 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2202 false);
2203 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2204 decoder_->offscreen_resolved_color_texture_.get());
2205 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2206 GL_FRAMEBUFFER_COMPLETE) {
2207 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2208 << "because offscreen resolved FBO was incomplete.";
2209 return;
2212 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2213 } else {
2214 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2216 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2217 const int width = decoder_->offscreen_size_.width();
2218 const int height = decoder_->offscreen_size_.height();
2219 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2220 decoder->BlitFramebufferHelper(0,
2222 width,
2223 height,
2226 width,
2227 height,
2228 GL_COLOR_BUFFER_BIT,
2229 GL_NEAREST);
2230 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2233 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2234 if (!resolve_and_bind_)
2235 return;
2237 ScopedGLErrorSuppressor suppressor(
2238 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2239 decoder_->RestoreCurrentFramebufferBindings();
2240 if (decoder_->state_.enable_flags.scissor_test) {
2241 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2245 BackTexture::BackTexture(
2246 MemoryTracker* memory_tracker,
2247 ContextState* state)
2248 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2249 state_(state),
2250 bytes_allocated_(0),
2251 id_(0) {
2254 BackTexture::~BackTexture() {
2255 // This does not destroy the render texture because that would require that
2256 // the associated GL context was current. Just check that it was explicitly
2257 // destroyed.
2258 DCHECK_EQ(id_, 0u);
2261 void BackTexture::Create() {
2262 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2263 state_->GetErrorState());
2264 Destroy();
2265 glGenTextures(1, &id_);
2266 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2267 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2268 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2269 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2270 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2272 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2273 // never called on an offscreen context, no data will ever be uploaded to the
2274 // saved offscreen color texture (it is deferred until to when SwapBuffers
2275 // is called). My idea is that some nvidia drivers might have a bug where
2276 // deleting a texture that has never been populated might cause a
2277 // crash.
2278 glTexImage2D(
2279 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2281 bytes_allocated_ = 16u * 16u * 4u;
2282 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2285 bool BackTexture::AllocateStorage(
2286 const gfx::Size& size, GLenum format, bool zero) {
2287 DCHECK_NE(id_, 0u);
2288 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2289 state_->GetErrorState());
2290 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2291 uint32 image_size = 0;
2292 GLES2Util::ComputeImageDataSizes(
2293 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2294 NULL, NULL);
2296 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2297 return false;
2300 scoped_ptr<char[]> zero_data;
2301 if (zero) {
2302 zero_data.reset(new char[image_size]);
2303 memset(zero_data.get(), 0, image_size);
2306 glTexImage2D(GL_TEXTURE_2D,
2307 0, // mip level
2308 format,
2309 size.width(),
2310 size.height(),
2311 0, // border
2312 format,
2313 GL_UNSIGNED_BYTE,
2314 zero_data.get());
2316 size_ = size;
2318 bool success = glGetError() == GL_NO_ERROR;
2319 if (success) {
2320 memory_tracker_.TrackMemFree(bytes_allocated_);
2321 bytes_allocated_ = image_size;
2322 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2324 return success;
2327 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2328 DCHECK_NE(id_, 0u);
2329 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2330 state_->GetErrorState());
2331 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2332 glCopyTexImage2D(GL_TEXTURE_2D,
2333 0, // level
2334 format,
2335 0, 0,
2336 size.width(),
2337 size.height(),
2338 0); // border
2341 void BackTexture::Destroy() {
2342 if (id_ != 0) {
2343 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2344 state_->GetErrorState());
2345 glDeleteTextures(1, &id_);
2346 id_ = 0;
2348 memory_tracker_.TrackMemFree(bytes_allocated_);
2349 bytes_allocated_ = 0;
2352 void BackTexture::Invalidate() {
2353 id_ = 0;
2356 BackRenderbuffer::BackRenderbuffer(
2357 RenderbufferManager* renderbuffer_manager,
2358 MemoryTracker* memory_tracker,
2359 ContextState* state)
2360 : renderbuffer_manager_(renderbuffer_manager),
2361 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2362 state_(state),
2363 bytes_allocated_(0),
2364 id_(0) {
2367 BackRenderbuffer::~BackRenderbuffer() {
2368 // This does not destroy the render buffer because that would require that
2369 // the associated GL context was current. Just check that it was explicitly
2370 // destroyed.
2371 DCHECK_EQ(id_, 0u);
2374 void BackRenderbuffer::Create() {
2375 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2376 state_->GetErrorState());
2377 Destroy();
2378 glGenRenderbuffersEXT(1, &id_);
2381 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2382 const gfx::Size& size,
2383 GLenum format,
2384 GLsizei samples) {
2385 ScopedGLErrorSuppressor suppressor(
2386 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2387 ScopedRenderBufferBinder binder(state_, id_);
2389 uint32 estimated_size = 0;
2390 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2391 size.width(), size.height(), samples, format, &estimated_size)) {
2392 return false;
2395 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2396 return false;
2399 if (samples <= 1) {
2400 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2401 format,
2402 size.width(),
2403 size.height());
2404 } else {
2405 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2406 GL_RENDERBUFFER,
2407 samples,
2408 format,
2409 size.width(),
2410 size.height());
2412 bool success = glGetError() == GL_NO_ERROR;
2413 if (success) {
2414 // Mark the previously allocated bytes as free.
2415 memory_tracker_.TrackMemFree(bytes_allocated_);
2416 bytes_allocated_ = estimated_size;
2417 // Track the newly allocated bytes.
2418 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2420 return success;
2423 void BackRenderbuffer::Destroy() {
2424 if (id_ != 0) {
2425 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2426 state_->GetErrorState());
2427 glDeleteRenderbuffersEXT(1, &id_);
2428 id_ = 0;
2430 memory_tracker_.TrackMemFree(bytes_allocated_);
2431 bytes_allocated_ = 0;
2434 void BackRenderbuffer::Invalidate() {
2435 id_ = 0;
2438 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2439 : decoder_(decoder),
2440 id_(0) {
2443 BackFramebuffer::~BackFramebuffer() {
2444 // This does not destroy the frame buffer because that would require that
2445 // the associated GL context was current. Just check that it was explicitly
2446 // destroyed.
2447 DCHECK_EQ(id_, 0u);
2450 void BackFramebuffer::Create() {
2451 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2452 decoder_->GetErrorState());
2453 Destroy();
2454 glGenFramebuffersEXT(1, &id_);
2457 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2458 DCHECK_NE(id_, 0u);
2459 ScopedGLErrorSuppressor suppressor(
2460 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2461 ScopedFrameBufferBinder binder(decoder_, id_);
2462 GLuint attach_id = texture ? texture->id() : 0;
2463 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2464 GL_COLOR_ATTACHMENT0,
2465 GL_TEXTURE_2D,
2466 attach_id,
2470 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2471 BackRenderbuffer* render_buffer) {
2472 DCHECK_NE(id_, 0u);
2473 ScopedGLErrorSuppressor suppressor(
2474 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2475 ScopedFrameBufferBinder binder(decoder_, id_);
2476 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2477 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2478 target,
2479 GL_RENDERBUFFER,
2480 attach_id);
2483 void BackFramebuffer::Destroy() {
2484 if (id_ != 0) {
2485 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2486 decoder_->GetErrorState());
2487 glDeleteFramebuffersEXT(1, &id_);
2488 id_ = 0;
2492 void BackFramebuffer::Invalidate() {
2493 id_ = 0;
2496 GLenum BackFramebuffer::CheckStatus() {
2497 DCHECK_NE(id_, 0u);
2498 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2499 decoder_->GetErrorState());
2500 ScopedFrameBufferBinder binder(decoder_, id_);
2501 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2504 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2505 return new GLES2DecoderImpl(group);
2508 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2509 : GLES2Decoder(),
2510 group_(group),
2511 logger_(&debug_marker_manager_),
2512 state_(group_->feature_info(), this, &logger_),
2513 attrib_0_buffer_id_(0),
2514 attrib_0_buffer_matches_value_(true),
2515 attrib_0_size_(0),
2516 fixed_attrib_buffer_id_(0),
2517 fixed_attrib_buffer_size_(0),
2518 offscreen_target_color_format_(0),
2519 offscreen_target_depth_format_(0),
2520 offscreen_target_stencil_format_(0),
2521 offscreen_target_samples_(0),
2522 offscreen_target_buffer_preserved_(true),
2523 offscreen_saved_color_format_(0),
2524 back_buffer_color_format_(0),
2525 back_buffer_has_depth_(false),
2526 back_buffer_has_stencil_(false),
2527 surfaceless_(false),
2528 backbuffer_needs_clear_bits_(0),
2529 current_decoder_error_(error::kNoError),
2530 use_shader_translator_(true),
2531 validators_(group_->feature_info()->validators()),
2532 feature_info_(group_->feature_info()),
2533 frame_number_(0),
2534 has_robustness_extension_(false),
2535 context_lost_reason_(error::kUnknown),
2536 context_was_lost_(false),
2537 reset_by_robustness_extension_(false),
2538 supports_post_sub_buffer_(false),
2539 webgl_version_(0),
2540 derivatives_explicitly_enabled_(false),
2541 frag_depth_explicitly_enabled_(false),
2542 draw_buffers_explicitly_enabled_(false),
2543 shader_texture_lod_explicitly_enabled_(false),
2544 compile_shader_always_succeeds_(false),
2545 lose_context_when_out_of_memory_(false),
2546 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2547 switches::kEnableGPUServiceLoggingGPU)),
2548 viewport_max_width_(0),
2549 viewport_max_height_(0),
2550 texture_state_(group_->feature_info()
2551 ->workarounds()
2552 .texsubimage_faster_than_teximage),
2553 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2554 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2555 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2556 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2557 gpu_trace_level_(2),
2558 gpu_trace_commands_(false),
2559 gpu_debug_commands_(false),
2560 validation_texture_(0),
2561 validation_fbo_multisample_(0),
2562 validation_fbo_(0) {
2563 DCHECK(group);
2565 // The shader translator is used for WebGL even when running on EGL
2566 // because additional restrictions are needed (like only enabling
2567 // GL_OES_standard_derivatives on demand). It is used for the unit
2568 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2569 // the empty string to CompileShader and this is not a valid shader.
2570 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2571 base::CommandLine::ForCurrentProcess()->HasSwitch(
2572 switches::kDisableGLSLTranslator)) {
2573 use_shader_translator_ = false;
2577 GLES2DecoderImpl::~GLES2DecoderImpl() {
2580 bool GLES2DecoderImpl::Initialize(
2581 const scoped_refptr<gfx::GLSurface>& surface,
2582 const scoped_refptr<gfx::GLContext>& context,
2583 bool offscreen,
2584 const gfx::Size& offscreen_size,
2585 const DisallowedFeatures& disallowed_features,
2586 const std::vector<int32>& attribs) {
2587 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2588 DCHECK(context->IsCurrent(surface.get()));
2589 DCHECK(!context_.get());
2590 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2592 ContextCreationAttribHelper attrib_parser;
2593 if (!attrib_parser.Parse(attribs))
2594 return false;
2595 webgl_version_ = attrib_parser.webgl_version;
2597 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2599 set_initialized();
2600 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2602 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2603 switches::kEnableGPUDebugging)) {
2604 set_debug(true);
2607 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2608 switches::kEnableGPUCommandLogging)) {
2609 set_log_commands(true);
2612 compile_shader_always_succeeds_ =
2613 base::CommandLine::ForCurrentProcess()->HasSwitch(
2614 switches::kCompileShaderAlwaysSucceeds);
2616 // Take ownership of the context and surface. The surface can be replaced with
2617 // SetSurface.
2618 context_ = context;
2619 surface_ = surface;
2621 // Create GPU Tracer for timing values.
2622 gpu_tracer_.reset(new GPUTracer(this));
2624 if (feature_info_->workarounds().disable_timestamp_queries) {
2625 // Forcing time elapsed query for any GPU Timing Client forces it for all
2626 // clients in the context.
2627 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2630 // Save the loseContextWhenOutOfMemory context creation attribute.
2631 lose_context_when_out_of_memory_ =
2632 attrib_parser.lose_context_when_out_of_memory;
2634 // If the failIfMajorPerformanceCaveat context creation attribute was true
2635 // and we are using a software renderer, fail.
2636 if (attrib_parser.fail_if_major_perf_caveat &&
2637 feature_info_->feature_flags().is_swiftshader) {
2638 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2639 Destroy(true);
2640 return false;
2643 disallowed_features_ = disallowed_features;
2644 if (webgl_version_ == 1) {
2645 disallowed_features_.npot_support = true;
2648 if (!group_->Initialize(this,
2649 ContextGroup::GetContextType(webgl_version_),
2650 disallowed_features_)) {
2651 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2652 Destroy(true);
2653 return false;
2655 CHECK_GL_ERROR();
2657 if (webgl_version_ == 2) {
2658 if (!feature_info_->IsES3Capable()) {
2659 LOG(ERROR) << "Underlying driver does not support ES3.";
2660 Destroy(true);
2661 return false;
2663 feature_info_->EnableES3Validators();
2664 set_unsafe_es3_apis_enabled(true);
2667 state_.attrib_values.resize(group_->max_vertex_attribs());
2668 vertex_array_manager_.reset(new VertexArrayManager());
2670 GLuint default_vertex_attrib_service_id = 0;
2671 if (features().native_vertex_array_object) {
2672 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2673 glBindVertexArrayOES(default_vertex_attrib_service_id);
2676 state_.default_vertex_attrib_manager =
2677 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2679 state_.default_vertex_attrib_manager->Initialize(
2680 group_->max_vertex_attribs(),
2681 feature_info_->workarounds().init_vertex_attributes);
2683 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2684 DoBindVertexArrayOES(0);
2686 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2688 image_manager_.reset(new ImageManager);
2690 util_.set_num_compressed_texture_formats(
2691 validators_->compressed_texture_format.GetValues().size());
2693 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2694 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2695 // OpenGL ES 2.0 does not have this issue.
2696 glEnableVertexAttribArray(0);
2698 glGenBuffersARB(1, &attrib_0_buffer_id_);
2699 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2700 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2701 glBindBuffer(GL_ARRAY_BUFFER, 0);
2702 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2704 state_.texture_units.resize(group_->max_texture_units());
2705 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2706 glActiveTexture(GL_TEXTURE0 + tt);
2707 // We want the last bind to be 2D.
2708 TextureRef* ref;
2709 if (features().oes_egl_image_external) {
2710 ref = texture_manager()->GetDefaultTextureInfo(
2711 GL_TEXTURE_EXTERNAL_OES);
2712 state_.texture_units[tt].bound_texture_external_oes = ref;
2713 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2715 if (features().arb_texture_rectangle) {
2716 ref = texture_manager()->GetDefaultTextureInfo(
2717 GL_TEXTURE_RECTANGLE_ARB);
2718 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2719 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2721 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2722 state_.texture_units[tt].bound_texture_cube_map = ref;
2723 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2724 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2725 state_.texture_units[tt].bound_texture_2d = ref;
2726 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2728 glActiveTexture(GL_TEXTURE0);
2729 CHECK_GL_ERROR();
2731 // cache ALPHA_BITS result for re-use with clear behaviour
2732 GLint alpha_bits = 0;
2734 if (offscreen) {
2735 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2736 features().chromium_framebuffer_multisample) {
2737 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2738 // max_sample_count must be initialized to a sane value. If
2739 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2740 GLint max_sample_count = 1;
2741 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2742 offscreen_target_samples_ = std::min(attrib_parser.samples,
2743 max_sample_count);
2744 } else {
2745 offscreen_target_samples_ = 1;
2747 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2749 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2750 const bool rgb8_supported =
2751 context_->HasExtension("GL_OES_rgb8_rgba8");
2752 // The only available default render buffer formats in GLES2 have very
2753 // little precision. Don't enable multisampling unless 8-bit render
2754 // buffer formats are available--instead fall back to 8-bit textures.
2755 if (rgb8_supported && offscreen_target_samples_ > 1) {
2756 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2757 GL_RGBA8 : GL_RGB8;
2758 } else {
2759 offscreen_target_samples_ = 1;
2760 offscreen_target_color_format_ =
2761 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2762 ? GL_RGBA
2763 : GL_RGB;
2766 // ANGLE only supports packed depth/stencil formats, so use it if it is
2767 // available.
2768 const bool depth24_stencil8_supported =
2769 feature_info_->feature_flags().packed_depth24_stencil8;
2770 VLOG(1) << "GL_OES_packed_depth_stencil "
2771 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2772 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2773 depth24_stencil8_supported) {
2774 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2775 offscreen_target_stencil_format_ = 0;
2776 } else {
2777 // It may be the case that this depth/stencil combination is not
2778 // supported, but this will be checked later by CheckFramebufferStatus.
2779 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2780 GL_DEPTH_COMPONENT16 : 0;
2781 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2782 GL_STENCIL_INDEX8 : 0;
2784 } else {
2785 offscreen_target_color_format_ =
2786 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2787 ? GL_RGBA
2788 : GL_RGB;
2790 // If depth is requested at all, use the packed depth stencil format if
2791 // it's available, as some desktop GL drivers don't support any non-packed
2792 // formats for depth attachments.
2793 const bool depth24_stencil8_supported =
2794 feature_info_->feature_flags().packed_depth24_stencil8;
2795 VLOG(1) << "GL_EXT_packed_depth_stencil "
2796 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2798 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2799 depth24_stencil8_supported) {
2800 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2801 offscreen_target_stencil_format_ = 0;
2802 } else {
2803 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2804 GL_DEPTH_COMPONENT : 0;
2805 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2806 GL_STENCIL_INDEX : 0;
2810 offscreen_saved_color_format_ =
2811 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2812 ? GL_RGBA
2813 : GL_RGB;
2815 // Create the target frame buffer. This is the one that the client renders
2816 // directly to.
2817 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2818 offscreen_target_frame_buffer_->Create();
2819 // Due to GLES2 format limitations, either the color texture (for
2820 // non-multisampling) or the color render buffer (for multisampling) will be
2821 // attached to the offscreen frame buffer. The render buffer has more
2822 // limited formats available to it, but the texture can't do multisampling.
2823 if (IsOffscreenBufferMultisampled()) {
2824 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2825 renderbuffer_manager(), memory_tracker(), &state_));
2826 offscreen_target_color_render_buffer_->Create();
2827 } else {
2828 offscreen_target_color_texture_.reset(new BackTexture(
2829 memory_tracker(), &state_));
2830 offscreen_target_color_texture_->Create();
2832 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2833 renderbuffer_manager(), memory_tracker(), &state_));
2834 offscreen_target_depth_render_buffer_->Create();
2835 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2836 renderbuffer_manager(), memory_tracker(), &state_));
2837 offscreen_target_stencil_render_buffer_->Create();
2839 // Create the saved offscreen texture. The target frame buffer is copied
2840 // here when SwapBuffers is called.
2841 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2842 offscreen_saved_frame_buffer_->Create();
2844 offscreen_saved_color_texture_.reset(new BackTexture(
2845 memory_tracker(), &state_));
2846 offscreen_saved_color_texture_->Create();
2848 // Allocate the render buffers at their initial size and check the status
2849 // of the frame buffers is okay.
2850 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2851 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2852 Destroy(true);
2853 return false;
2856 state_.viewport_width = offscreen_size.width();
2857 state_.viewport_height = offscreen_size.height();
2859 // Allocate the offscreen saved color texture.
2860 DCHECK(offscreen_saved_color_format_);
2861 offscreen_saved_color_texture_->AllocateStorage(
2862 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2864 offscreen_saved_frame_buffer_->AttachRenderTexture(
2865 offscreen_saved_color_texture_.get());
2866 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2867 GL_FRAMEBUFFER_COMPLETE) {
2868 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2869 Destroy(true);
2870 return false;
2873 // Bind to the new default frame buffer (the offscreen target frame buffer).
2874 // This should now be associated with ID zero.
2875 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2876 } else {
2877 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2878 // These are NOT if the back buffer has these proprorties. They are
2879 // if we want the command buffer to enforce them regardless of what
2880 // the real backbuffer is assuming the real back buffer gives us more than
2881 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2882 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2883 // can't do anything about that.
2885 if (!surfaceless_) {
2886 GLint depth_bits = 0;
2887 GLint stencil_bits = 0;
2889 bool default_fb = (GetBackbufferServiceId() == 0);
2891 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2892 glGetFramebufferAttachmentParameterivEXT(
2893 GL_FRAMEBUFFER,
2894 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2895 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2896 glGetFramebufferAttachmentParameterivEXT(
2897 GL_FRAMEBUFFER,
2898 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2899 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2900 glGetFramebufferAttachmentParameterivEXT(
2901 GL_FRAMEBUFFER,
2902 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2903 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2904 } else {
2905 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2906 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2907 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2910 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2911 // the user requested RGB then RGB. If the user did not specify a
2912 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2913 back_buffer_color_format_ =
2914 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2915 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2916 back_buffer_has_stencil_ =
2917 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2920 state_.viewport_width = surface->GetSize().width();
2921 state_.viewport_height = surface->GetSize().height();
2924 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2925 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2926 // isn't well documented; it was discovered in the Khronos OpenGL ES
2927 // mailing list archives. It also implicitly enables the desktop GL
2928 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2929 // variable in fragment shaders.
2930 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2931 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2932 glEnable(GL_POINT_SPRITE);
2935 has_robustness_extension_ =
2936 context->HasExtension("GL_ARB_robustness") ||
2937 context->HasExtension("GL_KHR_robustness") ||
2938 context->HasExtension("GL_EXT_robustness");
2940 if (!InitializeShaderTranslator()) {
2941 return false;
2944 GLint viewport_params[4] = { 0 };
2945 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2946 viewport_max_width_ = viewport_params[0];
2947 viewport_max_height_ = viewport_params[1];
2949 state_.scissor_width = state_.viewport_width;
2950 state_.scissor_height = state_.viewport_height;
2952 // Set all the default state because some GL drivers get it wrong.
2953 state_.InitCapabilities(NULL);
2954 state_.InitState(NULL);
2955 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2957 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2958 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2959 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2960 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2961 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2963 bool call_gl_clear = !surfaceless_;
2964 #if defined(OS_ANDROID)
2965 // Temporary workaround for Android WebView because this clear ignores the
2966 // clip and corrupts that external UI of the App. Not calling glClear is ok
2967 // because the system already clears the buffer before each draw. Proper
2968 // fix might be setting the scissor clip properly before initialize. See
2969 // crbug.com/259023 for details.
2970 call_gl_clear = surface_->GetHandle();
2971 #endif
2972 if (call_gl_clear) {
2973 // On configs where we report no alpha, if the underlying surface has
2974 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
2975 bool clear_alpha = back_buffer_color_format_ == GL_RGB && alpha_bits > 0;
2976 if (clear_alpha) {
2977 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
2980 // Clear the backbuffer.
2981 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2983 // Restore alpha clear value if we changed it.
2984 if (clear_alpha) {
2985 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2989 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2990 if (feature_info_->workarounds()
2991 .disable_post_sub_buffers_for_onscreen_surfaces &&
2992 !surface->IsOffscreen())
2993 supports_post_sub_buffer_ = false;
2995 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2996 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2999 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
3000 context_->SetUnbindFboOnMakeCurrent();
3003 // Only compositor contexts are known to use only the subset of GL
3004 // that can be safely migrated between the iGPU and the dGPU. Mark
3005 // those contexts as safe to forcibly transition between the GPUs.
3006 // http://crbug.com/180876, http://crbug.com/227228
3007 if (!offscreen)
3008 context_->SetSafeToForceGpuSwitch();
3010 async_pixel_transfer_manager_.reset(
3011 AsyncPixelTransferManager::Create(context.get()));
3012 async_pixel_transfer_manager_->Initialize(texture_manager());
3014 if (workarounds().gl_clear_broken) {
3015 DCHECK(!clear_framebuffer_blit_.get());
3016 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3017 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
3018 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
3019 return false;
3022 framebuffer_manager()->AddObserver(this);
3024 return true;
3027 Capabilities GLES2DecoderImpl::GetCapabilities() {
3028 DCHECK(initialized());
3029 Capabilities caps;
3030 caps.VisitPrecisions([](GLenum shader, GLenum type,
3031 Capabilities::ShaderPrecision* shader_precision) {
3032 GLint range[2] = {0, 0};
3033 GLint precision = 0;
3034 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
3035 shader_precision->min_range = range[0];
3036 shader_precision->max_range = range[1];
3037 shader_precision->precision = precision;
3039 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
3040 &caps.max_combined_texture_image_units);
3041 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
3042 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
3043 &caps.max_fragment_uniform_vectors);
3044 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
3045 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
3046 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
3047 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
3048 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
3049 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
3050 &caps.max_vertex_texture_image_units);
3051 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
3052 &caps.max_vertex_uniform_vectors);
3053 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
3054 &caps.num_compressed_texture_formats);
3055 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
3056 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
3057 &caps.bind_generates_resource_chromium);
3058 if (unsafe_es3_apis_enabled()) {
3059 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3060 // but for now we clamp them to 32-bit max.
3061 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
3062 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
3063 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
3064 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
3065 &caps.max_combined_fragment_uniform_components);
3066 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
3067 &caps.max_combined_uniform_blocks);
3068 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
3069 &caps.max_combined_vertex_uniform_components);
3070 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
3071 DoGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
3072 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
3073 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
3074 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
3075 &caps.max_fragment_input_components);
3076 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
3077 &caps.max_fragment_uniform_blocks);
3078 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
3079 &caps.max_fragment_uniform_components);
3080 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
3081 &caps.max_program_texel_offset);
3082 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
3083 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3084 // returned.
3085 if (caps.max_server_wait_timeout < 0)
3086 caps.max_server_wait_timeout = 0;
3087 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps.max_texture_lod_bias);
3088 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
3089 &caps.max_transform_feedback_interleaved_components);
3090 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
3091 &caps.max_transform_feedback_separate_attribs);
3092 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
3093 &caps.max_transform_feedback_separate_components);
3094 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
3095 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
3096 &caps.max_uniform_buffer_bindings);
3097 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
3098 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
3099 &caps.max_vertex_output_components);
3100 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
3101 &caps.max_vertex_uniform_blocks);
3102 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
3103 &caps.max_vertex_uniform_components);
3104 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
3105 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
3106 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
3107 &caps.num_program_binary_formats);
3108 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
3109 &caps.uniform_buffer_offset_alignment);
3110 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3111 caps.major_version = 3;
3112 caps.minor_version = 0;
3114 if (feature_info_->feature_flags().multisampled_render_to_texture ||
3115 feature_info_->feature_flags().chromium_framebuffer_multisample ||
3116 unsafe_es3_apis_enabled()) {
3117 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
3120 caps.egl_image_external =
3121 feature_info_->feature_flags().oes_egl_image_external;
3122 caps.texture_format_atc =
3123 feature_info_->feature_flags().ext_texture_format_atc;
3124 caps.texture_format_bgra8888 =
3125 feature_info_->feature_flags().ext_texture_format_bgra8888;
3126 caps.texture_format_dxt1 =
3127 feature_info_->feature_flags().ext_texture_format_dxt1;
3128 caps.texture_format_dxt5 =
3129 feature_info_->feature_flags().ext_texture_format_dxt5;
3130 caps.texture_format_etc1 =
3131 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
3132 caps.texture_format_etc1_npot =
3133 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
3134 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
3135 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
3136 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
3137 caps.discard_framebuffer =
3138 feature_info_->feature_flags().ext_discard_framebuffer;
3139 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3141 #if defined(OS_MACOSX)
3142 // This is unconditionally true on mac, no need to test for it at runtime.
3143 caps.iosurface = true;
3144 #endif
3146 caps.post_sub_buffer = supports_post_sub_buffer_;
3147 caps.image = true;
3148 caps.surfaceless = surfaceless_;
3150 caps.blend_equation_advanced =
3151 feature_info_->feature_flags().blend_equation_advanced;
3152 caps.blend_equation_advanced_coherent =
3153 feature_info_->feature_flags().blend_equation_advanced_coherent;
3154 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3155 caps.max_copy_texture_chromium_size =
3156 feature_info_->workarounds().max_copy_texture_chromium_size;
3157 caps.render_buffer_format_bgra8888 =
3158 feature_info_->feature_flags().ext_render_buffer_format_bgra8888;
3159 caps.occlusion_query_boolean =
3160 feature_info_->feature_flags().occlusion_query_boolean;
3161 caps.timer_queries =
3162 query_manager_->GPUTimingAvailable();
3163 return caps;
3166 void GLES2DecoderImpl::UpdateCapabilities() {
3167 util_.set_num_compressed_texture_formats(
3168 validators_->compressed_texture_format.GetValues().size());
3169 util_.set_num_shader_binary_formats(
3170 validators_->shader_binary_format.GetValues().size());
3173 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3174 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3176 if (!use_shader_translator_) {
3177 return true;
3179 ShBuiltInResources resources;
3180 ShInitBuiltInResources(&resources);
3181 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3182 resources.MaxVertexUniformVectors =
3183 group_->max_vertex_uniform_vectors();
3184 resources.MaxVaryingVectors = group_->max_varying_vectors();
3185 resources.MaxVertexTextureImageUnits =
3186 group_->max_vertex_texture_image_units();
3187 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3188 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3189 resources.MaxFragmentUniformVectors =
3190 group_->max_fragment_uniform_vectors();
3191 resources.MaxDrawBuffers = group_->max_draw_buffers();
3192 resources.MaxExpressionComplexity = 256;
3193 resources.MaxCallStackDepth = 256;
3195 GLint range[2] = { 0, 0 };
3196 GLint precision = 0;
3197 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3198 range, &precision);
3199 resources.FragmentPrecisionHigh =
3200 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3202 if (IsWebGLContext()) {
3203 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3204 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3205 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3206 if (!draw_buffers_explicitly_enabled_)
3207 resources.MaxDrawBuffers = 1;
3208 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3209 resources.NV_draw_buffers =
3210 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3211 } else {
3212 resources.OES_standard_derivatives =
3213 features().oes_standard_derivatives ? 1 : 0;
3214 resources.ARB_texture_rectangle =
3215 features().arb_texture_rectangle ? 1 : 0;
3216 resources.OES_EGL_image_external =
3217 features().oes_egl_image_external ? 1 : 0;
3218 resources.EXT_draw_buffers =
3219 features().ext_draw_buffers ? 1 : 0;
3220 resources.EXT_frag_depth =
3221 features().ext_frag_depth ? 1 : 0;
3222 resources.EXT_shader_texture_lod =
3223 features().ext_shader_texture_lod ? 1 : 0;
3224 resources.NV_draw_buffers =
3225 features().nv_draw_buffers ? 1 : 0;
3228 ShShaderSpec shader_spec;
3229 if (IsWebGLContext()) {
3230 shader_spec = webgl_version_ == 2 ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3231 } else {
3232 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3235 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3236 features().enable_shader_name_hashing)
3237 resources.HashFunction = &CityHash64;
3238 else
3239 resources.HashFunction = NULL;
3240 ShaderTranslatorInterface::GlslImplementationType implementation_type =
3241 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
3242 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
3243 int driver_bug_workarounds = 0;
3244 if (workarounds().needs_glsl_built_in_function_emulation)
3245 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3246 if (workarounds().init_gl_position_in_vertex_shader)
3247 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3248 if (workarounds().unfold_short_circuit_as_ternary_operation)
3249 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3250 if (workarounds().init_varyings_without_static_use)
3251 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3252 if (workarounds().unroll_for_loop_with_sampler_array_index)
3253 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3254 if (workarounds().scalarize_vec_and_mat_constructor_args)
3255 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3256 if (workarounds().regenerate_struct_names)
3257 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3258 if (workarounds().remove_pow_with_constant_exponent)
3259 driver_bug_workarounds |= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT;
3261 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3262 switches::kEmulateShaderPrecision))
3263 resources.WEBGL_debug_shader_precision = true;
3265 vertex_translator_ = shader_translator_cache()->GetTranslator(
3266 GL_VERTEX_SHADER,
3267 shader_spec,
3268 &resources,
3269 implementation_type,
3270 static_cast<ShCompileOptions>(driver_bug_workarounds));
3271 if (!vertex_translator_.get()) {
3272 LOG(ERROR) << "Could not initialize vertex shader translator.";
3273 Destroy(true);
3274 return false;
3277 fragment_translator_ = shader_translator_cache()->GetTranslator(
3278 GL_FRAGMENT_SHADER,
3279 shader_spec,
3280 &resources,
3281 implementation_type,
3282 static_cast<ShCompileOptions>(driver_bug_workarounds));
3283 if (!fragment_translator_.get()) {
3284 LOG(ERROR) << "Could not initialize fragment shader translator.";
3285 Destroy(true);
3286 return false;
3288 return true;
3291 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3292 for (GLsizei ii = 0; ii < n; ++ii) {
3293 if (GetBuffer(client_ids[ii])) {
3294 return false;
3297 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3298 glGenBuffersARB(n, service_ids.get());
3299 for (GLsizei ii = 0; ii < n; ++ii) {
3300 CreateBuffer(client_ids[ii], service_ids[ii]);
3302 return true;
3305 bool GLES2DecoderImpl::GenFramebuffersHelper(
3306 GLsizei n, const GLuint* client_ids) {
3307 for (GLsizei ii = 0; ii < n; ++ii) {
3308 if (GetFramebuffer(client_ids[ii])) {
3309 return false;
3312 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3313 glGenFramebuffersEXT(n, service_ids.get());
3314 for (GLsizei ii = 0; ii < n; ++ii) {
3315 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3317 return true;
3320 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3321 GLsizei n, const GLuint* client_ids) {
3322 for (GLsizei ii = 0; ii < n; ++ii) {
3323 if (GetRenderbuffer(client_ids[ii])) {
3324 return false;
3327 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3328 glGenRenderbuffersEXT(n, service_ids.get());
3329 for (GLsizei ii = 0; ii < n; ++ii) {
3330 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3332 return true;
3335 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3336 const GLuint* client_ids) {
3337 for (GLsizei ii = 0; ii < n; ++ii) {
3338 if (GetValuebuffer(client_ids[ii])) {
3339 return false;
3342 for (GLsizei ii = 0; ii < n; ++ii) {
3343 CreateValuebuffer(client_ids[ii]);
3345 return true;
3348 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3349 for (GLsizei ii = 0; ii < n; ++ii) {
3350 if (GetTexture(client_ids[ii])) {
3351 return false;
3354 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3355 glGenTextures(n, service_ids.get());
3356 for (GLsizei ii = 0; ii < n; ++ii) {
3357 CreateTexture(client_ids[ii], service_ids[ii]);
3359 return true;
3362 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id,
3363 GLsizei range) {
3364 GLuint last_client_id;
3365 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3366 return false;
3368 if (path_manager()->HasPathsInRange(first_client_id, last_client_id))
3369 return false;
3371 GLuint first_service_id = glGenPathsNV(range);
3372 if (first_service_id == 0) {
3373 // We have to fail the connection here, because client has already
3374 // succeeded in allocating the ids. This happens if we allocate
3375 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3376 // example).
3377 return false;
3379 // GenPathsNV does not wrap.
3380 DCHECK(first_service_id + range - 1 >= first_service_id);
3382 path_manager()->CreatePathRange(first_client_id, last_client_id,
3383 first_service_id);
3385 return true;
3388 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id,
3389 GLsizei range) {
3390 GLuint last_client_id;
3391 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3392 return false;
3394 path_manager()->RemovePaths(first_client_id, last_client_id);
3395 return true;
3398 void GLES2DecoderImpl::DeleteBuffersHelper(
3399 GLsizei n, const GLuint* client_ids) {
3400 for (GLsizei ii = 0; ii < n; ++ii) {
3401 Buffer* buffer = GetBuffer(client_ids[ii]);
3402 if (buffer && !buffer->IsDeleted()) {
3403 buffer->RemoveMappedRange();
3404 state_.RemoveBoundBuffer(buffer);
3405 RemoveBuffer(client_ids[ii]);
3410 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3411 GLsizei n, const GLuint* client_ids) {
3412 bool supports_separate_framebuffer_binds =
3413 features().chromium_framebuffer_multisample;
3415 for (GLsizei ii = 0; ii < n; ++ii) {
3416 Framebuffer* framebuffer =
3417 GetFramebuffer(client_ids[ii]);
3418 if (framebuffer && !framebuffer->IsDeleted()) {
3419 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3420 GLenum target = supports_separate_framebuffer_binds ?
3421 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3423 // Unbind attachments on FBO before deletion.
3424 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3425 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3427 glBindFramebufferEXT(target, GetBackbufferServiceId());
3428 framebuffer_state_.bound_draw_framebuffer = NULL;
3429 framebuffer_state_.clear_state_dirty = true;
3431 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3432 framebuffer_state_.bound_read_framebuffer = NULL;
3433 GLenum target = supports_separate_framebuffer_binds ?
3434 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3435 glBindFramebufferEXT(target, GetBackbufferServiceId());
3437 OnFboChanged();
3438 RemoveFramebuffer(client_ids[ii]);
3443 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3444 GLsizei n, const GLuint* client_ids) {
3445 bool supports_separate_framebuffer_binds =
3446 features().chromium_framebuffer_multisample;
3447 for (GLsizei ii = 0; ii < n; ++ii) {
3448 Renderbuffer* renderbuffer =
3449 GetRenderbuffer(client_ids[ii]);
3450 if (renderbuffer && !renderbuffer->IsDeleted()) {
3451 if (state_.bound_renderbuffer.get() == renderbuffer) {
3452 state_.bound_renderbuffer = NULL;
3454 // Unbind from current framebuffers.
3455 if (supports_separate_framebuffer_binds) {
3456 if (framebuffer_state_.bound_read_framebuffer.get()) {
3457 framebuffer_state_.bound_read_framebuffer
3458 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3460 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3461 framebuffer_state_.bound_draw_framebuffer
3462 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3464 } else {
3465 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3466 framebuffer_state_.bound_draw_framebuffer
3467 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3470 framebuffer_state_.clear_state_dirty = true;
3471 RemoveRenderbuffer(client_ids[ii]);
3476 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3477 GLsizei n,
3478 const GLuint* client_ids) {
3479 for (GLsizei ii = 0; ii < n; ++ii) {
3480 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3481 if (valuebuffer) {
3482 if (state_.bound_valuebuffer.get() == valuebuffer) {
3483 state_.bound_valuebuffer = NULL;
3485 RemoveValuebuffer(client_ids[ii]);
3490 void GLES2DecoderImpl::DeleteTexturesHelper(
3491 GLsizei n, const GLuint* client_ids) {
3492 bool supports_separate_framebuffer_binds =
3493 features().chromium_framebuffer_multisample;
3494 for (GLsizei ii = 0; ii < n; ++ii) {
3495 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3496 if (texture_ref) {
3497 Texture* texture = texture_ref->texture();
3498 if (texture->IsAttachedToFramebuffer()) {
3499 framebuffer_state_.clear_state_dirty = true;
3501 // Unbind texture_ref from texture_ref units.
3502 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3503 state_.texture_units[jj].Unbind(texture_ref);
3505 // Unbind from current framebuffers.
3506 if (supports_separate_framebuffer_binds) {
3507 if (framebuffer_state_.bound_read_framebuffer.get()) {
3508 framebuffer_state_.bound_read_framebuffer
3509 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3511 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3512 framebuffer_state_.bound_draw_framebuffer
3513 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3515 } else {
3516 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3517 framebuffer_state_.bound_draw_framebuffer
3518 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3521 #if defined(OS_MACOSX)
3522 GLuint service_id = texture->service_id();
3523 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3524 ReleaseIOSurfaceForTexture(service_id);
3526 #endif
3527 RemoveTexture(client_ids[ii]);
3532 // } // anonymous namespace
3534 bool GLES2DecoderImpl::MakeCurrent() {
3535 if (!context_.get())
3536 return false;
3538 if (WasContextLost()) {
3539 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3540 return false;
3543 if (!context_->MakeCurrent(surface_.get())) {
3544 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3545 MarkContextLost(error::kMakeCurrentFailed);
3546 group_->LoseContexts(error::kUnknown);
3547 return false;
3550 if (CheckResetStatus()) {
3551 LOG(ERROR)
3552 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3553 group_->LoseContexts(error::kUnknown);
3554 return false;
3557 ProcessFinishedAsyncTransfers();
3559 // Rebind the FBO if it was unbound by the context.
3560 if (workarounds().unbind_fbo_on_context_switch)
3561 RestoreFramebufferBindings();
3563 framebuffer_state_.clear_state_dirty = true;
3565 return true;
3568 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3569 ProcessPendingReadPixels(false);
3570 if (engine() && query_manager_.get())
3571 query_manager_->ProcessPendingTransferQueries();
3573 // TODO(epenner): Is there a better place to do this?
3574 // This needs to occur before we execute any batch of commands
3575 // from the client, as the client may have recieved an async
3576 // completion while issuing those commands.
3577 // "DidFlushStart" would be ideal if we had such a callback.
3578 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3581 static void RebindCurrentFramebuffer(
3582 GLenum target,
3583 Framebuffer* framebuffer,
3584 GLuint back_buffer_service_id) {
3585 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3587 if (framebuffer_id == 0) {
3588 framebuffer_id = back_buffer_service_id;
3591 glBindFramebufferEXT(target, framebuffer_id);
3594 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3595 framebuffer_state_.clear_state_dirty = true;
3597 if (!features().chromium_framebuffer_multisample) {
3598 RebindCurrentFramebuffer(
3599 GL_FRAMEBUFFER,
3600 framebuffer_state_.bound_draw_framebuffer.get(),
3601 GetBackbufferServiceId());
3602 } else {
3603 RebindCurrentFramebuffer(
3604 GL_READ_FRAMEBUFFER_EXT,
3605 framebuffer_state_.bound_read_framebuffer.get(),
3606 GetBackbufferServiceId());
3607 RebindCurrentFramebuffer(
3608 GL_DRAW_FRAMEBUFFER_EXT,
3609 framebuffer_state_.bound_draw_framebuffer.get(),
3610 GetBackbufferServiceId());
3612 OnFboChanged();
3615 bool GLES2DecoderImpl::CheckFramebufferValid(
3616 Framebuffer* framebuffer,
3617 GLenum target, const char* func_name) {
3618 if (!framebuffer) {
3619 if (surfaceless_)
3620 return false;
3621 if (backbuffer_needs_clear_bits_) {
3622 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3623 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3624 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3625 glClearStencil(0);
3626 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3627 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3628 glClearDepth(1.0f);
3629 state_.SetDeviceDepthMask(GL_TRUE);
3630 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3631 bool reset_draw_buffer = false;
3632 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3633 group_->draw_buffer() == GL_NONE) {
3634 reset_draw_buffer = true;
3635 GLenum buf = GL_BACK;
3636 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3637 buf = GL_COLOR_ATTACHMENT0;
3638 glDrawBuffersARB(1, &buf);
3640 glClear(backbuffer_needs_clear_bits_);
3641 if (reset_draw_buffer) {
3642 GLenum buf = GL_NONE;
3643 glDrawBuffersARB(1, &buf);
3645 backbuffer_needs_clear_bits_ = 0;
3646 RestoreClearState();
3648 return true;
3651 if (framebuffer_manager()->IsComplete(framebuffer)) {
3652 return true;
3655 GLenum completeness = framebuffer->IsPossiblyComplete();
3656 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3657 LOCAL_SET_GL_ERROR(
3658 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3659 return false;
3662 // Are all the attachments cleared?
3663 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3664 texture_manager()->HaveUnclearedMips()) {
3665 if (!framebuffer->IsCleared()) {
3666 // Can we clear them?
3667 if (framebuffer->GetStatus(texture_manager(), target) !=
3668 GL_FRAMEBUFFER_COMPLETE) {
3669 LOCAL_SET_GL_ERROR(
3670 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3671 "framebuffer incomplete (clear)");
3672 return false;
3674 ClearUnclearedAttachments(target, framebuffer);
3678 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3679 if (framebuffer->GetStatus(texture_manager(), target) !=
3680 GL_FRAMEBUFFER_COMPLETE) {
3681 LOCAL_SET_GL_ERROR(
3682 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3683 "framebuffer incomplete (check)");
3684 return false;
3686 framebuffer_manager()->MarkAsComplete(framebuffer);
3689 // NOTE: At this point we don't know if the framebuffer is complete but
3690 // we DO know that everything that needs to be cleared has been cleared.
3691 return true;
3694 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3695 if (!features().chromium_framebuffer_multisample) {
3696 bool valid = CheckFramebufferValid(
3697 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3698 func_name);
3700 if (valid)
3701 OnUseFramebuffer();
3703 return valid;
3705 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3706 GL_DRAW_FRAMEBUFFER_EXT,
3707 func_name) &&
3708 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3709 GL_READ_FRAMEBUFFER_EXT,
3710 func_name);
3713 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3714 const char* func_name) {
3715 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3716 framebuffer_state_.bound_read_framebuffer.get() :
3717 framebuffer_state_.bound_draw_framebuffer.get();
3718 if (!framebuffer)
3719 return true;
3720 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3721 LOCAL_SET_GL_ERROR(
3722 GL_INVALID_OPERATION, func_name, "no color image attached");
3723 return false;
3725 return true;
3728 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3729 TextureRef* texture, GLint level) {
3730 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3731 framebuffer_state_.bound_read_framebuffer.get() :
3732 framebuffer_state_.bound_draw_framebuffer.get();
3733 if (!framebuffer)
3734 return false;
3735 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3736 GL_COLOR_ATTACHMENT0);
3737 if (!attachment)
3738 return false;
3739 return attachment->FormsFeedbackLoop(texture, level);
3742 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3743 Framebuffer* framebuffer =
3744 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3745 if (framebuffer != NULL) {
3746 const Framebuffer::Attachment* attachment =
3747 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3748 if (attachment) {
3749 return gfx::Size(attachment->width(), attachment->height());
3751 return gfx::Size(0, 0);
3752 } else if (offscreen_target_frame_buffer_.get()) {
3753 return offscreen_size_;
3754 } else {
3755 return surface_->GetSize();
3759 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3760 Framebuffer* framebuffer =
3761 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3762 if (framebuffer != NULL) {
3763 return framebuffer->GetColorAttachmentTextureType();
3764 } else {
3765 return GL_UNSIGNED_BYTE;
3769 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3770 Framebuffer* framebuffer =
3771 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3772 if (framebuffer != NULL) {
3773 return framebuffer->GetColorAttachmentFormat();
3774 } else if (offscreen_target_frame_buffer_.get()) {
3775 return offscreen_target_color_format_;
3776 } else {
3777 return back_buffer_color_format_;
3781 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3782 Framebuffer* framebuffer =
3783 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3784 if (framebuffer != NULL) {
3785 return framebuffer->GetColorAttachmentFormat();
3786 } else if (offscreen_target_frame_buffer_.get()) {
3787 return offscreen_target_color_format_;
3788 } else {
3789 return back_buffer_color_format_;
3793 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3794 if (!offscreen_saved_color_texture_info_.get())
3795 return;
3796 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3797 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3798 texture_manager()->SetLevelInfo(
3799 offscreen_saved_color_texture_info_.get(), GL_TEXTURE_2D,
3800 0, // level
3801 GL_RGBA, offscreen_size_.width(), offscreen_size_.height(),
3802 1, // depth
3803 0, // border
3804 GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(offscreen_size_));
3805 texture_manager()->SetParameteri(
3806 "UpdateParentTextureInfo",
3807 GetErrorState(),
3808 offscreen_saved_color_texture_info_.get(),
3809 GL_TEXTURE_MAG_FILTER,
3810 GL_LINEAR);
3811 texture_manager()->SetParameteri(
3812 "UpdateParentTextureInfo",
3813 GetErrorState(),
3814 offscreen_saved_color_texture_info_.get(),
3815 GL_TEXTURE_MIN_FILTER,
3816 GL_LINEAR);
3817 texture_manager()->SetParameteri(
3818 "UpdateParentTextureInfo",
3819 GetErrorState(),
3820 offscreen_saved_color_texture_info_.get(),
3821 GL_TEXTURE_WRAP_S,
3822 GL_CLAMP_TO_EDGE);
3823 texture_manager()->SetParameteri(
3824 "UpdateParentTextureInfo",
3825 GetErrorState(),
3826 offscreen_saved_color_texture_info_.get(),
3827 GL_TEXTURE_WRAP_T,
3828 GL_CLAMP_TO_EDGE);
3829 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3830 &state_, target);
3831 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3834 void GLES2DecoderImpl::SetResizeCallback(
3835 const base::Callback<void(gfx::Size, float)>& callback) {
3836 resize_callback_ = callback;
3839 Logger* GLES2DecoderImpl::GetLogger() {
3840 return &logger_;
3843 void GLES2DecoderImpl::BeginDecoding() {
3844 gpu_tracer_->BeginDecoding();
3845 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3846 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3847 (*cb_command_trace_category_ != 0);
3850 void GLES2DecoderImpl::EndDecoding() {
3851 gpu_tracer_->EndDecoding();
3854 ErrorState* GLES2DecoderImpl::GetErrorState() {
3855 return state_.GetErrorState();
3858 void GLES2DecoderImpl::SetShaderCacheCallback(
3859 const ShaderCacheCallback& callback) {
3860 shader_cache_callback_ = callback;
3863 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3864 const WaitSyncPointCallback& callback) {
3865 wait_sync_point_callback_ = callback;
3868 AsyncPixelTransferManager*
3869 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3870 return async_pixel_transfer_manager_.get();
3873 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3874 async_pixel_transfer_manager_.reset();
3877 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3878 AsyncPixelTransferManager* manager) {
3879 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3882 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3883 uint32* service_texture_id) {
3884 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3885 if (texture_ref) {
3886 *service_texture_id = texture_ref->service_id();
3887 return true;
3889 return false;
3892 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3893 return texture_state_.texture_upload_count +
3894 async_pixel_transfer_manager_->GetTextureUploadCount();
3897 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3898 return texture_state_.total_texture_upload_time +
3899 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3902 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3903 return total_processing_commands_time_;
3906 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3907 total_processing_commands_time_ += time;
3910 void GLES2DecoderImpl::Destroy(bool have_context) {
3911 if (!initialized())
3912 return;
3914 DCHECK(!have_context || context_->IsCurrent(NULL));
3916 // Unbind everything.
3917 state_.vertex_attrib_manager = NULL;
3918 state_.default_vertex_attrib_manager = NULL;
3919 state_.texture_units.clear();
3920 state_.bound_array_buffer = NULL;
3921 state_.bound_copy_read_buffer = NULL;
3922 state_.bound_copy_write_buffer = NULL;
3923 state_.bound_pixel_pack_buffer = NULL;
3924 state_.bound_pixel_unpack_buffer = NULL;
3925 state_.bound_transform_feedback_buffer = NULL;
3926 state_.bound_uniform_buffer = NULL;
3927 framebuffer_state_.bound_read_framebuffer = NULL;
3928 framebuffer_state_.bound_draw_framebuffer = NULL;
3929 state_.bound_renderbuffer = NULL;
3930 state_.bound_valuebuffer = NULL;
3932 if (offscreen_saved_color_texture_info_.get()) {
3933 DCHECK(offscreen_target_color_texture_);
3934 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3935 offscreen_saved_color_texture_->id());
3936 offscreen_saved_color_texture_->Invalidate();
3937 offscreen_saved_color_texture_info_ = NULL;
3939 if (have_context) {
3940 if (copy_texture_CHROMIUM_.get()) {
3941 copy_texture_CHROMIUM_->Destroy();
3942 copy_texture_CHROMIUM_.reset();
3945 clear_framebuffer_blit_.reset();
3947 if (state_.current_program.get()) {
3948 program_manager()->UnuseProgram(shader_manager(),
3949 state_.current_program.get());
3952 if (attrib_0_buffer_id_) {
3953 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3955 if (fixed_attrib_buffer_id_) {
3956 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3959 if (validation_texture_) {
3960 glDeleteTextures(1, &validation_texture_);
3961 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3962 glDeleteFramebuffersEXT(1, &validation_fbo_);
3965 if (offscreen_target_frame_buffer_.get())
3966 offscreen_target_frame_buffer_->Destroy();
3967 if (offscreen_target_color_texture_.get())
3968 offscreen_target_color_texture_->Destroy();
3969 if (offscreen_target_color_render_buffer_.get())
3970 offscreen_target_color_render_buffer_->Destroy();
3971 if (offscreen_target_depth_render_buffer_.get())
3972 offscreen_target_depth_render_buffer_->Destroy();
3973 if (offscreen_target_stencil_render_buffer_.get())
3974 offscreen_target_stencil_render_buffer_->Destroy();
3975 if (offscreen_saved_frame_buffer_.get())
3976 offscreen_saved_frame_buffer_->Destroy();
3977 if (offscreen_saved_color_texture_.get())
3978 offscreen_saved_color_texture_->Destroy();
3979 if (offscreen_resolved_frame_buffer_.get())
3980 offscreen_resolved_frame_buffer_->Destroy();
3981 if (offscreen_resolved_color_texture_.get())
3982 offscreen_resolved_color_texture_->Destroy();
3983 } else {
3984 if (offscreen_target_frame_buffer_.get())
3985 offscreen_target_frame_buffer_->Invalidate();
3986 if (offscreen_target_color_texture_.get())
3987 offscreen_target_color_texture_->Invalidate();
3988 if (offscreen_target_color_render_buffer_.get())
3989 offscreen_target_color_render_buffer_->Invalidate();
3990 if (offscreen_target_depth_render_buffer_.get())
3991 offscreen_target_depth_render_buffer_->Invalidate();
3992 if (offscreen_target_stencil_render_buffer_.get())
3993 offscreen_target_stencil_render_buffer_->Invalidate();
3994 if (offscreen_saved_frame_buffer_.get())
3995 offscreen_saved_frame_buffer_->Invalidate();
3996 if (offscreen_saved_color_texture_.get())
3997 offscreen_saved_color_texture_->Invalidate();
3998 if (offscreen_resolved_frame_buffer_.get())
3999 offscreen_resolved_frame_buffer_->Invalidate();
4000 if (offscreen_resolved_color_texture_.get())
4001 offscreen_resolved_color_texture_->Invalidate();
4004 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4005 // Otherwise, we can leak objects. http://crbug.com/258772.
4006 // state_.current_program must be reset before group_ is reset because
4007 // the later deletes the ProgramManager object that referred by
4008 // state_.current_program object.
4009 state_.current_program = NULL;
4011 copy_texture_CHROMIUM_.reset();
4012 clear_framebuffer_blit_.reset();
4014 if (query_manager_.get()) {
4015 query_manager_->Destroy(have_context);
4016 query_manager_.reset();
4019 if (vertex_array_manager_ .get()) {
4020 vertex_array_manager_->Destroy(have_context);
4021 vertex_array_manager_.reset();
4024 if (image_manager_.get()) {
4025 image_manager_->Destroy(have_context);
4026 image_manager_.reset();
4029 offscreen_target_frame_buffer_.reset();
4030 offscreen_target_color_texture_.reset();
4031 offscreen_target_color_render_buffer_.reset();
4032 offscreen_target_depth_render_buffer_.reset();
4033 offscreen_target_stencil_render_buffer_.reset();
4034 offscreen_saved_frame_buffer_.reset();
4035 offscreen_saved_color_texture_.reset();
4036 offscreen_resolved_frame_buffer_.reset();
4037 offscreen_resolved_color_texture_.reset();
4039 // Need to release these before releasing |group_| which may own the
4040 // ShaderTranslatorCache.
4041 fragment_translator_ = NULL;
4042 vertex_translator_ = NULL;
4044 // Should destroy the transfer manager before the texture manager held
4045 // by the context group.
4046 async_pixel_transfer_manager_.reset();
4048 // Destroy the GPU Tracer which may own some in process GPU Timings.
4049 if (gpu_tracer_) {
4050 gpu_tracer_->Destroy(have_context);
4051 gpu_tracer_.reset();
4054 if (group_.get()) {
4055 framebuffer_manager()->RemoveObserver(this);
4056 group_->Destroy(this, have_context);
4057 group_ = NULL;
4060 if (context_.get()) {
4061 context_->ReleaseCurrent(NULL);
4062 context_ = NULL;
4065 #if defined(OS_MACOSX)
4066 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
4067 it != texture_to_io_surface_map_.end(); ++it) {
4068 CFRelease(it->second);
4070 texture_to_io_surface_map_.clear();
4071 #endif
4074 void GLES2DecoderImpl::SetSurface(
4075 const scoped_refptr<gfx::GLSurface>& surface) {
4076 DCHECK(context_->IsCurrent(NULL));
4077 DCHECK(surface_.get());
4078 surface_ = surface;
4079 RestoreCurrentFramebufferBindings();
4082 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
4083 if (!offscreen_saved_color_texture_.get()) {
4084 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
4085 return;
4087 if (!offscreen_saved_color_texture_info_.get()) {
4088 GLuint service_id = offscreen_saved_color_texture_->id();
4089 offscreen_saved_color_texture_info_ = TextureRef::Create(
4090 texture_manager(), 0, service_id);
4091 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
4092 GL_TEXTURE_2D);
4093 UpdateParentTextureInfo();
4095 mailbox_manager()->ProduceTexture(
4096 mailbox, offscreen_saved_color_texture_info_->texture());
4099 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
4100 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4101 if (!is_offscreen) {
4102 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4103 << " with an onscreen framebuffer.";
4104 return false;
4107 if (offscreen_size_ == size)
4108 return true;
4110 offscreen_size_ = size;
4111 int w = offscreen_size_.width();
4112 int h = offscreen_size_.height();
4113 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
4114 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4115 << "to allocate storage due to excessive dimensions.";
4116 return false;
4119 // Reallocate the offscreen target buffers.
4120 DCHECK(offscreen_target_color_format_);
4121 if (IsOffscreenBufferMultisampled()) {
4122 if (!offscreen_target_color_render_buffer_->AllocateStorage(
4123 feature_info_.get(),
4124 offscreen_size_,
4125 offscreen_target_color_format_,
4126 offscreen_target_samples_)) {
4127 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4128 << "to allocate storage for offscreen target color buffer.";
4129 return false;
4131 } else {
4132 if (!offscreen_target_color_texture_->AllocateStorage(
4133 offscreen_size_, offscreen_target_color_format_, false)) {
4134 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4135 << "to allocate storage for offscreen target color texture.";
4136 return false;
4139 if (offscreen_target_depth_format_ &&
4140 !offscreen_target_depth_render_buffer_->AllocateStorage(
4141 feature_info_.get(),
4142 offscreen_size_,
4143 offscreen_target_depth_format_,
4144 offscreen_target_samples_)) {
4145 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4146 << "to allocate storage for offscreen target depth buffer.";
4147 return false;
4149 if (offscreen_target_stencil_format_ &&
4150 !offscreen_target_stencil_render_buffer_->AllocateStorage(
4151 feature_info_.get(),
4152 offscreen_size_,
4153 offscreen_target_stencil_format_,
4154 offscreen_target_samples_)) {
4155 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4156 << "to allocate storage for offscreen target stencil buffer.";
4157 return false;
4160 // Attach the offscreen target buffers to the target frame buffer.
4161 if (IsOffscreenBufferMultisampled()) {
4162 offscreen_target_frame_buffer_->AttachRenderBuffer(
4163 GL_COLOR_ATTACHMENT0,
4164 offscreen_target_color_render_buffer_.get());
4165 } else {
4166 offscreen_target_frame_buffer_->AttachRenderTexture(
4167 offscreen_target_color_texture_.get());
4169 if (offscreen_target_depth_format_) {
4170 offscreen_target_frame_buffer_->AttachRenderBuffer(
4171 GL_DEPTH_ATTACHMENT,
4172 offscreen_target_depth_render_buffer_.get());
4174 const bool packed_depth_stencil =
4175 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4176 if (packed_depth_stencil) {
4177 offscreen_target_frame_buffer_->AttachRenderBuffer(
4178 GL_STENCIL_ATTACHMENT,
4179 offscreen_target_depth_render_buffer_.get());
4180 } else if (offscreen_target_stencil_format_) {
4181 offscreen_target_frame_buffer_->AttachRenderBuffer(
4182 GL_STENCIL_ATTACHMENT,
4183 offscreen_target_stencil_render_buffer_.get());
4186 if (offscreen_target_frame_buffer_->CheckStatus() !=
4187 GL_FRAMEBUFFER_COMPLETE) {
4188 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4189 << "because offscreen FBO was incomplete.";
4190 return false;
4193 // Clear the target frame buffer.
4195 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4196 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4197 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
4198 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4199 glClearStencil(0);
4200 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4201 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4202 glClearDepth(0);
4203 state_.SetDeviceDepthMask(GL_TRUE);
4204 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4205 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4206 RestoreClearState();
4209 // Destroy the offscreen resolved framebuffers.
4210 if (offscreen_resolved_frame_buffer_.get())
4211 offscreen_resolved_frame_buffer_->Destroy();
4212 if (offscreen_resolved_color_texture_.get())
4213 offscreen_resolved_color_texture_->Destroy();
4214 offscreen_resolved_color_texture_.reset();
4215 offscreen_resolved_frame_buffer_.reset();
4217 return true;
4220 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4221 const void* cmd_data) {
4222 const gles2::cmds::ResizeCHROMIUM& c =
4223 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4224 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4225 return error::kDeferCommandUntilLater;
4227 GLuint width = static_cast<GLuint>(c.width);
4228 GLuint height = static_cast<GLuint>(c.height);
4229 GLfloat scale_factor = c.scale_factor;
4230 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4232 width = std::max(1U, width);
4233 height = std::max(1U, height);
4235 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4236 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4237 // Make sure that we are done drawing to the back buffer before resizing.
4238 glFinish();
4239 #endif
4240 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4241 if (is_offscreen) {
4242 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4243 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4244 << "ResizeOffscreenFrameBuffer failed.";
4245 return error::kLostContext;
4249 if (!resize_callback_.is_null()) {
4250 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4251 DCHECK(context_->IsCurrent(surface_.get()));
4252 if (!context_->IsCurrent(surface_.get())) {
4253 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4254 << "current after resize callback.";
4255 return error::kLostContext;
4259 return error::kNoError;
4262 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4263 if (command_id > kStartPoint && command_id < kNumCommands) {
4264 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4266 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4269 // Decode a command, and call the corresponding GL functions.
4270 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4271 // of commands at once, and is now only used for tests that need to track
4272 // individual commands.
4273 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4274 unsigned int arg_count,
4275 const void* cmd_data) {
4276 return DoCommands(1, cmd_data, arg_count + 1, 0);
4279 // Decode multiple commands, and call the corresponding GL functions.
4280 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4281 // changed by a (malicious) client at any time, so if validation has to happen,
4282 // it should operate on a copy of them.
4283 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4284 // interest of performance in this critical execution loop.
4285 template <bool DebugImpl>
4286 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4287 const void* buffer,
4288 int num_entries,
4289 int* entries_processed) {
4290 commands_to_process_ = num_commands;
4291 error::Error result = error::kNoError;
4292 const CommandBufferEntry* cmd_data =
4293 static_cast<const CommandBufferEntry*>(buffer);
4294 int process_pos = 0;
4295 unsigned int command = 0;
4297 while (process_pos < num_entries && result == error::kNoError &&
4298 commands_to_process_--) {
4299 const unsigned int size = cmd_data->value_header.size;
4300 command = cmd_data->value_header.command;
4302 if (size == 0) {
4303 result = error::kInvalidSize;
4304 break;
4307 if (static_cast<int>(size) + process_pos > num_entries) {
4308 result = error::kOutOfBounds;
4309 break;
4312 if (DebugImpl) {
4313 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4314 GetCommandName(command));
4316 if (log_commands()) {
4317 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4318 << "cmd: " << GetCommandName(command);
4322 const unsigned int arg_count = size - 1;
4323 unsigned int command_index = command - kStartPoint - 1;
4324 if (command_index < arraysize(command_info)) {
4325 const CommandInfo& info = command_info[command_index];
4326 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4327 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4328 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4329 bool doing_gpu_trace = false;
4330 if (DebugImpl && gpu_trace_commands_) {
4331 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4332 doing_gpu_trace = true;
4333 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4334 GetCommandName(command),
4335 kTraceDecoder);
4339 uint32 immediate_data_size = (arg_count - info_arg_count) *
4340 sizeof(CommandBufferEntry); // NOLINT
4342 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4344 if (DebugImpl && doing_gpu_trace)
4345 gpu_tracer_->End(kTraceDecoder);
4347 if (DebugImpl && debug()) {
4348 GLenum error;
4349 while ((error = glGetError()) != GL_NO_ERROR) {
4350 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4351 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4352 << " : " << GetCommandName(command);
4353 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4356 } else {
4357 result = error::kInvalidArguments;
4359 } else {
4360 result = DoCommonCommand(command, arg_count, cmd_data);
4363 if (DebugImpl) {
4364 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4365 GetCommandName(command));
4368 if (result == error::kNoError &&
4369 current_decoder_error_ != error::kNoError) {
4370 result = current_decoder_error_;
4371 current_decoder_error_ = error::kNoError;
4374 if (result != error::kDeferCommandUntilLater) {
4375 process_pos += size;
4376 cmd_data += size;
4380 if (entries_processed)
4381 *entries_processed = process_pos;
4383 if (error::IsError(result)) {
4384 LOG(ERROR) << "Error: " << result << " for Command "
4385 << GetCommandName(command);
4388 return result;
4391 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4392 const void* buffer,
4393 int num_entries,
4394 int* entries_processed) {
4395 if (gpu_debug_commands_) {
4396 return DoCommandsImpl<true>(
4397 num_commands, buffer, num_entries, entries_processed);
4398 } else {
4399 return DoCommandsImpl<false>(
4400 num_commands, buffer, num_entries, entries_processed);
4404 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4405 buffer_manager()->RemoveBuffer(client_id);
4408 void GLES2DecoderImpl::DoFinish() {
4409 glFinish();
4410 ProcessPendingReadPixels(true);
4411 ProcessPendingQueries(true);
4414 void GLES2DecoderImpl::DoFlush() {
4415 glFlush();
4416 ProcessPendingQueries(false);
4419 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4420 GLuint texture_index = texture_unit - GL_TEXTURE0;
4421 if (texture_index >= state_.texture_units.size()) {
4422 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4423 "glActiveTexture", texture_unit, "texture_unit");
4424 return;
4426 state_.active_texture_unit = texture_index;
4427 glActiveTexture(texture_unit);
4430 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4431 Buffer* buffer = NULL;
4432 GLuint service_id = 0;
4433 if (client_id != 0) {
4434 buffer = GetBuffer(client_id);
4435 if (!buffer) {
4436 if (!group_->bind_generates_resource()) {
4437 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4438 "glBindBuffer",
4439 "id not generated by glGenBuffers");
4440 return;
4443 // It's a new id so make a buffer buffer for it.
4444 glGenBuffersARB(1, &service_id);
4445 CreateBuffer(client_id, service_id);
4446 buffer = GetBuffer(client_id);
4449 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4450 if (buffer) {
4451 if (!buffer_manager()->SetTarget(buffer, target)) {
4452 LOCAL_SET_GL_ERROR(
4453 GL_INVALID_OPERATION,
4454 "glBindBuffer", "buffer bound to more than 1 target");
4455 return;
4457 service_id = buffer->service_id();
4459 state_.SetBoundBuffer(target, buffer);
4460 glBindBuffer(target, service_id);
4463 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4464 bool all_draw_buffers) {
4465 Framebuffer* framebuffer =
4466 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4467 if (!all_draw_buffers || !framebuffer) {
4468 return (GLES2Util::GetChannelsForFormat(
4469 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4471 return framebuffer->HasAlphaMRT();
4474 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4475 Framebuffer* framebuffer =
4476 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4477 if (framebuffer) {
4478 return framebuffer->HasDepthAttachment();
4480 if (offscreen_target_frame_buffer_.get()) {
4481 return offscreen_target_depth_format_ != 0;
4483 return back_buffer_has_depth_;
4486 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4487 Framebuffer* framebuffer =
4488 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4489 if (framebuffer) {
4490 return framebuffer->HasStencilAttachment();
4492 if (offscreen_target_frame_buffer_.get()) {
4493 return offscreen_target_stencil_format_ != 0 ||
4494 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4496 return back_buffer_has_stencil_;
4499 void GLES2DecoderImpl::ApplyDirtyState() {
4500 if (framebuffer_state_.clear_state_dirty) {
4501 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4502 state_.SetDeviceColorMask(state_.color_mask_red,
4503 state_.color_mask_green,
4504 state_.color_mask_blue,
4505 state_.color_mask_alpha && have_alpha);
4507 bool have_depth = BoundFramebufferHasDepthAttachment();
4508 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4510 bool have_stencil = BoundFramebufferHasStencilAttachment();
4511 state_.SetDeviceStencilMaskSeparate(
4512 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4513 state_.SetDeviceStencilMaskSeparate(
4514 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4516 state_.SetDeviceCapabilityState(
4517 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4518 state_.SetDeviceCapabilityState(
4519 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4520 framebuffer_state_.clear_state_dirty = false;
4524 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4525 return (offscreen_target_frame_buffer_.get())
4526 ? offscreen_target_frame_buffer_->id()
4527 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4530 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4531 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4532 "context", logger_.GetLogPrefix());
4533 // Restore the Framebuffer first because of bugs in Intel drivers.
4534 // Intel drivers incorrectly clip the viewport settings to
4535 // the size of the current framebuffer object.
4536 RestoreFramebufferBindings();
4537 state_.RestoreState(prev_state);
4540 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4541 GLuint service_id =
4542 framebuffer_state_.bound_draw_framebuffer.get()
4543 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4544 : GetBackbufferServiceId();
4545 if (!features().chromium_framebuffer_multisample) {
4546 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4547 } else {
4548 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4549 service_id = framebuffer_state_.bound_read_framebuffer.get()
4550 ? framebuffer_state_.bound_read_framebuffer->service_id()
4551 : GetBackbufferServiceId();
4552 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4554 OnFboChanged();
4557 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4558 state_.RestoreRenderbufferBindings();
4561 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4562 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4563 if (texture) {
4564 GLenum target = texture->target();
4565 glBindTexture(target, service_id);
4566 glTexParameteri(
4567 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4568 glTexParameteri(
4569 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4570 glTexParameteri(
4571 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4572 glTexParameteri(
4573 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4574 RestoreTextureUnitBindings(state_.active_texture_unit);
4578 void GLES2DecoderImpl::ClearAllAttributes() const {
4579 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4580 // other VAOs.
4581 if (feature_info_->feature_flags().native_vertex_array_object)
4582 glBindVertexArrayOES(0);
4584 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4585 if (i != 0) // Never disable attribute 0
4586 glDisableVertexAttribArray(i);
4587 if (features().angle_instanced_arrays)
4588 glVertexAttribDivisorANGLE(i, 0);
4592 void GLES2DecoderImpl::RestoreAllAttributes() const {
4593 state_.RestoreVertexAttribs();
4596 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4597 state_.SetIgnoreCachedStateForTest(ignore);
4600 void GLES2DecoderImpl::OnFboChanged() const {
4601 if (workarounds().restore_scissor_on_fbo_change)
4602 state_.fbo_binding_for_scissor_workaround_dirty = true;
4604 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4605 GLint bound_fbo_unsigned = -1;
4606 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4607 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4608 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4609 surface_->NotifyWasBound();
4613 // Called after the FBO is checked for completeness.
4614 void GLES2DecoderImpl::OnUseFramebuffer() const {
4615 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4616 state_.fbo_binding_for_scissor_workaround_dirty = false;
4617 // The driver forgets the correct scissor when modifying the FBO binding.
4618 glScissor(state_.scissor_x,
4619 state_.scissor_y,
4620 state_.scissor_width,
4621 state_.scissor_height);
4623 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4624 // it's unclear how this bug works.
4625 glFlush();
4629 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4630 Framebuffer* framebuffer = NULL;
4631 GLuint service_id = 0;
4632 if (client_id != 0) {
4633 framebuffer = GetFramebuffer(client_id);
4634 if (!framebuffer) {
4635 if (!group_->bind_generates_resource()) {
4636 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4637 "glBindFramebuffer",
4638 "id not generated by glGenFramebuffers");
4639 return;
4642 // It's a new id so make a framebuffer framebuffer for it.
4643 glGenFramebuffersEXT(1, &service_id);
4644 CreateFramebuffer(client_id, service_id);
4645 framebuffer = GetFramebuffer(client_id);
4646 } else {
4647 service_id = framebuffer->service_id();
4649 framebuffer->MarkAsValid();
4651 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4653 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4654 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4657 // vmiura: This looks like dup code
4658 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4659 framebuffer_state_.bound_read_framebuffer = framebuffer;
4662 framebuffer_state_.clear_state_dirty = true;
4664 // If we are rendering to the backbuffer get the FBO id for any simulated
4665 // backbuffer.
4666 if (framebuffer == NULL) {
4667 service_id = GetBackbufferServiceId();
4670 glBindFramebufferEXT(target, service_id);
4671 OnFboChanged();
4674 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4675 Renderbuffer* renderbuffer = NULL;
4676 GLuint service_id = 0;
4677 if (client_id != 0) {
4678 renderbuffer = GetRenderbuffer(client_id);
4679 if (!renderbuffer) {
4680 if (!group_->bind_generates_resource()) {
4681 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4682 "glBindRenderbuffer",
4683 "id not generated by glGenRenderbuffers");
4684 return;
4687 // It's a new id so make a renderbuffer for it.
4688 glGenRenderbuffersEXT(1, &service_id);
4689 CreateRenderbuffer(client_id, service_id);
4690 renderbuffer = GetRenderbuffer(client_id);
4691 } else {
4692 service_id = renderbuffer->service_id();
4694 renderbuffer->MarkAsValid();
4696 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4697 state_.bound_renderbuffer = renderbuffer;
4698 state_.bound_renderbuffer_valid = true;
4699 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4702 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4703 TextureRef* texture_ref = NULL;
4704 GLuint service_id = 0;
4705 if (client_id != 0) {
4706 texture_ref = GetTexture(client_id);
4707 if (!texture_ref) {
4708 if (!group_->bind_generates_resource()) {
4709 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4710 "glBindTexture",
4711 "id not generated by glGenTextures");
4712 return;
4715 // It's a new id so make a texture texture for it.
4716 glGenTextures(1, &service_id);
4717 DCHECK_NE(0u, service_id);
4718 CreateTexture(client_id, service_id);
4719 texture_ref = GetTexture(client_id);
4721 } else {
4722 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4725 // Check the texture exists
4726 if (texture_ref) {
4727 Texture* texture = texture_ref->texture();
4728 // Check that we are not trying to bind it to a different target.
4729 if (texture->target() != 0 && texture->target() != target) {
4730 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4731 "glBindTexture",
4732 "texture bound to more than 1 target.");
4733 return;
4735 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4736 if (texture->target() == 0) {
4737 texture_manager()->SetTarget(texture_ref, target);
4739 glBindTexture(target, texture->service_id());
4740 } else {
4741 glBindTexture(target, 0);
4744 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4745 unit.bind_target = target;
4746 switch (target) {
4747 case GL_TEXTURE_2D:
4748 unit.bound_texture_2d = texture_ref;
4749 break;
4750 case GL_TEXTURE_CUBE_MAP:
4751 unit.bound_texture_cube_map = texture_ref;
4752 break;
4753 case GL_TEXTURE_EXTERNAL_OES:
4754 unit.bound_texture_external_oes = texture_ref;
4755 break;
4756 case GL_TEXTURE_RECTANGLE_ARB:
4757 unit.bound_texture_rectangle_arb = texture_ref;
4758 break;
4759 case GL_TEXTURE_3D:
4760 unit.bound_texture_3d = texture_ref;
4761 break;
4762 case GL_TEXTURE_2D_ARRAY:
4763 unit.bound_texture_2d_array = texture_ref;
4764 break;
4765 default:
4766 NOTREACHED(); // Validation should prevent us getting here.
4767 break;
4771 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4772 if (state_.vertex_attrib_manager->Enable(index, false)) {
4773 if (index != 0 ||
4774 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4775 glDisableVertexAttribArray(index);
4777 } else {
4778 LOCAL_SET_GL_ERROR(
4779 GL_INVALID_VALUE,
4780 "glDisableVertexAttribArray", "index out of range");
4784 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4785 GLsizei numAttachments,
4786 const GLenum* attachments) {
4787 if (workarounds().disable_discard_framebuffer)
4788 return;
4790 Framebuffer* framebuffer =
4791 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4793 // Validates the attachments. If one of them fails
4794 // the whole command fails.
4795 for (GLsizei i = 0; i < numAttachments; ++i) {
4796 if ((framebuffer &&
4797 !validators_->attachment.IsValid(attachments[i])) ||
4798 (!framebuffer &&
4799 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4800 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4801 "glDiscardFramebufferEXT", attachments[i], "attachments");
4802 return;
4806 // Marks each one of them as not cleared
4807 for (GLsizei i = 0; i < numAttachments; ++i) {
4808 if (framebuffer) {
4809 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4810 texture_manager(),
4811 attachments[i],
4812 false);
4813 } else {
4814 switch (attachments[i]) {
4815 case GL_COLOR_EXT:
4816 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4817 break;
4818 case GL_DEPTH_EXT:
4819 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4820 case GL_STENCIL_EXT:
4821 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4822 break;
4823 default:
4824 NOTREACHED();
4825 break;
4830 // If the default framebuffer is bound but we are still rendering to an
4831 // FBO, translate attachment names that refer to default framebuffer
4832 // channels to corresponding framebuffer attachments.
4833 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4834 for (GLsizei i = 0; i < numAttachments; ++i) {
4835 GLenum attachment = attachments[i];
4836 if (!framebuffer && GetBackbufferServiceId()) {
4837 switch (attachment) {
4838 case GL_COLOR_EXT:
4839 attachment = GL_COLOR_ATTACHMENT0;
4840 break;
4841 case GL_DEPTH_EXT:
4842 attachment = GL_DEPTH_ATTACHMENT;
4843 break;
4844 case GL_STENCIL_EXT:
4845 attachment = GL_STENCIL_ATTACHMENT;
4846 break;
4847 default:
4848 NOTREACHED();
4849 return;
4852 translated_attachments[i] = attachment;
4855 ScopedRenderTo do_render(framebuffer);
4856 if (feature_info_->gl_version_info().is_es3) {
4857 glInvalidateFramebuffer(
4858 target, numAttachments, translated_attachments.get());
4859 } else {
4860 glDiscardFramebufferEXT(
4861 target, numAttachments, translated_attachments.get());
4865 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4866 if (state_.vertex_attrib_manager->Enable(index, true)) {
4867 glEnableVertexAttribArray(index);
4868 } else {
4869 LOCAL_SET_GL_ERROR(
4870 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4874 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4875 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4876 &state_, target);
4877 if (!texture_ref ||
4878 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4879 LOCAL_SET_GL_ERROR(
4880 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4881 return;
4884 if (target == GL_TEXTURE_CUBE_MAP) {
4885 for (int i = 0; i < 6; ++i) {
4886 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4887 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4888 LOCAL_SET_GL_ERROR(
4889 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4890 return;
4893 } else {
4894 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4895 LOCAL_SET_GL_ERROR(
4896 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4897 return;
4901 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4902 // Workaround for Mac driver bug. In the large scheme of things setting
4903 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4904 // hit so there's probably no need to make this conditional. The bug appears
4905 // to be that if the filtering mode is set to something that doesn't require
4906 // mipmaps for rendering, or is never set to something other than the default,
4907 // then glGenerateMipmap misbehaves.
4908 if (workarounds().set_texture_filter_before_generating_mipmap) {
4909 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4911 glGenerateMipmapEXT(target);
4912 if (workarounds().set_texture_filter_before_generating_mipmap) {
4913 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4914 texture_ref->texture()->min_filter());
4916 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4917 if (error == GL_NO_ERROR) {
4918 texture_manager()->MarkMipmapsGenerated(texture_ref);
4922 bool GLES2DecoderImpl::GetHelper(
4923 GLenum pname, GLint* params, GLsizei* num_written) {
4924 DCHECK(num_written);
4925 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4926 switch (pname) {
4927 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4928 *num_written = 1;
4929 // Return the GL implementation's preferred format and (see below type)
4930 // if we have the GL extension that exposes this. This allows the GPU
4931 // client to use the implementation's preferred format for glReadPixels
4932 // for optimisation.
4934 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4935 // case when requested on integer/floating point buffers but which is
4936 // acceptable on GLES2 and with the GL_OES_read_format extension.
4938 // Therefore if an error occurs we swallow the error and use the
4939 // internal implementation.
4940 if (params) {
4941 if (context_->HasExtension("GL_OES_read_format")) {
4942 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4943 GetErrorState());
4944 glGetIntegerv(pname, params);
4945 if (glGetError() == GL_NO_ERROR)
4946 return true;
4948 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4949 GetBoundReadFrameBufferInternalFormat());
4951 return true;
4952 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4953 *num_written = 1;
4954 if (params) {
4955 if (context_->HasExtension("GL_OES_read_format")) {
4956 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4957 GetErrorState());
4958 glGetIntegerv(pname, params);
4959 if (glGetError() == GL_NO_ERROR)
4960 return true;
4962 *params = GLES2Util::GetPreferredGLReadPixelsType(
4963 GetBoundReadFrameBufferInternalFormat(),
4964 GetBoundReadFrameBufferTextureType());
4966 return true;
4967 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4968 *num_written = 1;
4969 if (params) {
4970 *params = group_->max_fragment_uniform_vectors();
4972 return true;
4973 case GL_MAX_VARYING_VECTORS:
4974 *num_written = 1;
4975 if (params) {
4976 *params = group_->max_varying_vectors();
4978 return true;
4979 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4980 *num_written = 1;
4981 if (params) {
4982 *params = group_->max_vertex_uniform_vectors();
4984 return true;
4987 if (unsafe_es3_apis_enabled()) {
4988 switch (pname) {
4989 case GL_MAX_VARYING_COMPONENTS: {
4990 if (feature_info_->gl_version_info().is_es) {
4991 // We can just delegate this query to the driver.
4992 return false;
4995 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
4996 // OpenGL core profile, so for simplicity, just compute it
4997 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
4998 // configurations.
4999 GLint max_varying_vectors = 0;
5000 glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors);
5001 *num_written = 1;
5002 if (params) {
5003 *params = max_varying_vectors * 4;
5005 return true;
5009 switch (pname) {
5010 case GL_MAX_VIEWPORT_DIMS:
5011 if (offscreen_target_frame_buffer_.get()) {
5012 *num_written = 2;
5013 if (params) {
5014 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5015 params[1] = renderbuffer_manager()->max_renderbuffer_size();
5017 return true;
5019 return false;
5020 case GL_MAX_SAMPLES:
5021 *num_written = 1;
5022 if (params) {
5023 params[0] = renderbuffer_manager()->max_samples();
5025 return true;
5026 case GL_MAX_RENDERBUFFER_SIZE:
5027 *num_written = 1;
5028 if (params) {
5029 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5031 return true;
5032 case GL_MAX_TEXTURE_SIZE:
5033 *num_written = 1;
5034 if (params) {
5035 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
5037 return true;
5038 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
5039 *num_written = 1;
5040 if (params) {
5041 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
5043 return true;
5044 case GL_MAX_COLOR_ATTACHMENTS_EXT:
5045 *num_written = 1;
5046 if (params) {
5047 params[0] = group_->max_color_attachments();
5049 return true;
5050 case GL_MAX_DRAW_BUFFERS_ARB:
5051 *num_written = 1;
5052 if (params) {
5053 params[0] = group_->max_draw_buffers();
5055 return true;
5056 case GL_ALPHA_BITS:
5057 *num_written = 1;
5058 if (params) {
5059 GLint v = 0;
5060 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5061 Framebuffer* framebuffer =
5062 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5063 if (framebuffer) {
5064 glGetFramebufferAttachmentParameterivEXT(
5065 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5066 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
5067 } else {
5068 v = (back_buffer_color_format_ == GL_RGBA ? 8 : 0);
5070 } else {
5071 glGetIntegerv(GL_ALPHA_BITS, &v);
5073 params[0] =
5074 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
5076 return true;
5077 case GL_DEPTH_BITS:
5078 *num_written = 1;
5079 if (params) {
5080 GLint v = 0;
5081 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5082 Framebuffer* framebuffer =
5083 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5084 if (framebuffer) {
5085 glGetFramebufferAttachmentParameterivEXT(
5086 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
5087 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
5088 } else {
5089 v = (back_buffer_has_depth_ ? 24 : 0);
5091 } else {
5092 glGetIntegerv(GL_DEPTH_BITS, &v);
5094 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
5096 return true;
5097 case GL_RED_BITS:
5098 case GL_GREEN_BITS:
5099 case GL_BLUE_BITS:
5100 *num_written = 1;
5101 if (params) {
5102 GLint v = 0;
5103 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5104 Framebuffer* framebuffer =
5105 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5106 if (framebuffer) {
5107 GLenum framebuffer_enum = 0;
5108 switch (pname) {
5109 case GL_RED_BITS:
5110 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
5111 break;
5112 case GL_GREEN_BITS:
5113 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
5114 break;
5115 case GL_BLUE_BITS:
5116 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
5117 break;
5119 glGetFramebufferAttachmentParameterivEXT(
5120 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
5121 } else {
5122 v = 8;
5124 } else {
5125 glGetIntegerv(pname, &v);
5127 params[0] = v;
5129 return true;
5130 case GL_STENCIL_BITS:
5131 *num_written = 1;
5132 if (params) {
5133 GLint v = 0;
5134 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5135 Framebuffer* framebuffer =
5136 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5137 if (framebuffer) {
5138 glGetFramebufferAttachmentParameterivEXT(
5139 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
5140 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
5141 } else {
5142 v = (back_buffer_has_stencil_ ? 8 : 0);
5144 } else {
5145 glGetIntegerv(GL_STENCIL_BITS, &v);
5147 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
5149 return true;
5150 case GL_COMPRESSED_TEXTURE_FORMATS:
5151 *num_written = validators_->compressed_texture_format.GetValues().size();
5152 if (params) {
5153 for (GLint ii = 0; ii < *num_written; ++ii) {
5154 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
5157 return true;
5158 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
5159 *num_written = 1;
5160 if (params) {
5161 *params = validators_->compressed_texture_format.GetValues().size();
5163 return true;
5164 case GL_NUM_SHADER_BINARY_FORMATS:
5165 *num_written = 1;
5166 if (params) {
5167 *params = validators_->shader_binary_format.GetValues().size();
5169 return true;
5170 case GL_SHADER_BINARY_FORMATS:
5171 *num_written = validators_->shader_binary_format.GetValues().size();
5172 if (params) {
5173 for (GLint ii = 0; ii < *num_written; ++ii) {
5174 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5177 return true;
5178 case GL_SHADER_COMPILER:
5179 *num_written = 1;
5180 if (params) {
5181 *params = GL_TRUE;
5183 return true;
5184 case GL_ARRAY_BUFFER_BINDING:
5185 *num_written = 1;
5186 if (params) {
5187 *params = GetClientId(
5188 buffer_manager(), state_.bound_array_buffer.get());
5190 return true;
5191 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5192 *num_written = 1;
5193 if (params) {
5194 *params = GetClientId(
5195 buffer_manager(),
5196 state_.vertex_attrib_manager->element_array_buffer());
5198 return true;
5199 case GL_COPY_READ_BUFFER_BINDING:
5200 *num_written = 1;
5201 if (params) {
5202 *params = GetClientId(
5203 buffer_manager(), state_.bound_copy_read_buffer.get());
5205 return true;
5206 case GL_COPY_WRITE_BUFFER_BINDING:
5207 *num_written = 1;
5208 if (params) {
5209 *params = GetClientId(
5210 buffer_manager(), state_.bound_copy_write_buffer.get());
5212 return true;
5213 case GL_PIXEL_PACK_BUFFER_BINDING:
5214 *num_written = 1;
5215 if (params) {
5216 *params = GetClientId(
5217 buffer_manager(), state_.bound_pixel_pack_buffer.get());
5219 return true;
5220 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5221 *num_written = 1;
5222 if (params) {
5223 *params = GetClientId(
5224 buffer_manager(), state_.bound_pixel_unpack_buffer.get());
5226 return true;
5227 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5228 *num_written = 1;
5229 if (params) {
5230 *params = GetClientId(
5231 buffer_manager(), state_.bound_transform_feedback_buffer.get());
5233 return true;
5234 case GL_UNIFORM_BUFFER_BINDING:
5235 *num_written = 1;
5236 if (params) {
5237 *params = GetClientId(
5238 buffer_manager(), state_.bound_uniform_buffer.get());
5240 return true;
5241 case GL_FRAMEBUFFER_BINDING:
5242 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5243 *num_written = 1;
5244 if (params) {
5245 *params = GetClientId(
5246 framebuffer_manager(),
5247 GetFramebufferInfoForTarget(GL_FRAMEBUFFER));
5249 return true;
5250 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5251 *num_written = 1;
5252 if (params) {
5253 *params = GetClientId(
5254 framebuffer_manager(),
5255 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT));
5257 return true;
5258 case GL_RENDERBUFFER_BINDING:
5259 *num_written = 1;
5260 if (params) {
5261 Renderbuffer* renderbuffer =
5262 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5263 if (renderbuffer) {
5264 *params = renderbuffer->client_id();
5265 } else {
5266 *params = 0;
5269 return true;
5270 case GL_CURRENT_PROGRAM:
5271 *num_written = 1;
5272 if (params) {
5273 *params = GetClientId(program_manager(), state_.current_program.get());
5275 return true;
5276 case GL_VERTEX_ARRAY_BINDING_OES:
5277 *num_written = 1;
5278 if (params) {
5279 if (state_.vertex_attrib_manager.get() !=
5280 state_.default_vertex_attrib_manager.get()) {
5281 GLuint client_id = 0;
5282 vertex_array_manager_->GetClientId(
5283 state_.vertex_attrib_manager->service_id(), &client_id);
5284 *params = client_id;
5285 } else {
5286 *params = 0;
5289 return true;
5290 case GL_TEXTURE_BINDING_2D:
5291 *num_written = 1;
5292 if (params) {
5293 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5294 if (unit.bound_texture_2d.get()) {
5295 *params = unit.bound_texture_2d->client_id();
5296 } else {
5297 *params = 0;
5300 return true;
5301 case GL_TEXTURE_BINDING_CUBE_MAP:
5302 *num_written = 1;
5303 if (params) {
5304 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5305 if (unit.bound_texture_cube_map.get()) {
5306 *params = unit.bound_texture_cube_map->client_id();
5307 } else {
5308 *params = 0;
5311 return true;
5312 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5313 *num_written = 1;
5314 if (params) {
5315 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5316 if (unit.bound_texture_external_oes.get()) {
5317 *params = unit.bound_texture_external_oes->client_id();
5318 } else {
5319 *params = 0;
5322 return true;
5323 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5324 *num_written = 1;
5325 if (params) {
5326 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5327 if (unit.bound_texture_rectangle_arb.get()) {
5328 *params = unit.bound_texture_rectangle_arb->client_id();
5329 } else {
5330 *params = 0;
5333 return true;
5334 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5335 *num_written = 1;
5336 if (params) {
5337 params[0] = group_->bind_generates_resource() ? 1 : 0;
5339 return true;
5340 default:
5341 if (pname >= GL_DRAW_BUFFER0_ARB &&
5342 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5343 *num_written = 1;
5344 if (params) {
5345 Framebuffer* framebuffer =
5346 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5347 if (framebuffer) {
5348 params[0] = framebuffer->GetDrawBuffer(pname);
5349 } else { // backbuffer
5350 if (pname == GL_DRAW_BUFFER0_ARB)
5351 params[0] = group_->draw_buffer();
5352 else
5353 params[0] = GL_NONE;
5356 return true;
5358 *num_written = util_.GLGetNumValuesReturned(pname);
5359 return false;
5363 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5364 GLenum pname, GLsizei* num_values) {
5365 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5366 return true;
5368 return GetHelper(pname, NULL, num_values);
5371 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5372 if (GL_MAX_SAMPLES == pname &&
5373 features().use_img_for_multisampled_render_to_texture) {
5374 return GL_MAX_SAMPLES_IMG;
5376 return pname;
5379 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5380 DCHECK(params);
5381 GLsizei num_written = 0;
5382 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5383 scoped_ptr<GLint[]> values(new GLint[num_written]);
5384 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5385 GetHelper(pname, values.get(), &num_written);
5387 for (GLsizei ii = 0; ii < num_written; ++ii) {
5388 params[ii] = static_cast<GLboolean>(values[ii]);
5390 } else {
5391 pname = AdjustGetPname(pname);
5392 glGetBooleanv(pname, params);
5396 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5397 DCHECK(params);
5398 GLsizei num_written = 0;
5399 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5400 if (GetHelper(pname, NULL, &num_written)) {
5401 scoped_ptr<GLint[]> values(new GLint[num_written]);
5402 GetHelper(pname, values.get(), &num_written);
5403 for (GLsizei ii = 0; ii < num_written; ++ii) {
5404 params[ii] = static_cast<GLfloat>(values[ii]);
5406 } else {
5407 pname = AdjustGetPname(pname);
5408 glGetFloatv(pname, params);
5413 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5414 DCHECK(params);
5415 if (unsafe_es3_apis_enabled()) {
5416 switch (pname) {
5417 case GL_MAX_ELEMENT_INDEX: {
5418 if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
5419 feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
5420 glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
5421 } else {
5422 // Assume that desktop GL implementations can generally support
5423 // 32-bit indices.
5424 if (params) {
5425 *params = std::numeric_limits<unsigned int>::max();
5428 return;
5432 pname = AdjustGetPname(pname);
5433 glGetInteger64v(pname, params);
5436 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5437 DCHECK(params);
5438 GLsizei num_written;
5439 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5440 !GetHelper(pname, params, &num_written)) {
5441 pname = AdjustGetPname(pname);
5442 glGetIntegerv(pname, params);
5446 void GLES2DecoderImpl::DoGetProgramiv(
5447 GLuint program_id, GLenum pname, GLint* params) {
5448 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5449 if (!program) {
5450 return;
5452 program->GetProgramiv(pname, params);
5455 void GLES2DecoderImpl::DoGetBufferParameteriv(
5456 GLenum target, GLenum pname, GLint* params) {
5457 // Just delegate it. Some validation is actually done before this.
5458 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5459 &state_, target, pname, params);
5462 void GLES2DecoderImpl::DoBindAttribLocation(
5463 GLuint program_id, GLuint index, const char* name) {
5464 if (!StringIsValidForGLES(name)) {
5465 LOCAL_SET_GL_ERROR(
5466 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5467 return;
5469 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5470 LOCAL_SET_GL_ERROR(
5471 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5472 return;
5474 if (index >= group_->max_vertex_attribs()) {
5475 LOCAL_SET_GL_ERROR(
5476 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5477 return;
5479 Program* program = GetProgramInfoNotShader(
5480 program_id, "glBindAttribLocation");
5481 if (!program) {
5482 return;
5484 // At this point, the program's shaders may not be translated yet,
5485 // therefore, we may not find the hashed attribute name.
5486 // glBindAttribLocation call with original name is useless.
5487 // So instead, we should simply cache the binding, and then call
5488 // Program::ExecuteBindAttribLocationCalls() right before link.
5489 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5490 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5491 glBindAttribLocation(program->service_id(), index, name);
5494 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5495 uint32 immediate_data_size,
5496 const void* cmd_data) {
5497 const gles2::cmds::BindAttribLocationBucket& c =
5498 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5499 GLuint program = static_cast<GLuint>(c.program);
5500 GLuint index = static_cast<GLuint>(c.index);
5501 Bucket* bucket = GetBucket(c.name_bucket_id);
5502 if (!bucket || bucket->size() == 0) {
5503 return error::kInvalidArguments;
5505 std::string name_str;
5506 if (!bucket->GetAsString(&name_str)) {
5507 return error::kInvalidArguments;
5509 DoBindAttribLocation(program, index, name_str.c_str());
5510 return error::kNoError;
5513 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5514 GLuint program_id, GLint location, const char* name) {
5515 if (!StringIsValidForGLES(name)) {
5516 LOCAL_SET_GL_ERROR(
5517 GL_INVALID_VALUE,
5518 "glBindUniformLocationCHROMIUM", "Invalid character");
5519 return;
5521 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5522 LOCAL_SET_GL_ERROR(
5523 GL_INVALID_OPERATION,
5524 "glBindUniformLocationCHROMIUM", "reserved prefix");
5525 return;
5527 if (location < 0 || static_cast<uint32>(location) >=
5528 (group_->max_fragment_uniform_vectors() +
5529 group_->max_vertex_uniform_vectors()) * 4) {
5530 LOCAL_SET_GL_ERROR(
5531 GL_INVALID_VALUE,
5532 "glBindUniformLocationCHROMIUM", "location out of range");
5533 return;
5535 Program* program = GetProgramInfoNotShader(
5536 program_id, "glBindUniformLocationCHROMIUM");
5537 if (!program) {
5538 return;
5540 if (!program->SetUniformLocationBinding(name, location)) {
5541 LOCAL_SET_GL_ERROR(
5542 GL_INVALID_VALUE,
5543 "glBindUniformLocationCHROMIUM", "location out of range");
5547 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5548 uint32 immediate_data_size,
5549 const void* cmd_data) {
5550 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5551 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5552 cmd_data);
5553 GLuint program = static_cast<GLuint>(c.program);
5554 GLint location = static_cast<GLint>(c.location);
5555 Bucket* bucket = GetBucket(c.name_bucket_id);
5556 if (!bucket || bucket->size() == 0) {
5557 return error::kInvalidArguments;
5559 std::string name_str;
5560 if (!bucket->GetAsString(&name_str)) {
5561 return error::kInvalidArguments;
5563 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5564 return error::kNoError;
5567 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5568 const void* cmd_data) {
5569 const gles2::cmds::DeleteShader& c =
5570 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5571 GLuint client_id = c.shader;
5572 if (client_id) {
5573 Shader* shader = GetShader(client_id);
5574 if (shader) {
5575 if (!shader->IsDeleted()) {
5576 shader_manager()->Delete(shader);
5578 } else {
5579 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5582 return error::kNoError;
5585 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5586 const void* cmd_data) {
5587 const gles2::cmds::DeleteProgram& c =
5588 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5589 GLuint client_id = c.program;
5590 if (client_id) {
5591 Program* program = GetProgram(client_id);
5592 if (program) {
5593 if (!program->IsDeleted()) {
5594 program_manager()->MarkAsDeleted(shader_manager(), program);
5596 } else {
5597 LOCAL_SET_GL_ERROR(
5598 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5601 return error::kNoError;
5604 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5605 DCHECK(!ShouldDeferDraws());
5606 if (CheckBoundFramebuffersValid("glClear")) {
5607 ApplyDirtyState();
5608 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5609 if (workarounds().gl_clear_broken) {
5610 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5611 GetErrorState());
5612 if (!BoundFramebufferHasDepthAttachment())
5613 mask &= ~GL_DEPTH_BUFFER_BIT;
5614 if (!BoundFramebufferHasStencilAttachment())
5615 mask &= ~GL_STENCIL_BUFFER_BIT;
5616 clear_framebuffer_blit_->ClearFramebuffer(
5617 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5618 state_.color_clear_green, state_.color_clear_blue,
5619 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5620 return error::kNoError;
5622 glClear(mask);
5624 return error::kNoError;
5627 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5628 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5629 GLuint client_renderbuffer_id) {
5630 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5631 if (!framebuffer) {
5632 LOCAL_SET_GL_ERROR(
5633 GL_INVALID_OPERATION,
5634 "glFramebufferRenderbuffer", "no framebuffer bound");
5635 return;
5637 GLuint service_id = 0;
5638 Renderbuffer* renderbuffer = NULL;
5639 if (client_renderbuffer_id) {
5640 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5641 if (!renderbuffer) {
5642 LOCAL_SET_GL_ERROR(
5643 GL_INVALID_OPERATION,
5644 "glFramebufferRenderbuffer", "unknown renderbuffer");
5645 return;
5647 service_id = renderbuffer->service_id();
5649 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5650 glFramebufferRenderbufferEXT(
5651 target, attachment, renderbuffertarget, service_id);
5652 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5653 if (error == GL_NO_ERROR) {
5654 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5656 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5657 framebuffer_state_.clear_state_dirty = true;
5659 OnFboChanged();
5662 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5663 if (SetCapabilityState(cap, false)) {
5664 glDisable(cap);
5668 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5669 if (SetCapabilityState(cap, true)) {
5670 glEnable(cap);
5674 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5675 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5676 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5677 glDepthRange(znear, zfar);
5680 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5681 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5682 state_.sample_coverage_invert = (invert != 0);
5683 glSampleCoverage(state_.sample_coverage_value, invert);
5686 // Assumes framebuffer is complete.
5687 void GLES2DecoderImpl::ClearUnclearedAttachments(
5688 GLenum target, Framebuffer* framebuffer) {
5689 if (target == GL_READ_FRAMEBUFFER_EXT) {
5690 // bind this to the DRAW point, clear then bind back to READ
5691 // TODO(gman): I don't think there is any guarantee that an FBO that
5692 // is complete on the READ attachment will be complete as a DRAW
5693 // attachment.
5694 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5695 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5697 GLbitfield clear_bits = 0;
5698 if (framebuffer->HasUnclearedColorAttachments()) {
5699 glClearColor(
5700 0.0f, 0.0f, 0.0f,
5701 (GLES2Util::GetChannelsForFormat(
5702 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5703 1.0f);
5704 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5705 clear_bits |= GL_COLOR_BUFFER_BIT;
5706 if (feature_info_->feature_flags().ext_draw_buffers)
5707 framebuffer->PrepareDrawBuffersForClear();
5710 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5711 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5712 glClearStencil(0);
5713 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5714 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5715 clear_bits |= GL_STENCIL_BUFFER_BIT;
5718 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5719 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5720 glClearDepth(1.0f);
5721 state_.SetDeviceDepthMask(GL_TRUE);
5722 clear_bits |= GL_DEPTH_BUFFER_BIT;
5725 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5726 glClear(clear_bits);
5728 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5729 feature_info_->feature_flags().ext_draw_buffers)
5730 framebuffer->RestoreDrawBuffersAfterClear();
5732 framebuffer_manager()->MarkAttachmentsAsCleared(
5733 framebuffer, renderbuffer_manager(), texture_manager());
5735 RestoreClearState();
5737 if (target == GL_READ_FRAMEBUFFER_EXT) {
5738 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5739 Framebuffer* draw_framebuffer =
5740 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5741 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5742 GetBackbufferServiceId();
5743 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5747 void GLES2DecoderImpl::RestoreClearState() {
5748 framebuffer_state_.clear_state_dirty = true;
5749 glClearColor(
5750 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5751 state_.color_clear_alpha);
5752 glClearStencil(state_.stencil_clear);
5753 glClearDepth(state_.depth_clear);
5754 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5755 state_.enable_flags.scissor_test);
5756 glScissor(state_.scissor_x, state_.scissor_y, state_.scissor_width,
5757 state_.scissor_height);
5760 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5761 Framebuffer* framebuffer =
5762 GetFramebufferInfoForTarget(target);
5763 if (!framebuffer) {
5764 return GL_FRAMEBUFFER_COMPLETE;
5766 GLenum completeness = framebuffer->IsPossiblyComplete();
5767 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5768 return completeness;
5770 return framebuffer->GetStatus(texture_manager(), target);
5773 void GLES2DecoderImpl::DoFramebufferTexture2D(
5774 GLenum target, GLenum attachment, GLenum textarget,
5775 GLuint client_texture_id, GLint level) {
5776 DoFramebufferTexture2DCommon(
5777 "glFramebufferTexture2D", target, attachment,
5778 textarget, client_texture_id, level, 0);
5781 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5782 GLenum target, GLenum attachment, GLenum textarget,
5783 GLuint client_texture_id, GLint level, GLsizei samples) {
5784 DoFramebufferTexture2DCommon(
5785 "glFramebufferTexture2DMultisample", target, attachment,
5786 textarget, client_texture_id, level, samples);
5789 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5790 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5791 GLuint client_texture_id, GLint level, GLsizei samples) {
5792 if (samples > renderbuffer_manager()->max_samples()) {
5793 LOCAL_SET_GL_ERROR(
5794 GL_INVALID_VALUE,
5795 "glFramebufferTexture2DMultisample", "samples too large");
5796 return;
5798 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5799 if (!framebuffer) {
5800 LOCAL_SET_GL_ERROR(
5801 GL_INVALID_OPERATION,
5802 name, "no framebuffer bound.");
5803 return;
5805 GLuint service_id = 0;
5806 TextureRef* texture_ref = NULL;
5807 if (client_texture_id) {
5808 texture_ref = GetTexture(client_texture_id);
5809 if (!texture_ref) {
5810 LOCAL_SET_GL_ERROR(
5811 GL_INVALID_OPERATION,
5812 name, "unknown texture_ref");
5813 return;
5815 service_id = texture_ref->service_id();
5818 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5819 LOCAL_SET_GL_ERROR(
5820 GL_INVALID_VALUE,
5821 name, "level out of range");
5822 return;
5825 if (texture_ref)
5826 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5828 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5829 if (0 == samples) {
5830 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5831 } else {
5832 if (features().use_img_for_multisampled_render_to_texture) {
5833 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5834 service_id, level, samples);
5835 } else {
5836 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5837 service_id, level, samples);
5840 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5841 if (error == GL_NO_ERROR) {
5842 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5843 samples);
5845 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5846 framebuffer_state_.clear_state_dirty = true;
5849 if (texture_ref)
5850 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5852 OnFboChanged();
5855 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5856 GLenum target, GLenum attachment, GLuint client_texture_id,
5857 GLint level, GLint layer) {
5858 // TODO(zmo): Unsafe ES3 API, missing states update.
5859 GLuint service_id = 0;
5860 TextureRef* texture_ref = NULL;
5861 if (client_texture_id) {
5862 texture_ref = GetTexture(client_texture_id);
5863 if (!texture_ref) {
5864 LOCAL_SET_GL_ERROR(
5865 GL_INVALID_OPERATION,
5866 "glFramebufferTextureLayer", "unknown texture_ref");
5867 return;
5869 service_id = texture_ref->service_id();
5871 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5874 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5875 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5876 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5877 if (!framebuffer) {
5878 LOCAL_SET_GL_ERROR(
5879 GL_INVALID_OPERATION,
5880 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5881 return;
5883 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5884 const Framebuffer::Attachment* attachment_object =
5885 framebuffer->GetAttachment(attachment);
5886 *params = attachment_object ? attachment_object->object_name() : 0;
5887 } else {
5888 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5889 features().use_img_for_multisampled_render_to_texture) {
5890 pname = GL_TEXTURE_SAMPLES_IMG;
5892 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5896 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5897 GLenum target, GLenum pname, GLint* params) {
5898 Renderbuffer* renderbuffer =
5899 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5900 if (!renderbuffer) {
5901 LOCAL_SET_GL_ERROR(
5902 GL_INVALID_OPERATION,
5903 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5904 return;
5907 EnsureRenderbufferBound();
5908 switch (pname) {
5909 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5910 *params = renderbuffer->internal_format();
5911 break;
5912 case GL_RENDERBUFFER_WIDTH:
5913 *params = renderbuffer->width();
5914 break;
5915 case GL_RENDERBUFFER_HEIGHT:
5916 *params = renderbuffer->height();
5917 break;
5918 case GL_RENDERBUFFER_SAMPLES_EXT:
5919 if (features().use_img_for_multisampled_render_to_texture) {
5920 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5921 params);
5922 } else {
5923 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5924 params);
5926 default:
5927 glGetRenderbufferParameterivEXT(target, pname, params);
5928 break;
5932 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5933 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5934 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5935 GLbitfield mask, GLenum filter) {
5936 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5938 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5939 return;
5942 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5943 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5944 BlitFramebufferHelper(
5945 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5946 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5947 state_.enable_flags.scissor_test);
5950 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5951 if (!state_.bound_renderbuffer_valid) {
5952 state_.bound_renderbuffer_valid = true;
5953 glBindRenderbufferEXT(GL_RENDERBUFFER,
5954 state_.bound_renderbuffer.get()
5955 ? state_.bound_renderbuffer->service_id()
5956 : 0);
5960 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5961 const FeatureInfo* feature_info,
5962 GLenum target,
5963 GLsizei samples,
5964 GLenum internal_format,
5965 GLsizei width,
5966 GLsizei height) {
5967 // TODO(sievers): This could be resolved at the GL binding level, but the
5968 // binding process is currently a bit too 'brute force'.
5969 if (feature_info->gl_version_info().is_angle) {
5970 glRenderbufferStorageMultisampleANGLE(
5971 target, samples, internal_format, width, height);
5972 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5973 glRenderbufferStorageMultisample(
5974 target, samples, internal_format, width, height);
5975 } else {
5976 glRenderbufferStorageMultisampleEXT(
5977 target, samples, internal_format, width, height);
5981 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5982 GLint srcY0,
5983 GLint srcX1,
5984 GLint srcY1,
5985 GLint dstX0,
5986 GLint dstY0,
5987 GLint dstX1,
5988 GLint dstY1,
5989 GLbitfield mask,
5990 GLenum filter) {
5991 // TODO(sievers): This could be resolved at the GL binding level, but the
5992 // binding process is currently a bit too 'brute force'.
5993 if (feature_info_->gl_version_info().is_angle) {
5994 glBlitFramebufferANGLE(
5995 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5996 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5997 glBlitFramebuffer(
5998 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5999 } else {
6000 glBlitFramebufferEXT(
6001 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6005 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6006 GLsizei samples,
6007 GLenum internalformat,
6008 GLsizei width,
6009 GLsizei height) {
6010 if (samples > renderbuffer_manager()->max_samples()) {
6011 LOCAL_SET_GL_ERROR(
6012 GL_INVALID_VALUE,
6013 "glRenderbufferStorageMultisample", "samples too large");
6014 return false;
6017 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6018 height > renderbuffer_manager()->max_renderbuffer_size()) {
6019 LOCAL_SET_GL_ERROR(
6020 GL_INVALID_VALUE,
6021 "glRenderbufferStorageMultisample", "dimensions too large");
6022 return false;
6025 uint32 estimated_size = 0;
6026 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6027 width, height, samples, internalformat, &estimated_size)) {
6028 LOCAL_SET_GL_ERROR(
6029 GL_OUT_OF_MEMORY,
6030 "glRenderbufferStorageMultisample", "dimensions too large");
6031 return false;
6034 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6035 LOCAL_SET_GL_ERROR(
6036 GL_OUT_OF_MEMORY,
6037 "glRenderbufferStorageMultisample", "out of memory");
6038 return false;
6041 return true;
6044 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6045 GLenum target, GLsizei samples, GLenum internalformat,
6046 GLsizei width, GLsizei height) {
6047 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6048 if (!renderbuffer) {
6049 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6050 "glRenderbufferStorageMultisampleCHROMIUM",
6051 "no renderbuffer bound");
6052 return;
6055 if (!ValidateRenderbufferStorageMultisample(
6056 samples, internalformat, width, height)) {
6057 return;
6060 EnsureRenderbufferBound();
6061 GLenum impl_format =
6062 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6063 internalformat);
6064 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6065 "glRenderbufferStorageMultisampleCHROMIUM");
6066 RenderbufferStorageMultisampleHelper(
6067 feature_info_.get(), target, samples, impl_format, width, height);
6068 GLenum error =
6069 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6070 if (error == GL_NO_ERROR) {
6071 if (workarounds().validate_multisample_buffer_allocation) {
6072 if (!VerifyMultisampleRenderbufferIntegrity(
6073 renderbuffer->service_id(), impl_format)) {
6074 LOCAL_SET_GL_ERROR(
6075 GL_OUT_OF_MEMORY,
6076 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6077 return;
6081 // TODO(gman): If renderbuffers tracked which framebuffers they were
6082 // attached to we could just mark those framebuffers as not complete.
6083 framebuffer_manager()->IncFramebufferStateChangeCount();
6084 renderbuffer_manager()->SetInfo(
6085 renderbuffer, samples, internalformat, width, height);
6089 // This is the handler for multisampled_render_to_texture extensions.
6090 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6091 GLenum target, GLsizei samples, GLenum internalformat,
6092 GLsizei width, GLsizei height) {
6093 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6094 if (!renderbuffer) {
6095 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6096 "glRenderbufferStorageMultisampleEXT",
6097 "no renderbuffer bound");
6098 return;
6101 if (!ValidateRenderbufferStorageMultisample(
6102 samples, internalformat, width, height)) {
6103 return;
6106 EnsureRenderbufferBound();
6107 GLenum impl_format =
6108 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6109 internalformat);
6110 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6111 if (features().use_img_for_multisampled_render_to_texture) {
6112 glRenderbufferStorageMultisampleIMG(
6113 target, samples, impl_format, width, height);
6114 } else {
6115 glRenderbufferStorageMultisampleEXT(
6116 target, samples, impl_format, width, height);
6118 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6119 if (error == GL_NO_ERROR) {
6120 // TODO(gman): If renderbuffers tracked which framebuffers they were
6121 // attached to we could just mark those framebuffers as not complete.
6122 framebuffer_manager()->IncFramebufferStateChangeCount();
6123 renderbuffer_manager()->SetInfo(
6124 renderbuffer, samples, internalformat, width, height);
6128 // This function validates the allocation of a multisampled renderbuffer
6129 // by clearing it to a key color, blitting the contents to a texture, and
6130 // reading back the color to ensure it matches the key.
6131 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6132 GLuint renderbuffer, GLenum format) {
6134 // Only validate color buffers.
6135 // These formats have been selected because they are very common or are known
6136 // to be used by the WebGL backbuffer. If problems are observed with other
6137 // color formats they can be added here.
6138 switch (format) {
6139 case GL_RGB:
6140 case GL_RGB8:
6141 case GL_RGBA:
6142 case GL_RGBA8:
6143 break;
6144 default:
6145 return true;
6148 GLint draw_framebuffer, read_framebuffer;
6150 // Cache framebuffer and texture bindings.
6151 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
6152 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
6154 if (!validation_texture_) {
6155 GLint bound_texture;
6156 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
6158 // Create additional resources needed for the verification.
6159 glGenTextures(1, &validation_texture_);
6160 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
6161 glGenFramebuffersEXT(1, &validation_fbo_);
6163 // Texture only needs to be 1x1.
6164 glBindTexture(GL_TEXTURE_2D, validation_texture_);
6165 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6166 // multisample will fail if the color format of the source and destination
6167 // do not match. Here, we assume that the source is GL_RGBA, and make the
6168 // destination GL_RGBA. http://crbug.com/484203
6169 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
6170 GL_UNSIGNED_BYTE, NULL);
6172 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6173 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6174 GL_TEXTURE_2D, validation_texture_, 0);
6176 glBindTexture(GL_TEXTURE_2D, bound_texture);
6179 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6180 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6181 GL_RENDERBUFFER, renderbuffer);
6183 // Cache current state and reset it to the values we require.
6184 GLboolean scissor_enabled = false;
6185 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6186 if (scissor_enabled)
6187 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6189 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6190 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6191 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6193 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6194 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6195 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6197 // Clear the buffer to the desired key color.
6198 glClear(GL_COLOR_BUFFER_BIT);
6200 // Blit from the multisample buffer to a standard texture.
6201 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6202 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6204 BlitFramebufferHelper(
6205 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6207 // Read a pixel from the buffer.
6208 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6210 unsigned char pixel[3] = {0, 0, 0};
6211 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6213 // Detach the renderbuffer.
6214 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6215 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6216 GL_RENDERBUFFER, 0);
6218 // Restore cached state.
6219 if (scissor_enabled)
6220 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6222 state_.SetDeviceColorMask(
6223 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6224 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6225 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6226 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6228 // Return true if the pixel matched the desired key color.
6229 return (pixel[0] == 0xFF &&
6230 pixel[1] == 0x00 &&
6231 pixel[2] == 0xFF);
6234 void GLES2DecoderImpl::DoRenderbufferStorage(
6235 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6236 Renderbuffer* renderbuffer =
6237 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6238 if (!renderbuffer) {
6239 LOCAL_SET_GL_ERROR(
6240 GL_INVALID_OPERATION,
6241 "glRenderbufferStorage", "no renderbuffer bound");
6242 return;
6245 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6246 height > renderbuffer_manager()->max_renderbuffer_size()) {
6247 LOCAL_SET_GL_ERROR(
6248 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6249 return;
6252 uint32 estimated_size = 0;
6253 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6254 width, height, 1, internalformat, &estimated_size)) {
6255 LOCAL_SET_GL_ERROR(
6256 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6257 return;
6260 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6261 LOCAL_SET_GL_ERROR(
6262 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6263 return;
6266 EnsureRenderbufferBound();
6267 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6268 glRenderbufferStorageEXT(
6269 target,
6270 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6271 internalformat),
6272 width,
6273 height);
6274 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6275 if (error == GL_NO_ERROR) {
6276 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6277 // we could just mark those framebuffers as not complete.
6278 framebuffer_manager()->IncFramebufferStateChangeCount();
6279 renderbuffer_manager()->SetInfo(
6280 renderbuffer, 1, internalformat, width, height);
6284 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6285 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6286 Program* program = GetProgramInfoNotShader(
6287 program_id, "glLinkProgram");
6288 if (!program) {
6289 return;
6292 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6293 if (program->Link(shader_manager(),
6294 workarounds().count_all_in_varyings_packing ?
6295 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6296 shader_cache_callback_)) {
6297 if (program == state_.current_program.get()) {
6298 if (workarounds().use_current_program_after_successful_link)
6299 glUseProgram(program->service_id());
6300 if (workarounds().clear_uniforms_before_first_program_use)
6301 program_manager()->ClearUniforms(program);
6305 // LinkProgram can be very slow. Exit command processing to allow for
6306 // context preemption and GPU watchdog checks.
6307 ExitCommandProcessingEarly();
6310 void GLES2DecoderImpl::DoSamplerParameterfv(
6311 GLuint sampler, GLenum pname, const GLfloat* params) {
6312 DCHECK(params);
6313 glSamplerParameterf(sampler, pname, params[0]);
6316 void GLES2DecoderImpl::DoSamplerParameteriv(
6317 GLuint sampler, GLenum pname, const GLint* params) {
6318 DCHECK(params);
6319 glSamplerParameteri(sampler, pname, params[0]);
6322 void GLES2DecoderImpl::DoTexParameterf(
6323 GLenum target, GLenum pname, GLfloat param) {
6324 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6325 &state_, target);
6326 if (!texture) {
6327 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6328 return;
6331 texture_manager()->SetParameterf(
6332 "glTexParameterf", GetErrorState(), texture, pname, param);
6335 void GLES2DecoderImpl::DoTexParameteri(
6336 GLenum target, GLenum pname, GLint param) {
6337 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6338 &state_, target);
6339 if (!texture) {
6340 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6341 return;
6344 texture_manager()->SetParameteri(
6345 "glTexParameteri", GetErrorState(), texture, pname, param);
6348 void GLES2DecoderImpl::DoTexParameterfv(
6349 GLenum target, GLenum pname, const GLfloat* params) {
6350 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6351 &state_, target);
6352 if (!texture) {
6353 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6354 return;
6357 texture_manager()->SetParameterf(
6358 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6361 void GLES2DecoderImpl::DoTexParameteriv(
6362 GLenum target, GLenum pname, const GLint* params) {
6363 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6364 &state_, target);
6365 if (!texture) {
6366 LOCAL_SET_GL_ERROR(
6367 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6368 return;
6371 texture_manager()->SetParameteri(
6372 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6375 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6376 if (!state_.bound_valuebuffer.get()) {
6377 // There is no valuebuffer bound
6378 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6379 "no valuebuffer in use");
6380 return false;
6382 return true;
6385 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6386 GLenum subscription,
6387 const char* function_name) {
6388 if (!CheckCurrentValuebuffer(function_name)) {
6389 return false;
6391 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6392 // The valuebuffer is not subscribed to the target
6393 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6394 "valuebuffer is not subscribed");
6395 return false;
6397 return true;
6400 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6401 GLenum subscription,
6402 const char* function_name) {
6403 if (!CheckCurrentProgramForUniform(location, function_name)) {
6404 return false;
6406 GLint real_location = -1;
6407 GLint array_index = -1;
6408 const Program::UniformInfo* info =
6409 state_.current_program->GetUniformInfoByFakeLocation(
6410 location, &real_location, &array_index);
6411 if (!info) {
6412 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6413 return false;
6415 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6416 info->accepts_api_type) == 0) {
6417 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6418 "wrong type for subscription");
6419 return false;
6421 return true;
6424 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6425 if (!state_.current_program.get()) {
6426 // The program does not exist.
6427 LOCAL_SET_GL_ERROR(
6428 GL_INVALID_OPERATION, function_name, "no program in use");
6429 return false;
6431 if (!state_.current_program->InUse()) {
6432 LOCAL_SET_GL_ERROR(
6433 GL_INVALID_OPERATION, function_name, "program not linked");
6434 return false;
6436 return true;
6439 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6440 GLint location, const char* function_name) {
6441 if (!CheckCurrentProgram(function_name)) {
6442 return false;
6444 return location != -1;
6447 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6448 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6449 if (!framebuffer)
6450 return false;
6451 const Framebuffer::Attachment* attachment =
6452 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6453 if (!attachment)
6454 return false;
6456 DCHECK(state_.current_program.get());
6457 const Program::SamplerIndices& sampler_indices =
6458 state_.current_program->sampler_indices();
6459 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6460 const Program::UniformInfo* uniform_info =
6461 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6462 DCHECK(uniform_info);
6463 if (uniform_info->type != GL_SAMPLER_2D)
6464 continue;
6465 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6466 GLuint texture_unit_index = uniform_info->texture_units[jj];
6467 if (texture_unit_index >= state_.texture_units.size())
6468 continue;
6469 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6470 TextureRef* texture_ref =
6471 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6472 if (attachment->IsTexture(texture_ref))
6473 return true;
6476 return false;
6479 bool GLES2DecoderImpl::CheckUniformForApiType(
6480 const Program::UniformInfo* info,
6481 const char* function_name,
6482 Program::UniformApiType api_type) {
6483 DCHECK(info);
6484 if ((api_type & info->accepts_api_type) == 0) {
6485 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6486 "wrong uniform function for type");
6487 return false;
6489 return true;
6492 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6493 GLint fake_location,
6494 const char* function_name,
6495 Program::UniformApiType api_type,
6496 GLint* real_location,
6497 GLenum* type,
6498 GLsizei* count) {
6499 DCHECK(type);
6500 DCHECK(count);
6501 DCHECK(real_location);
6503 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6504 return false;
6506 GLint array_index = -1;
6507 const Program::UniformInfo* info =
6508 state_.current_program->GetUniformInfoByFakeLocation(
6509 fake_location, real_location, &array_index);
6510 if (!info) {
6511 LOCAL_SET_GL_ERROR(
6512 GL_INVALID_OPERATION, function_name, "unknown location");
6513 return false;
6515 if (!CheckUniformForApiType(info, function_name, api_type)) {
6516 return false;
6518 if (*count > 1 && !info->is_array) {
6519 LOCAL_SET_GL_ERROR(
6520 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6521 return false;
6523 *count = std::min(info->size - array_index, *count);
6524 if (*count <= 0) {
6525 return false;
6527 *type = info->type;
6528 return true;
6531 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6532 GLenum type = 0;
6533 GLsizei count = 1;
6534 GLint real_location = -1;
6535 if (!PrepForSetUniformByLocation(fake_location,
6536 "glUniform1i",
6537 Program::kUniform1i,
6538 &real_location,
6539 &type,
6540 &count)) {
6541 return;
6543 if (!state_.current_program->SetSamplers(
6544 state_.texture_units.size(), fake_location, 1, &v0)) {
6545 LOCAL_SET_GL_ERROR(
6546 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6547 return;
6549 glUniform1i(real_location, v0);
6552 void GLES2DecoderImpl::DoUniform1iv(
6553 GLint fake_location, GLsizei count, const GLint *value) {
6554 GLenum type = 0;
6555 GLint real_location = -1;
6556 if (!PrepForSetUniformByLocation(fake_location,
6557 "glUniform1iv",
6558 Program::kUniform1i,
6559 &real_location,
6560 &type,
6561 &count)) {
6562 return;
6564 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6565 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6566 if (!state_.current_program->SetSamplers(
6567 state_.texture_units.size(), fake_location, count, value)) {
6568 LOCAL_SET_GL_ERROR(
6569 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6570 return;
6573 glUniform1iv(real_location, count, value);
6576 void GLES2DecoderImpl::DoUniform1fv(
6577 GLint fake_location, GLsizei count, const GLfloat* value) {
6578 GLenum type = 0;
6579 GLint real_location = -1;
6580 if (!PrepForSetUniformByLocation(fake_location,
6581 "glUniform1fv",
6582 Program::kUniform1f,
6583 &real_location,
6584 &type,
6585 &count)) {
6586 return;
6588 if (type == GL_BOOL) {
6589 scoped_ptr<GLint[]> temp(new GLint[count]);
6590 for (GLsizei ii = 0; ii < count; ++ii) {
6591 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6593 DoUniform1iv(real_location, count, temp.get());
6594 } else {
6595 glUniform1fv(real_location, count, value);
6599 void GLES2DecoderImpl::DoUniform2fv(
6600 GLint fake_location, GLsizei count, const GLfloat* value) {
6601 GLenum type = 0;
6602 GLint real_location = -1;
6603 if (!PrepForSetUniformByLocation(fake_location,
6604 "glUniform2fv",
6605 Program::kUniform2f,
6606 &real_location,
6607 &type,
6608 &count)) {
6609 return;
6611 if (type == GL_BOOL_VEC2) {
6612 GLsizei num_values = count * 2;
6613 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6614 for (GLsizei ii = 0; ii < num_values; ++ii) {
6615 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6617 glUniform2iv(real_location, count, temp.get());
6618 } else {
6619 glUniform2fv(real_location, count, value);
6623 void GLES2DecoderImpl::DoUniform3fv(
6624 GLint fake_location, GLsizei count, const GLfloat* value) {
6625 GLenum type = 0;
6626 GLint real_location = -1;
6627 if (!PrepForSetUniformByLocation(fake_location,
6628 "glUniform3fv",
6629 Program::kUniform3f,
6630 &real_location,
6631 &type,
6632 &count)) {
6633 return;
6635 if (type == GL_BOOL_VEC3) {
6636 GLsizei num_values = count * 3;
6637 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6638 for (GLsizei ii = 0; ii < num_values; ++ii) {
6639 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6641 glUniform3iv(real_location, count, temp.get());
6642 } else {
6643 glUniform3fv(real_location, count, value);
6647 void GLES2DecoderImpl::DoUniform4fv(
6648 GLint fake_location, GLsizei count, const GLfloat* value) {
6649 GLenum type = 0;
6650 GLint real_location = -1;
6651 if (!PrepForSetUniformByLocation(fake_location,
6652 "glUniform4fv",
6653 Program::kUniform4f,
6654 &real_location,
6655 &type,
6656 &count)) {
6657 return;
6659 if (type == GL_BOOL_VEC4) {
6660 GLsizei num_values = count * 4;
6661 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6662 for (GLsizei ii = 0; ii < num_values; ++ii) {
6663 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6665 glUniform4iv(real_location, count, temp.get());
6666 } else {
6667 glUniform4fv(real_location, count, value);
6671 void GLES2DecoderImpl::DoUniform2iv(
6672 GLint fake_location, GLsizei count, const GLint* value) {
6673 GLenum type = 0;
6674 GLint real_location = -1;
6675 if (!PrepForSetUniformByLocation(fake_location,
6676 "glUniform2iv",
6677 Program::kUniform2i,
6678 &real_location,
6679 &type,
6680 &count)) {
6681 return;
6683 glUniform2iv(real_location, count, value);
6686 void GLES2DecoderImpl::DoUniform3iv(
6687 GLint fake_location, GLsizei count, const GLint* value) {
6688 GLenum type = 0;
6689 GLint real_location = -1;
6690 if (!PrepForSetUniformByLocation(fake_location,
6691 "glUniform3iv",
6692 Program::kUniform3i,
6693 &real_location,
6694 &type,
6695 &count)) {
6696 return;
6698 glUniform3iv(real_location, count, value);
6701 void GLES2DecoderImpl::DoUniform4iv(
6702 GLint fake_location, GLsizei count, const GLint* value) {
6703 GLenum type = 0;
6704 GLint real_location = -1;
6705 if (!PrepForSetUniformByLocation(fake_location,
6706 "glUniform4iv",
6707 Program::kUniform4i,
6708 &real_location,
6709 &type,
6710 &count)) {
6711 return;
6713 glUniform4iv(real_location, count, value);
6716 void GLES2DecoderImpl::DoUniformMatrix2fv(
6717 GLint fake_location, GLsizei count, GLboolean transpose,
6718 const GLfloat* value) {
6719 GLenum type = 0;
6720 GLint real_location = -1;
6721 if (!PrepForSetUniformByLocation(fake_location,
6722 "glUniformMatrix2fv",
6723 Program::kUniformMatrix2f,
6724 &real_location,
6725 &type,
6726 &count)) {
6727 return;
6729 glUniformMatrix2fv(real_location, count, transpose, value);
6732 void GLES2DecoderImpl::DoUniformMatrix3fv(
6733 GLint fake_location, GLsizei count, GLboolean transpose,
6734 const GLfloat* value) {
6735 GLenum type = 0;
6736 GLint real_location = -1;
6737 if (!PrepForSetUniformByLocation(fake_location,
6738 "glUniformMatrix3fv",
6739 Program::kUniformMatrix3f,
6740 &real_location,
6741 &type,
6742 &count)) {
6743 return;
6745 glUniformMatrix3fv(real_location, count, transpose, value);
6748 void GLES2DecoderImpl::DoUniformMatrix4fv(
6749 GLint fake_location, GLsizei count, GLboolean transpose,
6750 const GLfloat* value) {
6751 GLenum type = 0;
6752 GLint real_location = -1;
6753 if (!PrepForSetUniformByLocation(fake_location,
6754 "glUniformMatrix4fv",
6755 Program::kUniformMatrix4f,
6756 &real_location,
6757 &type,
6758 &count)) {
6759 return;
6761 glUniformMatrix4fv(real_location, count, transpose, value);
6764 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6765 GLuint service_id = 0;
6766 Program* program = NULL;
6767 if (program_id) {
6768 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6769 if (!program) {
6770 return;
6772 if (!program->IsValid()) {
6773 // Program was not linked successfully. (ie, glLinkProgram)
6774 LOCAL_SET_GL_ERROR(
6775 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6776 return;
6778 service_id = program->service_id();
6780 if (state_.current_program.get()) {
6781 program_manager()->UnuseProgram(shader_manager(),
6782 state_.current_program.get());
6784 state_.current_program = program;
6785 LogClientServiceMapping("glUseProgram", program_id, service_id);
6786 glUseProgram(service_id);
6787 if (state_.current_program.get()) {
6788 program_manager()->UseProgram(state_.current_program.get());
6789 if (workarounds().clear_uniforms_before_first_program_use)
6790 program_manager()->ClearUniforms(program);
6794 void GLES2DecoderImpl::RenderWarning(
6795 const char* filename, int line, const std::string& msg) {
6796 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6799 void GLES2DecoderImpl::PerformanceWarning(
6800 const char* filename, int line, const std::string& msg) {
6801 logger_.LogMessage(filename, line,
6802 std::string("PERFORMANCE WARNING: ") + msg);
6805 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6806 Texture* texture, GLenum textarget) {
6807 // Image is already in use if texture is attached to a framebuffer.
6808 if (texture && !texture->IsAttachedToFramebuffer()) {
6809 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6810 if (image) {
6811 ScopedGLErrorSuppressor suppressor(
6812 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6813 GetErrorState());
6814 glBindTexture(textarget, texture->service_id());
6815 image->WillUseTexImage();
6816 RestoreCurrentTextureBindings(&state_, textarget);
6821 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6822 Texture* texture, GLenum textarget) {
6823 // Image is still in use if texture is attached to a framebuffer.
6824 if (texture && !texture->IsAttachedToFramebuffer()) {
6825 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6826 if (image) {
6827 ScopedGLErrorSuppressor suppressor(
6828 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6829 GetErrorState());
6830 glBindTexture(textarget, texture->service_id());
6831 image->DidUseTexImage();
6832 RestoreCurrentTextureBindings(&state_, textarget);
6837 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6838 DCHECK(state_.current_program.get());
6839 if (!texture_manager()->HaveUnrenderableTextures() &&
6840 !texture_manager()->HaveImages()) {
6841 return true;
6844 bool textures_set = false;
6845 const Program::SamplerIndices& sampler_indices =
6846 state_.current_program->sampler_indices();
6847 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6848 const Program::UniformInfo* uniform_info =
6849 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6850 DCHECK(uniform_info);
6851 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6852 GLuint texture_unit_index = uniform_info->texture_units[jj];
6853 if (texture_unit_index < state_.texture_units.size()) {
6854 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6855 TextureRef* texture_ref =
6856 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6857 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6858 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6859 textures_set = true;
6860 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6861 glBindTexture(
6862 textarget,
6863 texture_manager()->black_texture_id(uniform_info->type));
6864 if (!texture_ref) {
6865 LOCAL_RENDER_WARNING(
6866 std::string("there is no texture bound to the unit ") +
6867 base::IntToString(texture_unit_index));
6868 } else {
6869 LOCAL_RENDER_WARNING(
6870 std::string("texture bound to texture unit ") +
6871 base::IntToString(texture_unit_index) +
6872 " is not renderable. It maybe non-power-of-2 and have"
6873 " incompatible texture filtering.");
6875 continue;
6878 if (textarget != GL_TEXTURE_CUBE_MAP) {
6879 Texture* texture = texture_ref->texture();
6880 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6881 if (image && !texture->IsAttachedToFramebuffer()) {
6882 ScopedGLErrorSuppressor suppressor(
6883 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6884 textures_set = true;
6885 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6886 image->WillUseTexImage();
6887 continue;
6891 // else: should this be an error?
6894 return !textures_set;
6897 void GLES2DecoderImpl::RestoreStateForTextures() {
6898 DCHECK(state_.current_program.get());
6899 const Program::SamplerIndices& sampler_indices =
6900 state_.current_program->sampler_indices();
6901 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6902 const Program::UniformInfo* uniform_info =
6903 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6904 DCHECK(uniform_info);
6905 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6906 GLuint texture_unit_index = uniform_info->texture_units[jj];
6907 if (texture_unit_index < state_.texture_units.size()) {
6908 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6909 TextureRef* texture_ref =
6910 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6911 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6912 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6913 // Get the texture_ref info that was previously bound here.
6914 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6915 ? texture_unit.bound_texture_2d.get()
6916 : texture_unit.bound_texture_cube_map.get();
6917 glBindTexture(texture_unit.bind_target,
6918 texture_ref ? texture_ref->service_id() : 0);
6919 continue;
6922 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6923 Texture* texture = texture_ref->texture();
6924 gfx::GLImage* image =
6925 texture->GetLevelImage(texture_unit.bind_target, 0);
6926 if (image && !texture->IsAttachedToFramebuffer()) {
6927 ScopedGLErrorSuppressor suppressor(
6928 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6929 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6930 image->DidUseTexImage();
6931 continue;
6937 // Set the active texture back to whatever the user had it as.
6938 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6941 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6942 // Only check if there are some uncleared textures.
6943 if (!texture_manager()->HaveUnsafeTextures()) {
6944 return true;
6947 // 1: Check all textures we are about to render with.
6948 if (state_.current_program.get()) {
6949 const Program::SamplerIndices& sampler_indices =
6950 state_.current_program->sampler_indices();
6951 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6952 const Program::UniformInfo* uniform_info =
6953 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6954 DCHECK(uniform_info);
6955 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6956 GLuint texture_unit_index = uniform_info->texture_units[jj];
6957 if (texture_unit_index < state_.texture_units.size()) {
6958 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6959 TextureRef* texture_ref =
6960 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6961 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6962 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6963 return false;
6970 return true;
6973 bool GLES2DecoderImpl::IsDrawValid(
6974 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6975 GLsizei primcount) {
6976 DCHECK(instanced || primcount == 1);
6978 // NOTE: We specifically do not check current_program->IsValid() because
6979 // it could never be invalid since glUseProgram would have failed. While
6980 // glLinkProgram could later mark the program as invalid the previous
6981 // valid program will still function if it is still the current program.
6982 if (!state_.current_program.get()) {
6983 // The program does not exist.
6984 // But GL says no ERROR.
6985 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6986 return false;
6989 if (CheckDrawingFeedbackLoops()) {
6990 LOCAL_SET_GL_ERROR(
6991 GL_INVALID_OPERATION, function_name,
6992 "Source and destination textures of the draw are the same.");
6993 return false;
6996 return state_.vertex_attrib_manager
6997 ->ValidateBindings(function_name,
6998 this,
6999 feature_info_.get(),
7000 state_.current_program.get(),
7001 max_vertex_accessed,
7002 instanced,
7003 primcount);
7006 bool GLES2DecoderImpl::SimulateAttrib0(
7007 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
7008 DCHECK(simulated);
7009 *simulated = false;
7011 if (feature_info_->gl_version_info().BehavesLikeGLES())
7012 return true;
7014 const VertexAttrib* attrib =
7015 state_.vertex_attrib_manager->GetVertexAttrib(0);
7016 // If it's enabled or it's not used then we don't need to do anything.
7017 bool attrib_0_used =
7018 state_.current_program->GetAttribInfoByLocation(0) != NULL;
7019 if (attrib->enabled() && attrib_0_used) {
7020 return true;
7023 // Make a buffer with a single repeated vec4 value enough to
7024 // simulate the constant value that is supposed to be here.
7025 // This is required to emulate GLES2 on GL.
7026 GLuint num_vertices = max_vertex_accessed + 1;
7027 uint32 size_needed = 0;
7029 if (num_vertices == 0 ||
7030 !SafeMultiplyUint32(num_vertices, sizeof(Vec4f), &size_needed) ||
7031 size_needed > 0x7FFFFFFFU) {
7032 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7033 return false;
7036 LOCAL_PERFORMANCE_WARNING(
7037 "Attribute 0 is disabled. This has signficant performance penalty");
7039 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7040 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
7042 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
7043 if (new_buffer) {
7044 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7045 GLenum error = glGetError();
7046 if (error != GL_NO_ERROR) {
7047 LOCAL_SET_GL_ERROR(
7048 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7049 return false;
7053 const Vec4& value = state_.attrib_values[0];
7054 if (new_buffer ||
7055 (attrib_0_used &&
7056 (!attrib_0_buffer_matches_value_ || !value.Equal(attrib_0_value_)))){
7057 // TODO(zmo): This is not 100% correct because we might lose data when
7058 // casting to float type, but it is a corner case and once we migrate to
7059 // core profiles on desktop GL, it is no longer relevant.
7060 Vec4f fvalue(value);
7061 std::vector<Vec4f> temp(num_vertices, fvalue);
7062 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
7063 attrib_0_buffer_matches_value_ = true;
7064 attrib_0_value_ = value;
7065 attrib_0_size_ = size_needed;
7068 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
7070 if (attrib->divisor())
7071 glVertexAttribDivisorANGLE(0, 0);
7073 *simulated = true;
7074 return true;
7077 void GLES2DecoderImpl::RestoreStateForAttrib(
7078 GLuint attrib_index, bool restore_array_binding) {
7079 const VertexAttrib* attrib =
7080 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
7081 if (restore_array_binding) {
7082 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
7083 Buffer* buffer = attrib->buffer();
7084 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
7085 glVertexAttribPointer(
7086 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
7087 attrib->gl_stride(), ptr);
7089 if (attrib->divisor())
7090 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
7091 glBindBuffer(
7092 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
7093 state_.bound_array_buffer->service_id() : 0);
7095 // Never touch vertex attribute 0's state (in particular, never
7096 // disable it) when running on desktop GL because it will never be
7097 // re-enabled.
7098 if (attrib_index != 0 ||
7099 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
7100 if (attrib->enabled()) {
7101 glEnableVertexAttribArray(attrib_index);
7102 } else {
7103 glDisableVertexAttribArray(attrib_index);
7108 bool GLES2DecoderImpl::SimulateFixedAttribs(
7109 const char* function_name,
7110 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
7111 DCHECK(simulated);
7112 *simulated = false;
7113 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
7114 return true;
7116 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
7117 return true;
7120 LOCAL_PERFORMANCE_WARNING(
7121 "GL_FIXED attributes have a signficant performance penalty");
7123 // NOTE: we could be smart and try to check if a buffer is used
7124 // twice in 2 different attribs, find the overlapping parts and therefore
7125 // duplicate the minimum amount of data but this whole code path is not meant
7126 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7127 // tests so we just add to the buffer attrib used.
7129 GLuint elements_needed = 0;
7130 const VertexAttribManager::VertexAttribList& enabled_attribs =
7131 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
7132 for (VertexAttribManager::VertexAttribList::const_iterator it =
7133 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7134 const VertexAttrib* attrib = *it;
7135 const Program::VertexAttrib* attrib_info =
7136 state_.current_program->GetAttribInfoByLocation(attrib->index());
7137 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7138 max_vertex_accessed);
7139 GLuint num_vertices = max_accessed + 1;
7140 if (num_vertices == 0) {
7141 LOCAL_SET_GL_ERROR(
7142 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7143 return false;
7145 if (attrib_info &&
7146 attrib->CanAccess(max_accessed) &&
7147 attrib->type() == GL_FIXED) {
7148 uint32 elements_used = 0;
7149 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
7150 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
7151 LOCAL_SET_GL_ERROR(
7152 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7153 return false;
7158 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
7159 uint32 size_needed = 0;
7160 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
7161 size_needed > 0x7FFFFFFFU) {
7162 LOCAL_SET_GL_ERROR(
7163 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7164 return false;
7167 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7169 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
7170 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
7171 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7172 GLenum error = glGetError();
7173 if (error != GL_NO_ERROR) {
7174 LOCAL_SET_GL_ERROR(
7175 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7176 return false;
7180 // Copy the elements and convert to float
7181 GLintptr offset = 0;
7182 for (VertexAttribManager::VertexAttribList::const_iterator it =
7183 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7184 const VertexAttrib* attrib = *it;
7185 const Program::VertexAttrib* attrib_info =
7186 state_.current_program->GetAttribInfoByLocation(attrib->index());
7187 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7188 max_vertex_accessed);
7189 GLuint num_vertices = max_accessed + 1;
7190 if (num_vertices == 0) {
7191 LOCAL_SET_GL_ERROR(
7192 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7193 return false;
7195 if (attrib_info &&
7196 attrib->CanAccess(max_accessed) &&
7197 attrib->type() == GL_FIXED) {
7198 int num_elements = attrib->size() * num_vertices;
7199 const int src_size = num_elements * sizeof(int32);
7200 const int dst_size = num_elements * sizeof(float);
7201 scoped_ptr<float[]> data(new float[num_elements]);
7202 const int32* src = reinterpret_cast<const int32 *>(
7203 attrib->buffer()->GetRange(attrib->offset(), src_size));
7204 const int32* end = src + num_elements;
7205 float* dst = data.get();
7206 while (src != end) {
7207 *dst++ = static_cast<float>(*src++) / 65536.0f;
7209 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7210 glVertexAttribPointer(
7211 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7212 reinterpret_cast<GLvoid*>(offset));
7213 offset += dst_size;
7216 *simulated = true;
7217 return true;
7220 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7221 // There's no need to call glVertexAttribPointer because we shadow all the
7222 // settings and passing GL_FIXED to it will not work.
7223 glBindBuffer(
7224 GL_ARRAY_BUFFER,
7225 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7226 : 0);
7229 error::Error GLES2DecoderImpl::DoDrawArrays(
7230 const char* function_name,
7231 bool instanced,
7232 GLenum mode,
7233 GLint first,
7234 GLsizei count,
7235 GLsizei primcount) {
7236 error::Error error = WillAccessBoundFramebufferForDraw();
7237 if (error != error::kNoError)
7238 return error;
7239 if (!validators_->draw_mode.IsValid(mode)) {
7240 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7241 return error::kNoError;
7243 if (count < 0) {
7244 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7245 return error::kNoError;
7247 if (primcount < 0) {
7248 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7249 return error::kNoError;
7251 if (!CheckBoundFramebuffersValid(function_name)) {
7252 return error::kNoError;
7254 // We have to check this here because the prototype for glDrawArrays
7255 // is GLint not GLsizei.
7256 if (first < 0) {
7257 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7258 return error::kNoError;
7261 if (count == 0 || primcount == 0) {
7262 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7263 return error::kNoError;
7266 GLuint max_vertex_accessed = first + count - 1;
7267 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7268 if (!ClearUnclearedTextures()) {
7269 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7270 return error::kNoError;
7272 bool simulated_attrib_0 = false;
7273 if (!SimulateAttrib0(
7274 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7275 return error::kNoError;
7277 bool simulated_fixed_attribs = false;
7278 if (SimulateFixedAttribs(
7279 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7280 primcount)) {
7281 bool textures_set = !PrepareTexturesForRender();
7282 ApplyDirtyState();
7283 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7284 if (!instanced) {
7285 glDrawArrays(mode, first, count);
7286 } else {
7287 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7289 if (textures_set) {
7290 RestoreStateForTextures();
7292 if (simulated_fixed_attribs) {
7293 RestoreStateForSimulatedFixedAttribs();
7296 if (simulated_attrib_0) {
7297 // We don't have to restore attrib 0 generic data at the end of this
7298 // function even if it is simulated. This is because we will simulate
7299 // it in each draw call, and attrib 0 generic data queries use cached
7300 // values instead of passing down to the underlying driver.
7301 RestoreStateForAttrib(0, false);
7304 return error::kNoError;
7307 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7308 const void* cmd_data) {
7309 // TODO(zmo): crbug.com/481184
7310 // On Desktop GL with versions lower than 4.3, we need to emulate
7311 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7312 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7313 return DoDrawArrays("glDrawArrays",
7314 false,
7315 static_cast<GLenum>(c.mode),
7316 static_cast<GLint>(c.first),
7317 static_cast<GLsizei>(c.count),
7321 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7322 uint32 immediate_data_size,
7323 const void* cmd_data) {
7324 const gles2::cmds::DrawArraysInstancedANGLE& c =
7325 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7326 if (!features().angle_instanced_arrays) {
7327 LOCAL_SET_GL_ERROR(
7328 GL_INVALID_OPERATION,
7329 "glDrawArraysInstancedANGLE", "function not available");
7330 return error::kNoError;
7332 return DoDrawArrays("glDrawArraysIntancedANGLE",
7333 true,
7334 static_cast<GLenum>(c.mode),
7335 static_cast<GLint>(c.first),
7336 static_cast<GLsizei>(c.count),
7337 static_cast<GLsizei>(c.primcount));
7340 error::Error GLES2DecoderImpl::DoDrawElements(
7341 const char* function_name,
7342 bool instanced,
7343 GLenum mode,
7344 GLsizei count,
7345 GLenum type,
7346 int32 offset,
7347 GLsizei primcount) {
7348 error::Error error = WillAccessBoundFramebufferForDraw();
7349 if (error != error::kNoError)
7350 return error;
7351 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7352 LOCAL_SET_GL_ERROR(
7353 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7354 return error::kNoError;
7357 if (count < 0) {
7358 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7359 return error::kNoError;
7361 if (offset < 0) {
7362 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7363 return error::kNoError;
7365 if (!validators_->draw_mode.IsValid(mode)) {
7366 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7367 return error::kNoError;
7369 if (!validators_->index_type.IsValid(type)) {
7370 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7371 return error::kNoError;
7373 if (primcount < 0) {
7374 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7375 return error::kNoError;
7378 if (!CheckBoundFramebuffersValid(function_name)) {
7379 return error::kNoError;
7382 if (count == 0 || primcount == 0) {
7383 return error::kNoError;
7386 GLuint max_vertex_accessed;
7387 Buffer* element_array_buffer =
7388 state_.vertex_attrib_manager->element_array_buffer();
7390 if (!element_array_buffer->GetMaxValueForRange(
7391 offset, count, type, &max_vertex_accessed)) {
7392 LOCAL_SET_GL_ERROR(
7393 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7394 return error::kNoError;
7397 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7398 if (!ClearUnclearedTextures()) {
7399 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7400 return error::kNoError;
7402 bool simulated_attrib_0 = false;
7403 if (!SimulateAttrib0(
7404 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7405 return error::kNoError;
7407 bool simulated_fixed_attribs = false;
7408 if (SimulateFixedAttribs(
7409 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7410 primcount)) {
7411 bool textures_set = !PrepareTexturesForRender();
7412 ApplyDirtyState();
7413 // TODO(gman): Refactor to hide these details in BufferManager or
7414 // VertexAttribManager.
7415 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7416 bool used_client_side_array = false;
7417 if (element_array_buffer->IsClientSideArray()) {
7418 used_client_side_array = true;
7419 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7420 indices = element_array_buffer->GetRange(offset, 0);
7423 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7424 if (!instanced) {
7425 glDrawElements(mode, count, type, indices);
7426 } else {
7427 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7430 if (used_client_side_array) {
7431 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7432 element_array_buffer->service_id());
7435 if (textures_set) {
7436 RestoreStateForTextures();
7438 if (simulated_fixed_attribs) {
7439 RestoreStateForSimulatedFixedAttribs();
7442 if (simulated_attrib_0) {
7443 // We don't have to restore attrib 0 generic data at the end of this
7444 // function even if it is simulated. This is because we will simulate
7445 // it in each draw call, and attrib 0 generic data queries use cached
7446 // values instead of passing down to the underlying driver.
7447 RestoreStateForAttrib(0, false);
7450 return error::kNoError;
7453 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7454 const void* cmd_data) {
7455 // TODO(zmo): crbug.com/481184
7456 // On Desktop GL with versions lower than 4.3, we need to emulate
7457 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7458 const gles2::cmds::DrawElements& c =
7459 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7460 return DoDrawElements("glDrawElements",
7461 false,
7462 static_cast<GLenum>(c.mode),
7463 static_cast<GLsizei>(c.count),
7464 static_cast<GLenum>(c.type),
7465 static_cast<int32>(c.index_offset),
7469 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7470 uint32 immediate_data_size,
7471 const void* cmd_data) {
7472 const gles2::cmds::DrawElementsInstancedANGLE& c =
7473 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7474 if (!features().angle_instanced_arrays) {
7475 LOCAL_SET_GL_ERROR(
7476 GL_INVALID_OPERATION,
7477 "glDrawElementsInstancedANGLE", "function not available");
7478 return error::kNoError;
7480 return DoDrawElements("glDrawElementsInstancedANGLE",
7481 true,
7482 static_cast<GLenum>(c.mode),
7483 static_cast<GLsizei>(c.count),
7484 static_cast<GLenum>(c.type),
7485 static_cast<int32>(c.index_offset),
7486 static_cast<GLsizei>(c.primcount));
7489 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7490 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7491 GLuint max_vertex_accessed = 0;
7492 Buffer* buffer = GetBuffer(buffer_id);
7493 if (!buffer) {
7494 // TODO(gman): Should this be a GL error or a command buffer error?
7495 LOCAL_SET_GL_ERROR(
7496 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7497 } else {
7498 if (!buffer->GetMaxValueForRange(
7499 offset, count, type, &max_vertex_accessed)) {
7500 // TODO(gman): Should this be a GL error or a command buffer error?
7501 LOCAL_SET_GL_ERROR(
7502 GL_INVALID_OPERATION,
7503 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7506 return max_vertex_accessed;
7509 void GLES2DecoderImpl::DoShaderSource(
7510 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7511 std::string str;
7512 for (GLsizei ii = 0; ii < count; ++ii) {
7513 if (length && length[ii] > 0)
7514 str.append(data[ii], length[ii]);
7515 else
7516 str.append(data[ii]);
7518 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7519 if (!shader) {
7520 return;
7522 // Note: We don't actually call glShaderSource here. We wait until
7523 // we actually compile the shader.
7524 shader->set_source(str);
7527 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7528 GLuint client_program_id, GLsizei count, const char* const* varyings,
7529 GLenum buffer_mode) {
7530 Program* program = GetProgramInfoNotShader(
7531 client_program_id, "glTransformFeedbackVaryings");
7532 if (!program) {
7533 return;
7535 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7536 glTransformFeedbackVaryings(
7537 program->service_id(), count, varyings, buffer_mode);
7540 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7541 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7542 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7543 if (!shader) {
7544 return;
7547 scoped_refptr<ShaderTranslatorInterface> translator;
7548 if (use_shader_translator_) {
7549 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7550 vertex_translator_ : fragment_translator_;
7553 const Shader::TranslatedShaderSourceType source_type =
7554 feature_info_->feature_flags().angle_translated_shader_source ?
7555 Shader::kANGLE : Shader::kGL;
7556 shader->RequestCompile(translator, source_type);
7559 void GLES2DecoderImpl::DoGetShaderiv(
7560 GLuint shader_id, GLenum pname, GLint* params) {
7561 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7562 if (!shader) {
7563 return;
7566 // Compile now for statuses that require it.
7567 switch (pname) {
7568 case GL_COMPILE_STATUS:
7569 case GL_INFO_LOG_LENGTH:
7570 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7571 shader->DoCompile();
7572 break;
7574 default:
7575 break;
7578 switch (pname) {
7579 case GL_SHADER_SOURCE_LENGTH:
7580 *params = shader->source().size();
7581 if (*params)
7582 ++(*params);
7583 return;
7584 case GL_COMPILE_STATUS:
7585 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7586 return;
7587 case GL_INFO_LOG_LENGTH:
7588 *params = shader->log_info().size();
7589 if (*params)
7590 ++(*params);
7591 return;
7592 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7593 *params = shader->translated_source().size();
7594 if (*params)
7595 ++(*params);
7596 return;
7597 default:
7598 break;
7600 glGetShaderiv(shader->service_id(), pname, params);
7603 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7604 const void* cmd_data) {
7605 const gles2::cmds::GetShaderSource& c =
7606 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7607 GLuint shader_id = c.shader;
7608 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7609 Bucket* bucket = CreateBucket(bucket_id);
7610 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7611 if (!shader || shader->source().empty()) {
7612 bucket->SetSize(0);
7613 return error::kNoError;
7615 bucket->SetFromString(shader->source().c_str());
7616 return error::kNoError;
7619 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7620 uint32 immediate_data_size,
7621 const void* cmd_data) {
7622 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7623 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7624 cmd_data);
7625 GLuint shader_id = c.shader;
7626 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7627 Bucket* bucket = CreateBucket(bucket_id);
7628 Shader* shader = GetShaderInfoNotProgram(
7629 shader_id, "glGetTranslatedShaderSourceANGLE");
7630 if (!shader) {
7631 bucket->SetSize(0);
7632 return error::kNoError;
7635 // Make sure translator has been utilized in compile.
7636 shader->DoCompile();
7638 bucket->SetFromString(shader->translated_source().c_str());
7639 return error::kNoError;
7642 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7643 uint32 immediate_data_size,
7644 const void* cmd_data) {
7645 const gles2::cmds::GetProgramInfoLog& c =
7646 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7647 GLuint program_id = c.program;
7648 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7649 Bucket* bucket = CreateBucket(bucket_id);
7650 Program* program = GetProgramInfoNotShader(
7651 program_id, "glGetProgramInfoLog");
7652 if (!program || !program->log_info()) {
7653 bucket->SetFromString("");
7654 return error::kNoError;
7656 bucket->SetFromString(program->log_info()->c_str());
7657 return error::kNoError;
7660 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7661 uint32 immediate_data_size,
7662 const void* cmd_data) {
7663 const gles2::cmds::GetShaderInfoLog& c =
7664 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7665 GLuint shader_id = c.shader;
7666 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7667 Bucket* bucket = CreateBucket(bucket_id);
7668 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7669 if (!shader) {
7670 bucket->SetFromString("");
7671 return error::kNoError;
7674 // Shader must be compiled in order to get the info log.
7675 shader->DoCompile();
7677 bucket->SetFromString(shader->log_info().c_str());
7678 return error::kNoError;
7681 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7682 return state_.GetEnabled(cap);
7685 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7686 const Buffer* buffer = GetBuffer(client_id);
7687 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7690 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7691 const Framebuffer* framebuffer =
7692 GetFramebuffer(client_id);
7693 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7696 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7697 // IsProgram is true for programs as soon as they are created, until they are
7698 // deleted and no longer in use.
7699 const Program* program = GetProgram(client_id);
7700 return program != NULL && !program->IsDeleted();
7703 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7704 const Renderbuffer* renderbuffer =
7705 GetRenderbuffer(client_id);
7706 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7709 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7710 // IsShader is true for shaders as soon as they are created, until they
7711 // are deleted and not attached to any programs.
7712 const Shader* shader = GetShader(client_id);
7713 return shader != NULL && !shader->IsDeleted();
7716 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7717 const TextureRef* texture_ref = GetTexture(client_id);
7718 return texture_ref && texture_ref->texture()->IsValid();
7721 void GLES2DecoderImpl::DoAttachShader(
7722 GLuint program_client_id, GLint shader_client_id) {
7723 Program* program = GetProgramInfoNotShader(
7724 program_client_id, "glAttachShader");
7725 if (!program) {
7726 return;
7728 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7729 if (!shader) {
7730 return;
7732 if (!program->AttachShader(shader_manager(), shader)) {
7733 LOCAL_SET_GL_ERROR(
7734 GL_INVALID_OPERATION,
7735 "glAttachShader",
7736 "can not attach more than one shader of the same type.");
7737 return;
7739 glAttachShader(program->service_id(), shader->service_id());
7742 void GLES2DecoderImpl::DoDetachShader(
7743 GLuint program_client_id, GLint shader_client_id) {
7744 Program* program = GetProgramInfoNotShader(
7745 program_client_id, "glDetachShader");
7746 if (!program) {
7747 return;
7749 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7750 if (!shader) {
7751 return;
7753 if (!program->DetachShader(shader_manager(), shader)) {
7754 LOCAL_SET_GL_ERROR(
7755 GL_INVALID_OPERATION,
7756 "glDetachShader", "shader not attached to program");
7757 return;
7759 glDetachShader(program->service_id(), shader->service_id());
7762 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7763 Program* program = GetProgramInfoNotShader(
7764 program_client_id, "glValidateProgram");
7765 if (!program) {
7766 return;
7768 program->Validate();
7771 void GLES2DecoderImpl::GetVertexAttribHelper(
7772 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7773 switch (pname) {
7774 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
7776 Buffer* buffer = attrib->buffer();
7777 if (buffer && !buffer->IsDeleted()) {
7778 GLuint client_id;
7779 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7780 *params = client_id;
7782 break;
7784 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7785 *params = attrib->enabled();
7786 break;
7787 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7788 *params = attrib->size();
7789 break;
7790 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7791 *params = attrib->gl_stride();
7792 break;
7793 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7794 *params = attrib->type();
7795 break;
7796 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7797 *params = attrib->normalized();
7798 break;
7799 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
7800 *params = attrib->divisor();
7801 break;
7802 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
7803 *params = attrib->integer();
7804 break;
7805 default:
7806 NOTREACHED();
7807 break;
7811 void GLES2DecoderImpl::DoGetTexParameterfv(
7812 GLenum target, GLenum pname, GLfloat* params) {
7813 InitTextureMaxAnisotropyIfNeeded(target, pname);
7814 glGetTexParameterfv(target, pname, params);
7817 void GLES2DecoderImpl::DoGetTexParameteriv(
7818 GLenum target, GLenum pname, GLint* params) {
7819 InitTextureMaxAnisotropyIfNeeded(target, pname);
7820 glGetTexParameteriv(target, pname, params);
7823 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7824 GLenum target, GLenum pname) {
7825 if (!workarounds().init_texture_max_anisotropy)
7826 return;
7827 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7828 !validators_->texture_parameter.IsValid(pname)) {
7829 return;
7832 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7833 &state_, target);
7834 if (!texture_ref) {
7835 LOCAL_SET_GL_ERROR(
7836 GL_INVALID_OPERATION,
7837 "glGetTexParamter{fi}v", "unknown texture for target");
7838 return;
7840 Texture* texture = texture_ref->texture();
7841 texture->InitTextureMaxAnisotropyIfNeeded(target);
7844 template <typename T>
7845 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7846 GLuint index, GLenum pname, T* params) {
7847 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7848 if (!attrib) {
7849 LOCAL_SET_GL_ERROR(
7850 GL_INVALID_VALUE, "glGetVertexAttrib", "index out of range");
7851 return;
7853 switch (pname) {
7854 case GL_CURRENT_VERTEX_ATTRIB:
7855 state_.attrib_values[index].GetValues(params);
7856 break;
7857 default: {
7858 GLint value = 0;
7859 GetVertexAttribHelper(attrib, pname, &value);
7860 *params = static_cast<T>(value);
7861 break;
7866 void GLES2DecoderImpl::DoGetVertexAttribfv(
7867 GLuint index, GLenum pname, GLfloat* params) {
7868 DoGetVertexAttribImpl<GLfloat>(index, pname, params);
7871 void GLES2DecoderImpl::DoGetVertexAttribiv(
7872 GLuint index, GLenum pname, GLint* params) {
7873 DoGetVertexAttribImpl<GLint>(index, pname, params);
7876 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7877 GLuint index, GLenum pname, GLint* params) {
7878 DoGetVertexAttribImpl<GLint>(index, pname, params);
7881 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7882 GLuint index, GLenum pname, GLuint* params) {
7883 DoGetVertexAttribImpl<GLuint>(index, pname, params);
7886 template <typename T>
7887 bool GLES2DecoderImpl::SetVertexAttribValue(
7888 const char* function_name, GLuint index, const T* value) {
7889 if (index >= state_.attrib_values.size()) {
7890 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7891 return false;
7893 state_.attrib_values[index].SetValues(value);
7894 return true;
7897 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7898 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7899 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7900 glVertexAttrib1f(index, v0);
7904 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7905 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7906 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7907 glVertexAttrib2f(index, v0, v1);
7911 void GLES2DecoderImpl::DoVertexAttrib3f(
7912 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7913 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7914 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7915 glVertexAttrib3f(index, v0, v1, v2);
7919 void GLES2DecoderImpl::DoVertexAttrib4f(
7920 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7921 GLfloat v[4] = { v0, v1, v2, v3, };
7922 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7923 glVertexAttrib4f(index, v0, v1, v2, v3);
7927 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7928 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7929 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7930 glVertexAttrib1fv(index, v);
7934 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7935 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7936 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7937 glVertexAttrib2fv(index, v);
7941 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7942 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7943 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7944 glVertexAttrib3fv(index, v);
7948 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7949 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7950 glVertexAttrib4fv(index, v);
7954 void GLES2DecoderImpl::DoVertexAttribI4i(
7955 GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
7956 GLint v[4] = { v0, v1, v2, v3 };
7957 if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
7958 glVertexAttribI4i(index, v0, v1, v2, v3);
7962 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
7963 if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
7964 glVertexAttribI4iv(index, v);
7968 void GLES2DecoderImpl::DoVertexAttribI4ui(
7969 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
7970 GLuint v[4] = { v0, v1, v2, v3 };
7971 if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
7972 glVertexAttribI4ui(index, v0, v1, v2, v3);
7976 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
7977 if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
7978 glVertexAttribI4uiv(index, v);
7982 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
7983 uint32 immediate_data_size,
7984 const void* cmd_data) {
7985 if (!unsafe_es3_apis_enabled())
7986 return error::kUnknownCommand;
7987 const gles2::cmds::VertexAttribIPointer& c =
7988 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
7990 if (!state_.bound_array_buffer.get() ||
7991 state_.bound_array_buffer->IsDeleted()) {
7992 if (state_.vertex_attrib_manager.get() ==
7993 state_.default_vertex_attrib_manager.get()) {
7994 LOCAL_SET_GL_ERROR(
7995 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
7996 return error::kNoError;
7997 } else if (c.offset != 0) {
7998 LOCAL_SET_GL_ERROR(
7999 GL_INVALID_VALUE,
8000 "glVertexAttribIPointer", "client side arrays are not allowed");
8001 return error::kNoError;
8005 GLuint indx = c.indx;
8006 GLint size = c.size;
8007 GLenum type = c.type;
8008 GLsizei stride = c.stride;
8009 GLsizei offset = c.offset;
8010 const void* ptr = reinterpret_cast<const void*>(offset);
8011 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
8012 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
8013 return error::kNoError;
8015 if (!validators_->vertex_attrib_size.IsValid(size)) {
8016 LOCAL_SET_GL_ERROR(
8017 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8018 return error::kNoError;
8020 if (indx >= group_->max_vertex_attribs()) {
8021 LOCAL_SET_GL_ERROR(
8022 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
8023 return error::kNoError;
8025 if (stride < 0) {
8026 LOCAL_SET_GL_ERROR(
8027 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
8028 return error::kNoError;
8030 if (stride > 255) {
8031 LOCAL_SET_GL_ERROR(
8032 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
8033 return error::kNoError;
8035 if (offset < 0) {
8036 LOCAL_SET_GL_ERROR(
8037 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
8038 return error::kNoError;
8040 GLsizei component_size =
8041 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8042 // component_size must be a power of two to use & as optimized modulo.
8043 DCHECK(GLES2Util::IsPOT(component_size));
8044 if (offset & (component_size - 1)) {
8045 LOCAL_SET_GL_ERROR(
8046 GL_INVALID_OPERATION,
8047 "glVertexAttribIPointer", "offset not valid for type");
8048 return error::kNoError;
8050 if (stride & (component_size - 1)) {
8051 LOCAL_SET_GL_ERROR(
8052 GL_INVALID_OPERATION,
8053 "glVertexAttribIPointer", "stride not valid for type");
8054 return error::kNoError;
8056 state_.vertex_attrib_manager
8057 ->SetAttribInfo(indx,
8058 state_.bound_array_buffer.get(),
8059 size,
8060 type,
8061 GL_FALSE,
8062 stride,
8063 stride != 0 ? stride : component_size * size,
8064 offset,
8065 GL_TRUE);
8066 glVertexAttribIPointer(indx, size, type, stride, ptr);
8067 return error::kNoError;
8070 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
8071 uint32 immediate_data_size,
8072 const void* cmd_data) {
8073 const gles2::cmds::VertexAttribPointer& c =
8074 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
8076 if (!state_.bound_array_buffer.get() ||
8077 state_.bound_array_buffer->IsDeleted()) {
8078 if (state_.vertex_attrib_manager.get() ==
8079 state_.default_vertex_attrib_manager.get()) {
8080 LOCAL_SET_GL_ERROR(
8081 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
8082 return error::kNoError;
8083 } else if (c.offset != 0) {
8084 LOCAL_SET_GL_ERROR(
8085 GL_INVALID_VALUE,
8086 "glVertexAttribPointer", "client side arrays are not allowed");
8087 return error::kNoError;
8091 GLuint indx = c.indx;
8092 GLint size = c.size;
8093 GLenum type = c.type;
8094 GLboolean normalized = static_cast<GLboolean>(c.normalized);
8095 GLsizei stride = c.stride;
8096 GLsizei offset = c.offset;
8097 const void* ptr = reinterpret_cast<const void*>(offset);
8098 if (!validators_->vertex_attrib_type.IsValid(type)) {
8099 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
8100 return error::kNoError;
8102 if (!validators_->vertex_attrib_size.IsValid(size)) {
8103 LOCAL_SET_GL_ERROR(
8104 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8105 return error::kNoError;
8107 if (indx >= group_->max_vertex_attribs()) {
8108 LOCAL_SET_GL_ERROR(
8109 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
8110 return error::kNoError;
8112 if (stride < 0) {
8113 LOCAL_SET_GL_ERROR(
8114 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
8115 return error::kNoError;
8117 if (stride > 255) {
8118 LOCAL_SET_GL_ERROR(
8119 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
8120 return error::kNoError;
8122 if (offset < 0) {
8123 LOCAL_SET_GL_ERROR(
8124 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
8125 return error::kNoError;
8127 GLsizei component_size =
8128 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8129 // component_size must be a power of two to use & as optimized modulo.
8130 DCHECK(GLES2Util::IsPOT(component_size));
8131 if (offset & (component_size - 1)) {
8132 LOCAL_SET_GL_ERROR(
8133 GL_INVALID_OPERATION,
8134 "glVertexAttribPointer", "offset not valid for type");
8135 return error::kNoError;
8137 if (stride & (component_size - 1)) {
8138 LOCAL_SET_GL_ERROR(
8139 GL_INVALID_OPERATION,
8140 "glVertexAttribPointer", "stride not valid for type");
8141 return error::kNoError;
8143 state_.vertex_attrib_manager
8144 ->SetAttribInfo(indx,
8145 state_.bound_array_buffer.get(),
8146 size,
8147 type,
8148 normalized,
8149 stride,
8150 stride != 0 ? stride : component_size * size,
8151 offset,
8152 GL_FALSE);
8153 // We support GL_FIXED natively on EGL/GLES2 implementations
8154 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
8155 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
8157 return error::kNoError;
8160 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
8161 GLsizei height) {
8162 state_.viewport_x = x;
8163 state_.viewport_y = y;
8164 state_.viewport_width = std::min(width, viewport_max_width_);
8165 state_.viewport_height = std::min(height, viewport_max_height_);
8166 glViewport(x, y, width, height);
8169 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8170 uint32 immediate_data_size,
8171 const void* cmd_data) {
8172 const gles2::cmds::VertexAttribDivisorANGLE& c =
8173 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
8174 if (!features().angle_instanced_arrays) {
8175 LOCAL_SET_GL_ERROR(
8176 GL_INVALID_OPERATION,
8177 "glVertexAttribDivisorANGLE", "function not available");
8178 return error::kNoError;
8180 GLuint index = c.index;
8181 GLuint divisor = c.divisor;
8182 if (index >= group_->max_vertex_attribs()) {
8183 LOCAL_SET_GL_ERROR(
8184 GL_INVALID_VALUE,
8185 "glVertexAttribDivisorANGLE", "index out of range");
8186 return error::kNoError;
8189 state_.vertex_attrib_manager->SetDivisor(
8190 index,
8191 divisor);
8192 glVertexAttribDivisorANGLE(index, divisor);
8193 return error::kNoError;
8196 template <typename pixel_data_type>
8197 static void WriteAlphaData(
8198 void* pixels, uint32 row_count, uint32 channel_count,
8199 uint32 alpha_channel_index, uint32 unpadded_row_size,
8200 uint32 padded_row_size, pixel_data_type alpha_value) {
8201 DCHECK_GT(channel_count, 0U);
8202 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8203 uint32 unpadded_row_size_in_elements =
8204 unpadded_row_size / sizeof(pixel_data_type);
8205 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8206 uint32 padded_row_size_in_elements =
8207 padded_row_size / sizeof(pixel_data_type);
8208 pixel_data_type* dst =
8209 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8210 for (uint32 yy = 0; yy < row_count; ++yy) {
8211 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8212 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8213 *d = alpha_value;
8215 dst += padded_row_size_in_elements;
8219 void GLES2DecoderImpl::FinishReadPixels(
8220 const cmds::ReadPixels& c,
8221 GLuint buffer) {
8222 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8223 GLsizei width = c.width;
8224 GLsizei height = c.height;
8225 GLenum format = c.format;
8226 GLenum type = c.type;
8227 typedef cmds::ReadPixels::Result Result;
8228 uint32 pixels_size;
8229 Result* result = NULL;
8230 if (c.result_shm_id != 0) {
8231 result = GetSharedMemoryAs<Result*>(
8232 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8233 if (!result) {
8234 if (buffer != 0) {
8235 glDeleteBuffersARB(1, &buffer);
8237 return;
8240 GLES2Util::ComputeImageDataSizes(
8241 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8242 NULL, NULL);
8243 void* pixels = GetSharedMemoryAs<void*>(
8244 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8245 if (!pixels) {
8246 if (buffer != 0) {
8247 glDeleteBuffersARB(1, &buffer);
8249 return;
8252 if (buffer != 0) {
8253 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8254 void* data;
8255 if (features().map_buffer_range) {
8256 data = glMapBufferRange(
8257 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8258 } else {
8259 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8261 if (!data) {
8262 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8263 "Unable to map memory for readback.");
8264 return;
8266 memcpy(pixels, data, pixels_size);
8267 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8268 // have to restore the state.
8269 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8270 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8271 glDeleteBuffersARB(1, &buffer);
8274 if (result != NULL) {
8275 *result = true;
8278 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8279 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8280 if ((channels_exist & 0x0008) == 0 &&
8281 workarounds().clear_alpha_in_readpixels) {
8282 // Set the alpha to 255 because some drivers are buggy in this regard.
8283 uint32 temp_size;
8285 uint32 unpadded_row_size;
8286 uint32 padded_row_size;
8287 if (!GLES2Util::ComputeImageDataSizes(
8288 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8289 &unpadded_row_size, &padded_row_size)) {
8290 return;
8293 uint32 channel_count = 0;
8294 uint32 alpha_channel = 0;
8295 switch (format) {
8296 case GL_RGBA:
8297 case GL_BGRA_EXT:
8298 channel_count = 4;
8299 alpha_channel = 3;
8300 break;
8301 case GL_ALPHA:
8302 channel_count = 1;
8303 alpha_channel = 0;
8304 break;
8307 if (channel_count > 0) {
8308 switch (type) {
8309 case GL_UNSIGNED_BYTE:
8310 WriteAlphaData<uint8>(
8311 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8312 padded_row_size, 0xFF);
8313 break;
8314 case GL_FLOAT:
8315 WriteAlphaData<float>(
8316 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8317 padded_row_size, 1.0f);
8318 break;
8319 case GL_HALF_FLOAT:
8320 WriteAlphaData<uint16>(
8321 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8322 padded_row_size, 0x3C00);
8323 break;
8329 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8330 const void* cmd_data) {
8331 const gles2::cmds::ReadPixels& c =
8332 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8333 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8334 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8335 if (fbo_error != error::kNoError)
8336 return fbo_error;
8337 GLint x = c.x;
8338 GLint y = c.y;
8339 GLsizei width = c.width;
8340 GLsizei height = c.height;
8341 GLenum format = c.format;
8342 GLenum type = c.type;
8343 GLboolean async = static_cast<GLboolean>(c.async);
8344 if (width < 0 || height < 0) {
8345 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8346 return error::kNoError;
8348 typedef cmds::ReadPixels::Result Result;
8349 uint32 pixels_size;
8350 if (!GLES2Util::ComputeImageDataSizes(
8351 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8352 NULL, NULL)) {
8353 return error::kOutOfBounds;
8355 void* pixels = GetSharedMemoryAs<void*>(
8356 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8357 if (!pixels) {
8358 return error::kOutOfBounds;
8360 Result* result = NULL;
8361 if (c.result_shm_id != 0) {
8362 result = GetSharedMemoryAs<Result*>(
8363 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8364 if (!result) {
8365 return error::kOutOfBounds;
8369 if (!validators_->read_pixel_format.IsValid(format)) {
8370 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8371 return error::kNoError;
8373 if (!validators_->read_pixel_type.IsValid(type)) {
8374 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8375 return error::kNoError;
8377 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
8378 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
8379 // format and type are acceptable enums but not guaranteed to be supported
8380 // for this framebuffer. Have to ask gl if they are valid.
8381 GLint preferred_format = 0;
8382 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
8383 GLint preferred_type = 0;
8384 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
8385 if (format != static_cast<GLenum>(preferred_format) ||
8386 type != static_cast<GLenum>(preferred_type)) {
8387 LOCAL_SET_GL_ERROR(
8388 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
8389 "with the current read framebuffer");
8390 return error::kNoError;
8393 if (width == 0 || height == 0) {
8394 return error::kNoError;
8397 // Get the size of the current fbo or backbuffer.
8398 gfx::Size max_size = GetBoundReadFrameBufferSize();
8400 int32 max_x;
8401 int32 max_y;
8402 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8403 LOCAL_SET_GL_ERROR(
8404 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8405 return error::kNoError;
8408 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8409 return error::kNoError;
8412 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8413 return error::kNoError;
8416 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8418 ScopedResolvedFrameBufferBinder binder(this, false, true);
8420 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8421 // The user requested an out of range area. Get the results 1 line
8422 // at a time.
8423 uint32 temp_size;
8424 uint32 unpadded_row_size;
8425 uint32 padded_row_size;
8426 if (!GLES2Util::ComputeImageDataSizes(
8427 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8428 &unpadded_row_size, &padded_row_size)) {
8429 LOCAL_SET_GL_ERROR(
8430 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8431 return error::kNoError;
8434 GLint dest_x_offset = std::max(-x, 0);
8435 uint32 dest_row_offset;
8436 if (!GLES2Util::ComputeImageDataSizes(
8437 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8438 &dest_row_offset, NULL, NULL)) {
8439 LOCAL_SET_GL_ERROR(
8440 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8441 return error::kNoError;
8444 // Copy each row into the larger dest rect.
8445 int8* dst = static_cast<int8*>(pixels);
8446 GLint read_x = std::max(0, x);
8447 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8448 GLint read_width = read_end_x - read_x;
8449 for (GLint yy = 0; yy < height; ++yy) {
8450 GLint ry = y + yy;
8452 // Clear the row.
8453 memset(dst, 0, unpadded_row_size);
8455 // If the row is in range, copy it.
8456 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8457 glReadPixels(
8458 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8460 dst += padded_row_size;
8462 } else {
8463 if (async && features().use_async_readpixels) {
8464 GLuint buffer = 0;
8465 glGenBuffersARB(1, &buffer);
8466 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8467 // For ANGLE client version 2, GL_STREAM_READ is not available.
8468 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8469 GL_STATIC_DRAW : GL_STREAM_READ;
8470 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8471 GLenum error = glGetError();
8472 if (error == GL_NO_ERROR) {
8473 glReadPixels(x, y, width, height, format, type, 0);
8474 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8475 new FenceCallback()));
8476 WaitForReadPixels(base::Bind(
8477 &GLES2DecoderImpl::FinishReadPixels,
8478 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8479 <GLES2DecoderImpl>(this),
8480 c, buffer));
8481 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8482 return error::kNoError;
8483 } else {
8484 // On error, unbind pack buffer and fall through to sync readpixels
8485 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8486 glDeleteBuffersARB(1, &buffer);
8489 glReadPixels(x, y, width, height, format, type, pixels);
8491 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8492 if (error == GL_NO_ERROR) {
8493 if (result != NULL) {
8494 *result = true;
8496 FinishReadPixels(c, 0);
8499 return error::kNoError;
8502 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8503 const void* cmd_data) {
8504 const gles2::cmds::PixelStorei& c =
8505 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8506 GLenum pname = c.pname;
8507 GLenum param = c.param;
8508 if (!validators_->pixel_store.IsValid(pname)) {
8509 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8510 return error::kNoError;
8512 switch (pname) {
8513 case GL_PACK_ALIGNMENT:
8514 case GL_UNPACK_ALIGNMENT:
8515 if (!validators_->pixel_store_alignment.IsValid(param)) {
8516 LOCAL_SET_GL_ERROR(
8517 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8518 return error::kNoError;
8520 break;
8521 default:
8522 break;
8524 glPixelStorei(pname, param);
8525 switch (pname) {
8526 case GL_PACK_ALIGNMENT:
8527 state_.pack_alignment = param;
8528 break;
8529 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8530 state_.pack_reverse_row_order = (param != 0);
8531 break;
8532 case GL_UNPACK_ALIGNMENT:
8533 state_.unpack_alignment = param;
8534 break;
8535 default:
8536 // Validation should have prevented us from getting here.
8537 NOTREACHED();
8538 break;
8540 return error::kNoError;
8543 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8544 uint32 immediate_data_size,
8545 const void* cmd_data) {
8546 const gles2::cmds::PostSubBufferCHROMIUM& c =
8547 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8548 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8550 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8552 if (!supports_post_sub_buffer_) {
8553 LOCAL_SET_GL_ERROR(
8554 GL_INVALID_OPERATION,
8555 "glPostSubBufferCHROMIUM", "command not supported by surface");
8556 return error::kNoError;
8558 bool is_tracing;
8559 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8560 &is_tracing);
8561 if (is_tracing) {
8562 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8563 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8564 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8565 is_offscreen ? offscreen_size_ : surface_->GetSize());
8567 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height) !=
8568 gfx::SwapResult::SWAP_FAILED) {
8569 return error::kNoError;
8570 } else {
8571 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8572 return error::kLostContext;
8576 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8577 uint32 immediate_data_size,
8578 const void* cmd_data) {
8579 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8580 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8581 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8582 if (!ref) {
8583 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8584 "glScheduleOverlayPlaneCHROMIUM",
8585 "unknown texture");
8586 return error::kNoError;
8588 gfx::GLImage* image =
8589 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8590 if (!image) {
8591 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8592 "glScheduleOverlayPlaneCHROMIUM",
8593 "unsupported texture format");
8594 return error::kNoError;
8596 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8597 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8598 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8599 "glScheduleOverlayPlaneCHROMIUM",
8600 "invalid transform enum");
8601 return error::kNoError;
8603 if (!surface_->ScheduleOverlayPlane(
8604 c.plane_z_order,
8605 transform,
8606 image,
8607 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8608 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8609 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8610 "glScheduleOverlayPlaneCHROMIUM",
8611 "failed to schedule overlay");
8613 return error::kNoError;
8616 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8617 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8618 const std::string& name_str) {
8619 if (!StringIsValidForGLES(name_str.c_str())) {
8620 LOCAL_SET_GL_ERROR(
8621 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8622 return error::kNoError;
8624 Program* program = GetProgramInfoNotShader(
8625 client_id, "glGetAttribLocation");
8626 if (!program) {
8627 return error::kNoError;
8629 if (!program->IsValid()) {
8630 LOCAL_SET_GL_ERROR(
8631 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8632 return error::kNoError;
8634 GLint* location = GetSharedMemoryAs<GLint*>(
8635 location_shm_id, location_shm_offset, sizeof(GLint));
8636 if (!location) {
8637 return error::kOutOfBounds;
8639 // Require the client to init this incase the context is lost and we are no
8640 // longer executing commands.
8641 if (*location != -1) {
8642 return error::kGenericError;
8644 *location = program->GetAttribLocation(name_str);
8645 return error::kNoError;
8648 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8649 uint32 immediate_data_size,
8650 const void* cmd_data) {
8651 const gles2::cmds::GetAttribLocation& c =
8652 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8653 Bucket* bucket = GetBucket(c.name_bucket_id);
8654 if (!bucket) {
8655 return error::kInvalidArguments;
8657 std::string name_str;
8658 if (!bucket->GetAsString(&name_str)) {
8659 return error::kInvalidArguments;
8661 return GetAttribLocationHelper(
8662 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8665 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8666 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8667 const std::string& name_str) {
8668 if (!StringIsValidForGLES(name_str.c_str())) {
8669 LOCAL_SET_GL_ERROR(
8670 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8671 return error::kNoError;
8673 Program* program = GetProgramInfoNotShader(
8674 client_id, "glGetUniformLocation");
8675 if (!program) {
8676 return error::kNoError;
8678 if (!program->IsValid()) {
8679 LOCAL_SET_GL_ERROR(
8680 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8681 return error::kNoError;
8683 GLint* location = GetSharedMemoryAs<GLint*>(
8684 location_shm_id, location_shm_offset, sizeof(GLint));
8685 if (!location) {
8686 return error::kOutOfBounds;
8688 // Require the client to init this incase the context is lost an we are no
8689 // longer executing commands.
8690 if (*location != -1) {
8691 return error::kGenericError;
8693 *location = program->GetUniformFakeLocation(name_str);
8694 return error::kNoError;
8697 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8698 uint32 immediate_data_size,
8699 const void* cmd_data) {
8700 const gles2::cmds::GetUniformLocation& c =
8701 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8702 Bucket* bucket = GetBucket(c.name_bucket_id);
8703 if (!bucket) {
8704 return error::kInvalidArguments;
8706 std::string name_str;
8707 if (!bucket->GetAsString(&name_str)) {
8708 return error::kInvalidArguments;
8710 return GetUniformLocationHelper(
8711 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8714 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8715 uint32 immediate_data_size,
8716 const void* cmd_data) {
8717 if (!unsafe_es3_apis_enabled())
8718 return error::kUnknownCommand;
8719 const gles2::cmds::GetUniformIndices& c =
8720 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8721 Bucket* bucket = GetBucket(c.names_bucket_id);
8722 if (!bucket) {
8723 return error::kInvalidArguments;
8725 GLsizei count = 0;
8726 std::vector<char*> names;
8727 std::vector<GLint> len;
8728 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8729 return error::kInvalidArguments;
8731 typedef cmds::GetUniformIndices::Result Result;
8732 Result* result = GetSharedMemoryAs<Result*>(
8733 c.indices_shm_id, c.indices_shm_offset,
8734 Result::ComputeSize(static_cast<size_t>(count)));
8735 GLuint* indices = result ? result->GetData() : NULL;
8736 if (indices == NULL) {
8737 return error::kOutOfBounds;
8739 // Check that the client initialized the result.
8740 if (result->size != 0) {
8741 return error::kInvalidArguments;
8743 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8744 if (!program) {
8745 return error::kNoError;
8747 GLuint service_id = program->service_id();
8748 GLint link_status = GL_FALSE;
8749 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8750 if (link_status != GL_TRUE) {
8751 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8752 "glGetUniformIndices", "program not linked");
8753 return error::kNoError;
8755 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8756 glGetUniformIndices(service_id, count, &names[0], indices);
8757 GLenum error = glGetError();
8758 if (error == GL_NO_ERROR) {
8759 result->SetNumResults(count);
8760 } else {
8761 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8763 return error::kNoError;
8766 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8767 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8768 const std::string& name_str) {
8769 GLint* location = GetSharedMemoryAs<GLint*>(
8770 location_shm_id, location_shm_offset, sizeof(GLint));
8771 if (!location) {
8772 return error::kOutOfBounds;
8774 // Require the client to init this incase the context is lost and we are no
8775 // longer executing commands.
8776 if (*location != -1) {
8777 return error::kGenericError;
8779 Program* program = GetProgramInfoNotShader(
8780 client_id, "glGetFragDataLocation");
8781 if (!program) {
8782 return error::kNoError;
8784 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8785 return error::kNoError;
8788 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8789 uint32 immediate_data_size,
8790 const void* cmd_data) {
8791 if (!unsafe_es3_apis_enabled())
8792 return error::kUnknownCommand;
8793 const gles2::cmds::GetFragDataLocation& c =
8794 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8795 Bucket* bucket = GetBucket(c.name_bucket_id);
8796 if (!bucket) {
8797 return error::kInvalidArguments;
8799 std::string name_str;
8800 if (!bucket->GetAsString(&name_str)) {
8801 return error::kInvalidArguments;
8803 return GetFragDataLocationHelper(
8804 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8807 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8808 uint32 immediate_data_size, const void* cmd_data) {
8809 if (!unsafe_es3_apis_enabled())
8810 return error::kUnknownCommand;
8811 const gles2::cmds::GetUniformBlockIndex& c =
8812 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8813 Bucket* bucket = GetBucket(c.name_bucket_id);
8814 if (!bucket) {
8815 return error::kInvalidArguments;
8817 std::string name_str;
8818 if (!bucket->GetAsString(&name_str)) {
8819 return error::kInvalidArguments;
8821 GLuint* index = GetSharedMemoryAs<GLuint*>(
8822 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8823 if (!index) {
8824 return error::kOutOfBounds;
8826 // Require the client to init this in case the context is lost and we are no
8827 // longer executing commands.
8828 if (*index != GL_INVALID_INDEX) {
8829 return error::kGenericError;
8831 Program* program = GetProgramInfoNotShader(
8832 c.program, "glGetUniformBlockIndex");
8833 if (!program) {
8834 return error::kNoError;
8836 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8837 return error::kNoError;
8840 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8841 const void* cmd_data) {
8842 const gles2::cmds::GetString& c =
8843 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8844 GLenum name = static_cast<GLenum>(c.name);
8845 if (!validators_->string_type.IsValid(name)) {
8846 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8847 return error::kNoError;
8850 const char* str = nullptr;
8851 std::string extensions;
8852 switch (name) {
8853 case GL_VERSION:
8854 if (unsafe_es3_apis_enabled())
8855 str = "OpenGL ES 3.0 Chromium";
8856 else
8857 str = "OpenGL ES 2.0 Chromium";
8858 break;
8859 case GL_SHADING_LANGUAGE_VERSION:
8860 if (unsafe_es3_apis_enabled())
8861 str = "OpenGL ES GLSL ES 3.0 Chromium";
8862 else
8863 str = "OpenGL ES GLSL ES 1.0 Chromium";
8864 break;
8865 case GL_RENDERER:
8866 case GL_VENDOR:
8867 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8868 // They are used by WEBGL_debug_renderer_info.
8869 if (!IsWebGLContext())
8870 str = "Chromium";
8871 else
8872 str = reinterpret_cast<const char*>(glGetString(name));
8873 break;
8874 case GL_EXTENSIONS:
8876 // For WebGL contexts, strip out the OES derivatives and
8877 // EXT frag depth extensions if they have not been enabled.
8878 if (IsWebGLContext()) {
8879 extensions = feature_info_->extensions();
8880 if (!derivatives_explicitly_enabled_) {
8881 size_t offset = extensions.find(kOESDerivativeExtension);
8882 if (std::string::npos != offset) {
8883 extensions.replace(offset, arraysize(kOESDerivativeExtension),
8884 std::string());
8887 if (!frag_depth_explicitly_enabled_) {
8888 size_t offset = extensions.find(kEXTFragDepthExtension);
8889 if (std::string::npos != offset) {
8890 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
8891 std::string());
8894 if (!draw_buffers_explicitly_enabled_) {
8895 size_t offset = extensions.find(kEXTDrawBuffersExtension);
8896 if (std::string::npos != offset) {
8897 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
8898 std::string());
8901 if (!shader_texture_lod_explicitly_enabled_) {
8902 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
8903 if (std::string::npos != offset) {
8904 extensions.replace(offset,
8905 arraysize(kEXTShaderTextureLodExtension),
8906 std::string());
8909 } else {
8910 extensions = feature_info_->extensions().c_str();
8912 if (supports_post_sub_buffer_)
8913 extensions += " GL_CHROMIUM_post_sub_buffer";
8914 str = extensions.c_str();
8916 break;
8917 default:
8918 str = reinterpret_cast<const char*>(glGetString(name));
8919 break;
8921 Bucket* bucket = CreateBucket(c.bucket_id);
8922 bucket->SetFromString(str);
8923 return error::kNoError;
8926 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8927 const void* cmd_data) {
8928 const gles2::cmds::BufferData& c =
8929 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8930 GLenum target = static_cast<GLenum>(c.target);
8931 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8932 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8933 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8934 GLenum usage = static_cast<GLenum>(c.usage);
8935 const void* data = NULL;
8936 if (data_shm_id != 0 || data_shm_offset != 0) {
8937 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8938 if (!data) {
8939 return error::kOutOfBounds;
8942 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8943 return error::kNoError;
8946 void GLES2DecoderImpl::DoBufferSubData(
8947 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8948 // Just delegate it. Some validation is actually done before this.
8949 buffer_manager()->ValidateAndDoBufferSubData(
8950 &state_, target, offset, size, data);
8953 bool GLES2DecoderImpl::ClearLevel(Texture* texture,
8954 unsigned target,
8955 int level,
8956 unsigned format,
8957 unsigned type,
8958 int xoffset,
8959 int yoffset,
8960 int width,
8961 int height) {
8962 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8963 if (feature_info_->feature_flags().angle_depth_texture &&
8964 (channels & GLES2Util::kDepth) != 0) {
8965 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8966 // on depth formats.
8967 GLuint fb = 0;
8968 glGenFramebuffersEXT(1, &fb);
8969 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8971 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8972 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8973 GL_DEPTH_ATTACHMENT;
8975 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
8976 texture->service_id(), level);
8977 // ANGLE promises a depth only attachment ok.
8978 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8979 GL_FRAMEBUFFER_COMPLETE) {
8980 return false;
8982 glClearStencil(0);
8983 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8984 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8985 glClearDepth(1.0f);
8986 state_.SetDeviceDepthMask(GL_TRUE);
8987 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
8988 glScissor(xoffset, yoffset, width, height);
8989 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8991 RestoreClearState();
8993 glDeleteFramebuffersEXT(1, &fb);
8994 Framebuffer* framebuffer =
8995 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8996 GLuint fb_service_id =
8997 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8998 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8999 return true;
9002 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
9004 uint32 size;
9005 uint32 padded_row_size;
9006 if (!GLES2Util::ComputeImageDataSizes(
9007 width, height, 1, format, type, state_.unpack_alignment, &size,
9008 NULL, &padded_row_size)) {
9009 return false;
9012 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
9014 int tile_height;
9016 if (size > kMaxZeroSize) {
9017 if (kMaxZeroSize < padded_row_size) {
9018 // That'd be an awfully large texture.
9019 return false;
9021 // We should never have a large total size with a zero row size.
9022 DCHECK_GT(padded_row_size, 0U);
9023 tile_height = kMaxZeroSize / padded_row_size;
9024 if (!GLES2Util::ComputeImageDataSizes(
9025 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
9026 NULL, NULL)) {
9027 return false;
9029 } else {
9030 tile_height = height;
9033 // Assumes the size has already been checked.
9034 scoped_ptr<char[]> zero(new char[size]);
9035 memset(zero.get(), 0, size);
9036 glBindTexture(texture->target(), texture->service_id());
9038 GLint y = 0;
9039 while (y < height) {
9040 GLint h = y + tile_height > height ? height - y : tile_height;
9041 glTexSubImage2D(target, level, xoffset, yoffset + y, width, h, format, type,
9042 zero.get());
9043 y += tile_height;
9045 TextureRef* bound_texture =
9046 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
9047 glBindTexture(texture->target(),
9048 bound_texture ? bound_texture->service_id() : 0);
9049 return true;
9052 namespace {
9054 const int kS3TCBlockWidth = 4;
9055 const int kS3TCBlockHeight = 4;
9056 const int kS3TCDXT1BlockSize = 8;
9057 const int kS3TCDXT3AndDXT5BlockSize = 16;
9058 const int kEACAndETC2BlockSize = 4;
9060 bool IsValidDXTSize(GLint level, GLsizei size) {
9061 return (size == 1) ||
9062 (size == 2) || !(size % kS3TCBlockWidth);
9065 bool IsValidPVRTCSize(GLint level, GLsizei size) {
9066 return GLES2Util::IsPOT(size);
9069 } // anonymous namespace.
9071 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9072 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9073 GLenum format, GLsizei* size_in_bytes) {
9074 base::CheckedNumeric<GLsizei> bytes_required(0);
9076 switch (format) {
9077 case GL_ATC_RGB_AMD:
9078 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9079 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9080 case GL_ETC1_RGB8_OES:
9081 bytes_required =
9082 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9083 bytes_required *=
9084 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9085 bytes_required *= kS3TCDXT1BlockSize;
9086 break;
9087 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9088 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9089 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9090 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9091 bytes_required =
9092 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9093 bytes_required *=
9094 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9095 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
9096 break;
9097 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9098 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9099 bytes_required = std::max(width, 8);
9100 bytes_required *= std::max(height, 8);
9101 bytes_required *= 4;
9102 bytes_required += 7;
9103 bytes_required /= 8;
9104 break;
9105 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9106 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9107 bytes_required = std::max(width, 16);
9108 bytes_required *= std::max(height, 8);
9109 bytes_required *= 2;
9110 bytes_required += 7;
9111 bytes_required /= 8;
9112 break;
9114 // ES3 formats.
9115 case GL_COMPRESSED_R11_EAC:
9116 case GL_COMPRESSED_SIGNED_R11_EAC:
9117 case GL_COMPRESSED_RGB8_ETC2:
9118 case GL_COMPRESSED_SRGB8_ETC2:
9119 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9120 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9121 bytes_required =
9122 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9123 bytes_required *=
9124 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9125 bytes_required *= 8;
9126 bytes_required *= depth;
9127 break;
9128 case GL_COMPRESSED_RG11_EAC:
9129 case GL_COMPRESSED_SIGNED_RG11_EAC:
9130 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9131 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9132 bytes_required =
9133 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9134 bytes_required *=
9135 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9136 bytes_required *= 16;
9137 bytes_required *= depth;
9138 break;
9139 default:
9140 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
9141 return false;
9144 if (!bytes_required.IsValid()) {
9145 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid size");
9146 return false;
9149 *size_in_bytes = bytes_required.ValueOrDefault(0);
9150 return true;
9153 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9154 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9155 GLenum format, GLsizei size) {
9156 GLsizei bytes_required = 0;
9157 if (!GetCompressedTexSizeInBytes(
9158 function_name, width, height, depth, format, &bytes_required)) {
9159 return false;
9162 if (size != bytes_required) {
9163 LOCAL_SET_GL_ERROR(
9164 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
9165 return false;
9168 return true;
9171 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9172 const char* function_name, GLenum target, GLint level,
9173 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
9174 switch (format) {
9175 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9176 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9177 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9178 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9179 DCHECK_EQ(1, depth); // 2D formats.
9180 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
9181 LOCAL_SET_GL_ERROR(
9182 GL_INVALID_OPERATION, function_name,
9183 "width or height invalid for level");
9184 return false;
9186 return true;
9187 case GL_ATC_RGB_AMD:
9188 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9189 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9190 case GL_ETC1_RGB8_OES:
9191 DCHECK_EQ(1, depth); // 2D formats.
9192 if (width <= 0 || height <= 0) {
9193 LOCAL_SET_GL_ERROR(
9194 GL_INVALID_OPERATION, function_name,
9195 "width or height invalid for level");
9196 return false;
9198 return true;
9199 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9200 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9201 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9202 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9203 DCHECK_EQ(1, depth); // 2D formats.
9204 if (!IsValidPVRTCSize(level, width) ||
9205 !IsValidPVRTCSize(level, height)) {
9206 LOCAL_SET_GL_ERROR(
9207 GL_INVALID_OPERATION, function_name,
9208 "width or height invalid for level");
9209 return false;
9211 return true;
9213 // ES3 formats.
9214 case GL_COMPRESSED_R11_EAC:
9215 case GL_COMPRESSED_SIGNED_R11_EAC:
9216 case GL_COMPRESSED_RG11_EAC:
9217 case GL_COMPRESSED_SIGNED_RG11_EAC:
9218 case GL_COMPRESSED_RGB8_ETC2:
9219 case GL_COMPRESSED_SRGB8_ETC2:
9220 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9221 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9222 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9223 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9224 if (width <= 0 || height <= 0 || depth <= 0) {
9225 LOCAL_SET_GL_ERROR(
9226 GL_INVALID_OPERATION, function_name,
9227 "width, height, or depth invalid");
9228 return false;
9230 if (target == GL_TEXTURE_3D) {
9231 LOCAL_SET_GL_ERROR(
9232 GL_INVALID_OPERATION, function_name,
9233 "target invalid for format");
9234 return false;
9236 return true;
9237 default:
9238 return false;
9242 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9243 const char* function_name,
9244 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9245 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9246 Texture* texture) {
9247 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9248 LOCAL_SET_GL_ERROR(
9249 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9250 return false;
9253 switch (format) {
9254 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9255 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9256 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9257 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9258 const int kBlockWidth = 4;
9259 const int kBlockHeight = 4;
9260 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9261 LOCAL_SET_GL_ERROR(
9262 GL_INVALID_OPERATION, function_name,
9263 "xoffset or yoffset not multiple of 4");
9264 return false;
9266 GLsizei tex_width = 0;
9267 GLsizei tex_height = 0;
9268 if (!texture->GetLevelSize(target, level,
9269 &tex_width, &tex_height, nullptr) ||
9270 width - xoffset > tex_width ||
9271 height - yoffset > tex_height) {
9272 LOCAL_SET_GL_ERROR(
9273 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9274 return false;
9276 return ValidateCompressedTexDimensions(
9277 function_name, target, level, width, height, 1, format);
9279 case GL_ATC_RGB_AMD:
9280 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9281 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
9282 LOCAL_SET_GL_ERROR(
9283 GL_INVALID_OPERATION, function_name,
9284 "not supported for ATC textures");
9285 return false;
9287 case GL_ETC1_RGB8_OES: {
9288 LOCAL_SET_GL_ERROR(
9289 GL_INVALID_OPERATION, function_name,
9290 "not supported for ECT1_RGB8_OES textures");
9291 return false;
9293 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9294 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9295 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9296 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
9297 if ((xoffset != 0) || (yoffset != 0)) {
9298 LOCAL_SET_GL_ERROR(
9299 GL_INVALID_OPERATION, function_name,
9300 "xoffset and yoffset must be zero");
9301 return false;
9303 GLsizei tex_width = 0;
9304 GLsizei tex_height = 0;
9305 if (!texture->GetLevelSize(target, level,
9306 &tex_width, &tex_height, nullptr) ||
9307 width != tex_width ||
9308 height != tex_height) {
9309 LOCAL_SET_GL_ERROR(
9310 GL_INVALID_OPERATION, function_name,
9311 "dimensions must match existing texture level dimensions");
9312 return false;
9314 return ValidateCompressedTexDimensions(
9315 function_name, target, level, width, height, 1, format);
9318 // ES3 formats
9319 case GL_COMPRESSED_R11_EAC:
9320 case GL_COMPRESSED_SIGNED_R11_EAC:
9321 case GL_COMPRESSED_RG11_EAC:
9322 case GL_COMPRESSED_SIGNED_RG11_EAC:
9323 case GL_COMPRESSED_RGB8_ETC2:
9324 case GL_COMPRESSED_SRGB8_ETC2:
9325 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9326 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9327 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9328 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9330 const int kBlockSize = 4;
9331 GLsizei tex_width, tex_height;
9332 if (target == GL_TEXTURE_3D ||
9333 !texture->GetLevelSize(target, level,
9334 &tex_width, &tex_height, nullptr) ||
9335 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
9336 ((width % kBlockSize) && xoffset + width != tex_width) ||
9337 ((height % kBlockSize) && yoffset + height != tex_height)) {
9338 LOCAL_SET_GL_ERROR(
9339 GL_INVALID_OPERATION, function_name,
9340 "dimensions must match existing texture level dimensions");
9341 return false;
9343 return true;
9345 default:
9346 return false;
9350 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
9351 GLenum target,
9352 GLint level,
9353 GLenum internal_format,
9354 GLsizei width,
9355 GLsizei height,
9356 GLint border,
9357 GLsizei image_size,
9358 const void* data) {
9359 if (!validators_->texture_target.IsValid(target)) {
9360 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9361 "glCompressedTexImage2D", target, "target");
9362 return error::kNoError;
9364 if (!validators_->compressed_texture_format.IsValid(
9365 internal_format)) {
9366 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9367 "glCompressedTexImage2D", internal_format, "internal_format");
9368 return error::kNoError;
9370 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9371 border != 0) {
9372 LOCAL_SET_GL_ERROR(
9373 GL_INVALID_VALUE,
9374 "glCompressedTexImage2D", "dimensions out of range");
9375 return error::kNoError;
9377 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9378 &state_, target);
9379 if (!texture_ref) {
9380 LOCAL_SET_GL_ERROR(
9381 GL_INVALID_VALUE,
9382 "glCompressedTexImage2D", "unknown texture target");
9383 return error::kNoError;
9385 Texture* texture = texture_ref->texture();
9386 if (texture->IsImmutable()) {
9387 LOCAL_SET_GL_ERROR(
9388 GL_INVALID_OPERATION,
9389 "glCompressedTexImage2D", "texture is immutable");
9390 return error::kNoError;
9393 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
9394 width, height, 1, internal_format) ||
9395 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
9396 1, internal_format, image_size)) {
9397 return error::kNoError;
9400 if (!EnsureGPUMemoryAvailable(image_size)) {
9401 LOCAL_SET_GL_ERROR(
9402 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
9403 return error::kNoError;
9406 if (texture->IsAttachedToFramebuffer()) {
9407 framebuffer_state_.clear_state_dirty = true;
9410 scoped_ptr<int8[]> zero;
9411 if (!data) {
9412 zero.reset(new int8[image_size]);
9413 memset(zero.get(), 0, image_size);
9414 data = zero.get();
9416 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9417 glCompressedTexImage2D(
9418 target, level, internal_format, width, height, border, image_size, data);
9419 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9420 if (error == GL_NO_ERROR) {
9421 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9422 width, height, 1, border, 0, 0,
9423 gfx::Rect(width, height));
9426 // This may be a slow command. Exit command processing to allow for
9427 // context preemption and GPU watchdog checks.
9428 ExitCommandProcessingEarly();
9429 return error::kNoError;
9432 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
9433 uint32 immediate_data_size,
9434 const void* cmd_data) {
9435 const gles2::cmds::CompressedTexImage2D& c =
9436 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
9437 GLenum target = static_cast<GLenum>(c.target);
9438 GLint level = static_cast<GLint>(c.level);
9439 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9440 GLsizei width = static_cast<GLsizei>(c.width);
9441 GLsizei height = static_cast<GLsizei>(c.height);
9442 GLint border = static_cast<GLint>(c.border);
9443 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9444 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9445 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9446 const void* data = NULL;
9447 if (data_shm_id != 0 || data_shm_offset != 0) {
9448 data = GetSharedMemoryAs<const void*>(
9449 data_shm_id, data_shm_offset, image_size);
9450 if (!data) {
9451 return error::kOutOfBounds;
9454 return DoCompressedTexImage2D(
9455 target, level, internal_format, width, height, border, image_size, data);
9458 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9459 uint32 immediate_data_size,
9460 const void* cmd_data) {
9461 const gles2::cmds::CompressedTexImage2DBucket& c =
9462 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
9463 GLenum target = static_cast<GLenum>(c.target);
9464 GLint level = static_cast<GLint>(c.level);
9465 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9466 GLsizei width = static_cast<GLsizei>(c.width);
9467 GLsizei height = static_cast<GLsizei>(c.height);
9468 GLint border = static_cast<GLint>(c.border);
9469 Bucket* bucket = GetBucket(c.bucket_id);
9470 if (!bucket) {
9471 return error::kInvalidArguments;
9473 uint32 data_size = bucket->size();
9474 GLsizei imageSize = data_size;
9475 const void* data = bucket->GetData(0, data_size);
9476 if (!data) {
9477 return error::kInvalidArguments;
9479 return DoCompressedTexImage2D(
9480 target, level, internal_format, width, height, border,
9481 imageSize, data);
9484 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9485 uint32 immediate_data_size,
9486 const void* cmd_data) {
9487 const gles2::cmds::CompressedTexSubImage2DBucket& c =
9488 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
9489 GLenum target = static_cast<GLenum>(c.target);
9490 GLint level = static_cast<GLint>(c.level);
9491 GLint xoffset = static_cast<GLint>(c.xoffset);
9492 GLint yoffset = static_cast<GLint>(c.yoffset);
9493 GLsizei width = static_cast<GLsizei>(c.width);
9494 GLsizei height = static_cast<GLsizei>(c.height);
9495 GLenum format = static_cast<GLenum>(c.format);
9496 Bucket* bucket = GetBucket(c.bucket_id);
9497 if (!bucket) {
9498 return error::kInvalidArguments;
9500 uint32 data_size = bucket->size();
9501 GLsizei imageSize = data_size;
9502 const void* data = bucket->GetData(0, data_size);
9503 if (!data) {
9504 return error::kInvalidArguments;
9506 if (!validators_->texture_target.IsValid(target)) {
9507 LOCAL_SET_GL_ERROR(
9508 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9509 return error::kNoError;
9511 if (!validators_->compressed_texture_format.IsValid(format)) {
9512 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9513 "glCompressedTexSubImage2D", format, "format");
9514 return error::kNoError;
9516 if (width < 0) {
9517 LOCAL_SET_GL_ERROR(
9518 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9519 return error::kNoError;
9521 if (height < 0) {
9522 LOCAL_SET_GL_ERROR(
9523 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9524 return error::kNoError;
9526 if (imageSize < 0) {
9527 LOCAL_SET_GL_ERROR(
9528 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9529 return error::kNoError;
9531 DoCompressedTexSubImage2D(
9532 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9533 return error::kNoError;
9536 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
9537 GLenum target,
9538 GLint level,
9539 GLenum internal_format,
9540 GLsizei width,
9541 GLsizei height,
9542 GLsizei depth,
9543 GLint border,
9544 GLsizei image_size,
9545 const void* data) {
9546 if (!validators_->texture_3_d_target.IsValid(target)) {
9547 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9548 "glCompressedTexImage3D", target, "target");
9549 return error::kNoError;
9551 if (!validators_->compressed_texture_format.IsValid(
9552 internal_format)) {
9553 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9554 "glCompressedTexImage3D", internal_format, "internal_format");
9555 return error::kNoError;
9557 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
9558 border != 0) {
9559 LOCAL_SET_GL_ERROR(
9560 GL_INVALID_VALUE,
9561 "glCompressedTexImage3D", "dimensions out of range");
9562 return error::kNoError;
9564 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9565 &state_, target);
9566 if (!texture_ref) {
9567 LOCAL_SET_GL_ERROR(
9568 GL_INVALID_VALUE,
9569 "glCompressedTexImage3D", "unknown texture target");
9570 return error::kNoError;
9572 Texture* texture = texture_ref->texture();
9573 if (texture->IsImmutable()) {
9574 LOCAL_SET_GL_ERROR(
9575 GL_INVALID_OPERATION,
9576 "glCompressedTexImage3D", "texture is immutable");
9577 return error::kNoError;
9580 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
9581 width, height, depth, internal_format) ||
9582 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
9583 depth, internal_format, image_size)) {
9584 return error::kNoError;
9587 if (!EnsureGPUMemoryAvailable(image_size)) {
9588 LOCAL_SET_GL_ERROR(
9589 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
9590 return error::kNoError;
9593 if (texture->IsAttachedToFramebuffer()) {
9594 framebuffer_state_.clear_state_dirty = true;
9597 scoped_ptr<int8[]> zero;
9598 if (!data) {
9599 zero.reset(new int8[image_size]);
9600 memset(zero.get(), 0, image_size);
9601 data = zero.get();
9603 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9604 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
9605 border, image_size, data);
9606 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9607 if (error == GL_NO_ERROR) {
9608 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9609 width, height, depth, border, 0, 0,
9610 gfx::Rect(width, height));
9613 // This may be a slow command. Exit command processing to allow for
9614 // context preemption and GPU watchdog checks.
9615 ExitCommandProcessingEarly();
9616 return error::kNoError;
9619 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
9620 uint32 immediate_data_size, const void* cmd_data) {
9621 if (!unsafe_es3_apis_enabled())
9622 return error::kUnknownCommand;
9624 const gles2::cmds::CompressedTexImage3D& c =
9625 *static_cast<const gles2::cmds::CompressedTexImage3D*>(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 GLsizei depth = static_cast<GLsizei>(c.depth);
9632 GLint border = static_cast<GLint>(c.border);
9633 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9634 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9635 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9636 const void* data = NULL;
9637 if (data_shm_id != 0 || data_shm_offset != 0) {
9638 data = GetSharedMemoryAs<const void*>(
9639 data_shm_id, data_shm_offset, image_size);
9640 if (!data) {
9641 return error::kOutOfBounds;
9644 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9645 depth, border, image_size, data);
9648 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9649 uint32 immediate_data_size, const void* cmd_data) {
9650 if (!unsafe_es3_apis_enabled())
9651 return error::kUnknownCommand;
9653 const gles2::cmds::CompressedTexImage3DBucket& c =
9654 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
9655 GLenum target = static_cast<GLenum>(c.target);
9656 GLint level = static_cast<GLint>(c.level);
9657 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9658 GLsizei width = static_cast<GLsizei>(c.width);
9659 GLsizei height = static_cast<GLsizei>(c.height);
9660 GLsizei depth = static_cast<GLsizei>(c.depth);
9661 GLint border = static_cast<GLint>(c.border);
9662 Bucket* bucket = GetBucket(c.bucket_id);
9663 if (!bucket) {
9664 return error::kInvalidArguments;
9666 uint32 data_size = bucket->size();
9667 GLsizei imageSize = data_size;
9668 const void* data = bucket->GetData(0, data_size);
9669 if (!data) {
9670 return error::kInvalidArguments;
9672 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9673 depth, border, imageSize, data);
9676 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9677 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9678 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9679 GLsizei image_size, const void* data) {
9680 if (!validators_->texture_3_d_target.IsValid(target)) {
9681 LOCAL_SET_GL_ERROR(
9682 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
9683 return;
9685 if (!validators_->compressed_texture_format.IsValid(format)) {
9686 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9687 "glCompressedTexSubImage3D", format, "format");
9688 return;
9690 if (width < 0 || height < 0 || depth < 0) {
9691 LOCAL_SET_GL_ERROR(
9692 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
9693 return;
9695 if (image_size < 0) {
9696 LOCAL_SET_GL_ERROR(
9697 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
9698 return;
9700 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9701 &state_, target);
9702 if (!texture_ref) {
9703 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9704 "unknown texture for target");
9705 return;
9707 Texture* texture = texture_ref->texture();
9708 GLenum type = 0, internal_format = 0;
9709 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9710 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9711 "level does not exist");
9712 return;
9714 if (internal_format != format) {
9715 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9716 "format does not match internal format");
9717 return;
9719 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
9720 width, height, depth, type)) {
9721 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
9722 "bad dimensions");
9723 return;
9725 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9726 width, height, depth, format,
9727 image_size) ||
9728 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9729 target, level, xoffset, yoffset,
9730 zoffset, width, height, depth,
9731 format, texture)) {
9732 return;
9735 // Note: There is no need to deal with texture cleared tracking here
9736 // because the validation above means you can only get here if the level
9737 // is already a matching compressed format and in that case
9738 // CompressedTexImage3D already cleared the texture.
9739 glCompressedTexSubImage3D(
9740 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9741 image_size, data);
9743 // This may be a slow command. Exit command processing to allow for
9744 // context preemption and GPU watchdog checks.
9745 ExitCommandProcessingEarly();
9748 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9749 uint32 immediate_data_size, const void* cmd_data) {
9750 if (!unsafe_es3_apis_enabled())
9751 return error::kUnknownCommand;
9752 const gles2::cmds::CompressedTexSubImage3DBucket& c =
9753 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
9754 GLenum target = static_cast<GLenum>(c.target);
9755 GLint level = static_cast<GLint>(c.level);
9756 GLint xoffset = static_cast<GLint>(c.xoffset);
9757 GLint yoffset = static_cast<GLint>(c.yoffset);
9758 GLint zoffset = static_cast<GLint>(c.zoffset);
9759 GLsizei width = static_cast<GLsizei>(c.width);
9760 GLsizei height = static_cast<GLsizei>(c.height);
9761 GLsizei depth = static_cast<GLsizei>(c.depth);
9762 GLenum format = static_cast<GLenum>(c.format);
9763 Bucket* bucket = GetBucket(c.bucket_id);
9764 if (!bucket) {
9765 return error::kInvalidArguments;
9767 uint32 data_size = bucket->size();
9768 GLsizei image_size = data_size;
9769 const void* data = bucket->GetData(0, data_size);
9770 if (!data) {
9771 return error::kInvalidArguments;
9773 DoCompressedTexSubImage3D(
9774 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9775 image_size, data);
9776 return error::kNoError;
9779 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9780 const void* cmd_data) {
9781 const gles2::cmds::TexImage2D& c =
9782 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9783 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9784 "width", c.width, "height", c.height);
9785 // Set as failed for now, but if it successed, this will be set to not failed.
9786 texture_state_.tex_image_failed = true;
9787 GLenum target = static_cast<GLenum>(c.target);
9788 GLint level = static_cast<GLint>(c.level);
9789 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9790 // for internalformat.
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 GLint border = static_cast<GLint>(c.border);
9795 GLenum format = static_cast<GLenum>(c.format);
9796 GLenum type = static_cast<GLenum>(c.type);
9797 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9798 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9799 uint32 pixels_size;
9800 if (!GLES2Util::ComputeImageDataSizes(
9801 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9802 NULL, NULL)) {
9803 return error::kOutOfBounds;
9805 const void* pixels = NULL;
9806 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9807 pixels = GetSharedMemoryAs<const void*>(
9808 pixels_shm_id, pixels_shm_offset, pixels_size);
9809 if (!pixels) {
9810 return error::kOutOfBounds;
9814 // For testing only. Allows us to stress the ability to respond to OOM errors.
9815 if (workarounds().simulate_out_of_memory_on_large_textures &&
9816 (width * height >= 4096 * 4096)) {
9817 LOCAL_SET_GL_ERROR(
9818 GL_OUT_OF_MEMORY,
9819 "glTexImage2D", "synthetic out of memory");
9820 return error::kNoError;
9823 TextureManager::DoTexImageArguments args = {
9824 target, level, internal_format, width, height, 1, border, format, type,
9825 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
9826 texture_manager()->ValidateAndDoTexImage(
9827 &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
9829 // This may be a slow command. Exit command processing to allow for
9830 // context preemption and GPU watchdog checks.
9831 ExitCommandProcessingEarly();
9832 return error::kNoError;
9835 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
9836 const void* cmd_data) {
9837 if (!unsafe_es3_apis_enabled())
9838 return error::kUnknownCommand;
9840 const gles2::cmds::TexImage3D& c =
9841 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
9842 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9843 "widthXheight", c.width * c.height, "depth", c.depth);
9844 // Set as failed for now, but if it successed, this will be set to not failed.
9845 texture_state_.tex_image_failed = true;
9846 GLenum target = static_cast<GLenum>(c.target);
9847 GLint level = static_cast<GLint>(c.level);
9848 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9849 GLsizei width = static_cast<GLsizei>(c.width);
9850 GLsizei height = static_cast<GLsizei>(c.height);
9851 GLsizei depth = static_cast<GLsizei>(c.depth);
9852 GLint border = static_cast<GLint>(c.border);
9853 GLenum format = static_cast<GLenum>(c.format);
9854 GLenum type = static_cast<GLenum>(c.type);
9855 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9856 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9857 uint32 pixels_size;
9858 if (!GLES2Util::ComputeImageDataSizes(
9859 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
9860 NULL, NULL)) {
9861 return error::kOutOfBounds;
9863 const void* pixels = NULL;
9864 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9865 pixels = GetSharedMemoryAs<const void*>(
9866 pixels_shm_id, pixels_shm_offset, pixels_size);
9867 if (!pixels) {
9868 return error::kOutOfBounds;
9872 // For testing only. Allows us to stress the ability to respond to OOM errors.
9873 if (workarounds().simulate_out_of_memory_on_large_textures &&
9874 (width * height * depth >= 4096 * 4096)) {
9875 LOCAL_SET_GL_ERROR(
9876 GL_OUT_OF_MEMORY,
9877 "glTexImage3D", "synthetic out of memory");
9878 return error::kNoError;
9881 TextureManager::DoTexImageArguments args = {
9882 target, level, internal_format, width, height, depth, border, format, type,
9883 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
9884 texture_manager()->ValidateAndDoTexImage(
9885 &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
9887 // This may be a slow command. Exit command processing to allow for
9888 // context preemption and GPU watchdog checks.
9889 ExitCommandProcessingEarly();
9890 return error::kNoError;
9893 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9894 GLenum target,
9895 GLint level,
9896 GLint xoffset,
9897 GLint yoffset,
9898 GLsizei width,
9899 GLsizei height,
9900 GLenum format,
9901 GLsizei image_size,
9902 const void * data) {
9903 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9904 &state_, target);
9905 if (!texture_ref) {
9906 LOCAL_SET_GL_ERROR(
9907 GL_INVALID_OPERATION,
9908 "glCompressedTexSubImage2D", "unknown texture for target");
9909 return;
9911 Texture* texture = texture_ref->texture();
9912 GLenum type = 0;
9913 GLenum internal_format = 0;
9914 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9915 LOCAL_SET_GL_ERROR(
9916 GL_INVALID_OPERATION,
9917 "glCompressedTexSubImage2D", "level does not exist.");
9918 return;
9920 if (internal_format != format) {
9921 LOCAL_SET_GL_ERROR(
9922 GL_INVALID_OPERATION,
9923 "glCompressedTexSubImage2D", "format does not match internal format.");
9924 return;
9926 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
9927 height, 1, type)) {
9928 LOCAL_SET_GL_ERROR(
9929 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
9930 return;
9933 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
9934 width, height, 1, format, image_size) ||
9935 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
9936 target, level, xoffset, yoffset, 0,
9937 width, height, 1, format, texture)) {
9938 return;
9942 // Note: There is no need to deal with texture cleared tracking here
9943 // because the validation above means you can only get here if the level
9944 // is already a matching compressed format and in that case
9945 // CompressedTexImage2D already cleared the texture.
9946 glCompressedTexSubImage2D(
9947 target, level, xoffset, yoffset, width, height, format, image_size, data);
9949 // This may be a slow command. Exit command processing to allow for
9950 // context preemption and GPU watchdog checks.
9951 ExitCommandProcessingEarly();
9954 static void Clip(
9955 GLint start, GLint range, GLint sourceRange,
9956 GLint* out_start, GLint* out_range) {
9957 DCHECK(out_start);
9958 DCHECK(out_range);
9959 if (start < 0) {
9960 range += start;
9961 start = 0;
9963 GLint end = start + range;
9964 if (end > sourceRange) {
9965 range -= end - sourceRange;
9967 *out_start = start;
9968 *out_range = range;
9971 void GLES2DecoderImpl::DoCopyTexImage2D(
9972 GLenum target,
9973 GLint level,
9974 GLenum internal_format,
9975 GLint x,
9976 GLint y,
9977 GLsizei width,
9978 GLsizei height,
9979 GLint border) {
9980 DCHECK(!ShouldDeferReads());
9981 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9982 &state_, target);
9983 if (!texture_ref) {
9984 LOCAL_SET_GL_ERROR(
9985 GL_INVALID_OPERATION,
9986 "glCopyTexImage2D", "unknown texture for target");
9987 return;
9989 Texture* texture = texture_ref->texture();
9990 if (texture->IsImmutable()) {
9991 LOCAL_SET_GL_ERROR(
9992 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
9993 return;
9995 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9996 border != 0) {
9997 LOCAL_SET_GL_ERROR(
9998 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
9999 return;
10001 if (!texture_manager()->ValidateFormatAndTypeCombination(
10002 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
10003 GL_UNSIGNED_BYTE)) {
10004 return;
10007 // Check we have compatible formats.
10008 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10009 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10010 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
10012 if ((channels_needed & channels_exist) != channels_needed) {
10013 LOCAL_SET_GL_ERROR(
10014 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
10015 return;
10018 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10019 LOCAL_SET_GL_ERROR(
10020 GL_INVALID_OPERATION,
10021 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10022 return;
10025 uint32 estimated_size = 0;
10026 if (!GLES2Util::ComputeImageDataSizes(
10027 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10028 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
10029 LOCAL_SET_GL_ERROR(
10030 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
10031 return;
10034 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10035 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
10036 return;
10039 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10040 return;
10043 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10044 LOCAL_SET_GL_ERROR(
10045 GL_INVALID_OPERATION,
10046 "glCopyTexImage2D", "source and destination textures are the same");
10047 return;
10050 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10051 return;
10054 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10055 ScopedResolvedFrameBufferBinder binder(this, false, true);
10056 gfx::Size size = GetBoundReadFrameBufferSize();
10058 if (texture->IsAttachedToFramebuffer()) {
10059 framebuffer_state_.clear_state_dirty = true;
10062 // Clip to size to source dimensions
10063 GLint copyX = 0;
10064 GLint copyY = 0;
10065 GLint copyWidth = 0;
10066 GLint copyHeight = 0;
10067 Clip(x, width, size.width(), &copyX, &copyWidth);
10068 Clip(y, height, size.height(), &copyY, &copyHeight);
10070 if (copyX != x ||
10071 copyY != y ||
10072 copyWidth != width ||
10073 copyHeight != height) {
10074 // some part was clipped so clear the rect.
10075 uint32 pixels_size = 0;
10076 if (!GLES2Util::ComputeImageDataSizes(
10077 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10078 state_.unpack_alignment, &pixels_size, NULL, NULL)) {
10079 LOCAL_SET_GL_ERROR(
10080 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
10081 return;
10083 scoped_ptr<char[]> zero(new char[pixels_size]);
10084 memset(zero.get(), 0, pixels_size);
10085 ScopedModifyPixels modify(texture_ref);
10086 glTexImage2D(target, level, internal_format, width, height, border,
10087 internal_format, GL_UNSIGNED_BYTE, zero.get());
10088 if (copyHeight > 0 && copyWidth > 0) {
10089 GLint dx = copyX - x;
10090 GLint dy = copyY - y;
10091 GLint destX = dx;
10092 GLint destY = dy;
10093 glCopyTexSubImage2D(target, level,
10094 destX, destY, copyX, copyY,
10095 copyWidth, copyHeight);
10097 } else {
10098 ScopedModifyPixels modify(texture_ref);
10099 glCopyTexImage2D(target, level, internal_format,
10100 copyX, copyY, copyWidth, copyHeight, border);
10102 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10103 if (error == GL_NO_ERROR) {
10104 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10105 width, height, 1, border, internal_format,
10106 GL_UNSIGNED_BYTE, gfx::Rect(width, height));
10109 // This may be a slow command. Exit command processing to allow for
10110 // context preemption and GPU watchdog checks.
10111 ExitCommandProcessingEarly();
10114 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10115 GLenum target,
10116 GLint level,
10117 GLint xoffset,
10118 GLint yoffset,
10119 GLint x,
10120 GLint y,
10121 GLsizei width,
10122 GLsizei height) {
10123 DCHECK(!ShouldDeferReads());
10124 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10125 &state_, target);
10126 if (!texture_ref) {
10127 LOCAL_SET_GL_ERROR(
10128 GL_INVALID_OPERATION,
10129 "glCopyTexSubImage2D", "unknown texture for target");
10130 return;
10132 Texture* texture = texture_ref->texture();
10133 GLenum type = 0;
10134 GLenum format = 0;
10135 if (!texture->GetLevelType(target, level, &type, &format) ||
10136 !texture->ValidForTexture(
10137 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10138 LOCAL_SET_GL_ERROR(
10139 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
10140 return;
10142 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10143 LOCAL_SET_GL_ERROR(
10144 GL_INVALID_OPERATION,
10145 "glCopyTexSubImage2D", "async upload pending for texture");
10146 return;
10149 // Check we have compatible formats.
10150 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10151 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10152 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
10154 if (!channels_needed ||
10155 (channels_needed & channels_exist) != channels_needed) {
10156 LOCAL_SET_GL_ERROR(
10157 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
10158 return;
10161 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10162 LOCAL_SET_GL_ERROR(
10163 GL_INVALID_OPERATION,
10164 "glCopySubImage2D", "can not be used with depth or stencil textures");
10165 return;
10168 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10169 return;
10172 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10173 LOCAL_SET_GL_ERROR(
10174 GL_INVALID_OPERATION,
10175 "glCopyTexSubImage2D", "source and destination textures are the same");
10176 return;
10179 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10180 return;
10183 ScopedResolvedFrameBufferBinder binder(this, false, true);
10184 gfx::Size size = GetBoundReadFrameBufferSize();
10185 GLint copyX = 0;
10186 GLint copyY = 0;
10187 GLint copyWidth = 0;
10188 GLint copyHeight = 0;
10189 Clip(x, width, size.width(), &copyX, &copyWidth);
10190 Clip(y, height, size.height(), &copyY, &copyHeight);
10192 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
10193 height != size.height()) {
10194 gfx::Rect cleared_rect;
10195 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10196 gfx::Rect(xoffset, yoffset, width, height),
10197 &cleared_rect)) {
10198 DCHECK_GE(cleared_rect.size().GetArea(),
10199 texture->GetLevelClearedRect(target, level).size().GetArea());
10200 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10201 cleared_rect);
10202 } else {
10203 // Otherwise clear part of texture level that is not already cleared.
10204 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10205 level)) {
10206 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
10207 "dimensions too big");
10208 return;
10211 } else {
10212 // Write all pixels in below.
10213 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10216 if (copyX != x ||
10217 copyY != y ||
10218 copyWidth != width ||
10219 copyHeight != height) {
10220 // some part was clipped so clear the sub rect.
10221 uint32 pixels_size = 0;
10222 if (!GLES2Util::ComputeImageDataSizes(
10223 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10224 NULL, NULL)) {
10225 LOCAL_SET_GL_ERROR(
10226 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
10227 return;
10229 scoped_ptr<char[]> zero(new char[pixels_size]);
10230 memset(zero.get(), 0, pixels_size);
10231 ScopedModifyPixels modify(texture_ref);
10232 glTexSubImage2D(
10233 target, level, xoffset, yoffset, width, height,
10234 format, type, zero.get());
10237 if (copyHeight > 0 && copyWidth > 0) {
10238 GLint dx = copyX - x;
10239 GLint dy = copyY - y;
10240 GLint destX = xoffset + dx;
10241 GLint destY = yoffset + dy;
10242 ScopedModifyPixels modify(texture_ref);
10243 glCopyTexSubImage2D(target, level,
10244 destX, destY, copyX, copyY,
10245 copyWidth, copyHeight);
10248 // This may be a slow command. Exit command processing to allow for
10249 // context preemption and GPU watchdog checks.
10250 ExitCommandProcessingEarly();
10253 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10254 error::Error* error,
10255 const char* function_name,
10256 GLenum target,
10257 GLint level,
10258 GLint xoffset,
10259 GLint yoffset,
10260 GLsizei width,
10261 GLsizei height,
10262 GLenum format,
10263 GLenum type,
10264 const void * data) {
10265 (*error) = error::kNoError;
10266 if (!validators_->texture_target.IsValid(target)) {
10267 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10268 return false;
10270 if (width < 0) {
10271 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10272 return false;
10274 if (height < 0) {
10275 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10276 return false;
10278 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10279 &state_, target);
10280 if (!texture_ref) {
10281 LOCAL_SET_GL_ERROR(
10282 GL_INVALID_OPERATION,
10283 function_name, "unknown texture for target");
10284 return false;
10286 Texture* texture = texture_ref->texture();
10287 GLenum current_type = 0;
10288 GLenum internal_format = 0;
10289 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
10290 LOCAL_SET_GL_ERROR(
10291 GL_INVALID_OPERATION, function_name, "level does not exist.");
10292 return false;
10294 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
10295 function_name, format, type, internal_format, level)) {
10296 return false;
10298 if (type != current_type) {
10299 LOCAL_SET_GL_ERROR(
10300 GL_INVALID_OPERATION,
10301 function_name, "type does not match type of texture.");
10302 return false;
10304 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10305 LOCAL_SET_GL_ERROR(
10306 GL_INVALID_OPERATION,
10307 function_name, "async upload pending for texture");
10308 return false;
10310 if (!texture->ValidForTexture(
10311 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10312 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
10313 return false;
10315 if ((GLES2Util::GetChannelsForFormat(format) &
10316 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10317 LOCAL_SET_GL_ERROR(
10318 GL_INVALID_OPERATION,
10319 function_name, "can not supply data for depth or stencil textures");
10320 return false;
10322 if (data == NULL) {
10323 (*error) = error::kOutOfBounds;
10324 return false;
10326 return true;
10329 error::Error GLES2DecoderImpl::DoTexSubImage2D(
10330 GLenum target,
10331 GLint level,
10332 GLint xoffset,
10333 GLint yoffset,
10334 GLsizei width,
10335 GLsizei height,
10336 GLenum format,
10337 GLenum type,
10338 const void * data) {
10339 error::Error error = error::kNoError;
10340 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
10341 xoffset, yoffset, width, height, format, type, data)) {
10342 return error;
10344 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10345 &state_, target);
10346 Texture* texture = texture_ref->texture();
10347 GLsizei tex_width = 0;
10348 GLsizei tex_height = 0;
10349 bool ok = texture->GetLevelSize(
10350 target, level, &tex_width, &tex_height, nullptr);
10351 DCHECK(ok);
10352 if (xoffset != 0 || yoffset != 0 ||
10353 width != tex_width || height != tex_height) {
10354 gfx::Rect cleared_rect;
10355 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10356 gfx::Rect(xoffset, yoffset, width, height),
10357 &cleared_rect)) {
10358 DCHECK_GE(cleared_rect.size().GetArea(),
10359 texture->GetLevelClearedRect(target, level).size().GetArea());
10360 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10361 cleared_rect);
10362 } else {
10363 // Otherwise clear part of texture level that is not already cleared.
10364 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10365 level)) {
10366 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D",
10367 "dimensions too big");
10368 return error::kNoError;
10371 ScopedTextureUploadTimer timer(&texture_state_);
10372 glTexSubImage2D(
10373 target, level, xoffset, yoffset, width, height, format, type, data);
10374 return error::kNoError;
10377 if (!texture_state_.texsubimage_faster_than_teximage &&
10378 !texture->IsImmutable() &&
10379 !texture->HasImages()) {
10380 ScopedTextureUploadTimer timer(&texture_state_);
10381 GLenum internal_format;
10382 GLenum tex_type;
10383 texture->GetLevelType(target, level, &tex_type, &internal_format);
10384 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10385 // to look it up.
10386 glTexImage2D(
10387 target, level, internal_format, width, height, 0, format, type, data);
10388 } else {
10389 ScopedTextureUploadTimer timer(&texture_state_);
10390 glTexSubImage2D(
10391 target, level, xoffset, yoffset, width, height, format, type, data);
10393 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10395 // This may be a slow command. Exit command processing to allow for
10396 // context preemption and GPU watchdog checks.
10397 ExitCommandProcessingEarly();
10398 return error::kNoError;
10401 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
10402 const void* cmd_data) {
10403 const gles2::cmds::TexSubImage2D& c =
10404 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
10405 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10406 "width", c.width, "height", c.height);
10407 GLboolean internal = static_cast<GLboolean>(c.internal);
10408 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10409 return error::kNoError;
10411 GLenum target = static_cast<GLenum>(c.target);
10412 GLint level = static_cast<GLint>(c.level);
10413 GLint xoffset = static_cast<GLint>(c.xoffset);
10414 GLint yoffset = static_cast<GLint>(c.yoffset);
10415 GLsizei width = static_cast<GLsizei>(c.width);
10416 GLsizei height = static_cast<GLsizei>(c.height);
10417 GLenum format = static_cast<GLenum>(c.format);
10418 GLenum type = static_cast<GLenum>(c.type);
10419 uint32 data_size;
10420 if (!GLES2Util::ComputeImageDataSizes(
10421 width, height, 1, format, type, state_.unpack_alignment, &data_size,
10422 NULL, NULL)) {
10423 return error::kOutOfBounds;
10425 const void* pixels = GetSharedMemoryAs<const void*>(
10426 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10427 return DoTexSubImage2D(
10428 target, level, xoffset, yoffset, width, height, format, type, pixels);
10431 error::Error GLES2DecoderImpl::DoTexSubImage3D(
10432 GLenum target,
10433 GLint level,
10434 GLint xoffset,
10435 GLint yoffset,
10436 GLint zoffset,
10437 GLsizei width,
10438 GLsizei height,
10439 GLsizei depth,
10440 GLenum format,
10441 GLenum type,
10442 const void * data) {
10443 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10444 &state_, target);
10445 if (!texture_ref) {
10446 LOCAL_SET_GL_ERROR(
10447 GL_INVALID_ENUM, "glTexSubImage3D", "invalid target");
10450 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10451 ScopedTextureUploadTimer timer(&texture_state_);
10452 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
10453 depth, format, type, data);
10454 GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10455 if (error == GL_NO_ERROR) {
10456 // TODO(zmo): This is not 100% correct because only part of the level
10457 // image is cleared.
10458 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10461 // This may be a slow command. Exit command processing to allow for
10462 // context preemption and GPU watchdog checks.
10463 ExitCommandProcessingEarly();
10464 return error::kNoError;
10467 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
10468 const void* cmd_data) {
10469 if (!unsafe_es3_apis_enabled())
10470 return error::kUnknownCommand;
10472 const gles2::cmds::TexSubImage3D& c =
10473 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
10474 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10475 "widthXheight", c.width * c.height, "depth", c.depth);
10476 GLboolean internal = static_cast<GLboolean>(c.internal);
10477 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10478 return error::kNoError;
10480 GLenum target = static_cast<GLenum>(c.target);
10481 GLint level = static_cast<GLint>(c.level);
10482 GLint xoffset = static_cast<GLint>(c.xoffset);
10483 GLint yoffset = static_cast<GLint>(c.yoffset);
10484 GLint zoffset = static_cast<GLint>(c.zoffset);
10485 GLsizei width = static_cast<GLsizei>(c.width);
10486 GLsizei height = static_cast<GLsizei>(c.height);
10487 GLsizei depth = static_cast<GLsizei>(c.depth);
10488 GLenum format = static_cast<GLenum>(c.format);
10489 GLenum type = static_cast<GLenum>(c.type);
10490 uint32 data_size;
10491 if (!GLES2Util::ComputeImageDataSizes(
10492 width, height, depth, format, type, state_.unpack_alignment, &data_size,
10493 NULL, NULL)) {
10494 return error::kOutOfBounds;
10496 const void* pixels = GetSharedMemoryAs<const void*>(
10497 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10498 return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
10499 height, depth, format, type, pixels);
10502 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10503 uint32 immediate_data_size,
10504 const void* cmd_data) {
10505 const gles2::cmds::GetVertexAttribPointerv& c =
10506 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
10507 GLuint index = static_cast<GLuint>(c.index);
10508 GLenum pname = static_cast<GLenum>(c.pname);
10509 typedef cmds::GetVertexAttribPointerv::Result Result;
10510 Result* result = GetSharedMemoryAs<Result*>(
10511 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
10512 if (!result) {
10513 return error::kOutOfBounds;
10515 // Check that the client initialized the result.
10516 if (result->size != 0) {
10517 return error::kInvalidArguments;
10519 if (!validators_->vertex_pointer.IsValid(pname)) {
10520 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10521 "glGetVertexAttribPointerv", pname, "pname");
10522 return error::kNoError;
10524 if (index >= group_->max_vertex_attribs()) {
10525 LOCAL_SET_GL_ERROR(
10526 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
10527 return error::kNoError;
10529 result->SetNumResults(1);
10530 *result->GetData() =
10531 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
10532 return error::kNoError;
10535 template <class T>
10536 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
10537 GLint fake_location,
10538 uint32 shm_id,
10539 uint32 shm_offset,
10540 error::Error* error,
10541 GLint* real_location,
10542 GLuint* service_id,
10543 SizedResult<T>** result_pointer,
10544 GLenum* result_type,
10545 GLsizei* result_size) {
10546 DCHECK(error);
10547 DCHECK(service_id);
10548 DCHECK(result_pointer);
10549 DCHECK(result_type);
10550 DCHECK(result_size);
10551 DCHECK(real_location);
10552 *error = error::kNoError;
10553 // Make sure we have enough room for the result on failure.
10554 SizedResult<T>* result;
10555 result = GetSharedMemoryAs<SizedResult<T>*>(
10556 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
10557 if (!result) {
10558 *error = error::kOutOfBounds;
10559 return false;
10561 *result_pointer = result;
10562 // Set the result size to 0 so the client does not have to check for success.
10563 result->SetNumResults(0);
10564 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
10565 if (!program) {
10566 return false;
10568 if (!program->IsValid()) {
10569 // Program was not linked successfully. (ie, glLinkProgram)
10570 LOCAL_SET_GL_ERROR(
10571 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
10572 return false;
10574 *service_id = program->service_id();
10575 GLint array_index = -1;
10576 const Program::UniformInfo* uniform_info =
10577 program->GetUniformInfoByFakeLocation(
10578 fake_location, real_location, &array_index);
10579 if (!uniform_info) {
10580 // No such location.
10581 LOCAL_SET_GL_ERROR(
10582 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
10583 return false;
10585 GLenum type = uniform_info->type;
10586 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
10587 if (num_elements == 0) {
10588 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
10589 return false;
10591 result = GetSharedMemoryAs<SizedResult<T>*>(
10592 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
10593 if (!result) {
10594 *error = error::kOutOfBounds;
10595 return false;
10597 result->SetNumResults(num_elements);
10598 *result_size = num_elements * sizeof(T);
10599 *result_type = type;
10600 return true;
10603 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
10604 const void* cmd_data) {
10605 const gles2::cmds::GetUniformiv& c =
10606 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
10607 GLuint program = c.program;
10608 GLint fake_location = c.location;
10609 GLuint service_id;
10610 GLenum result_type;
10611 GLsizei result_size;
10612 GLint real_location = -1;
10613 Error error;
10614 cmds::GetUniformiv::Result* result;
10615 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
10616 c.params_shm_offset, &error, &real_location,
10617 &service_id, &result, &result_type,
10618 &result_size)) {
10619 glGetUniformiv(
10620 service_id, real_location, result->GetData());
10622 return error;
10625 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
10626 const void* cmd_data) {
10627 if (!unsafe_es3_apis_enabled())
10628 return error::kUnknownCommand;
10630 const gles2::cmds::GetUniformuiv& c =
10631 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
10632 GLuint program = c.program;
10633 GLint fake_location = c.location;
10634 GLuint service_id;
10635 GLenum result_type;
10636 GLsizei result_size;
10637 GLint real_location = -1;
10638 Error error;
10639 cmds::GetUniformuiv::Result* result;
10640 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
10641 c.params_shm_offset, &error, &real_location,
10642 &service_id, &result, &result_type,
10643 &result_size)) {
10644 glGetUniformuiv(
10645 service_id, real_location, result->GetData());
10647 return error;
10650 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
10651 const void* cmd_data) {
10652 const gles2::cmds::GetUniformfv& c =
10653 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
10654 GLuint program = c.program;
10655 GLint fake_location = c.location;
10656 GLuint service_id;
10657 GLint real_location = -1;
10658 Error error;
10659 cmds::GetUniformfv::Result* result;
10660 GLenum result_type;
10661 GLsizei result_size;
10662 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
10663 c.params_shm_offset, &error, &real_location,
10664 &service_id, &result, &result_type,
10665 &result_size)) {
10666 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
10667 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
10668 GLsizei num_values = result_size / sizeof(GLfloat);
10669 scoped_ptr<GLint[]> temp(new GLint[num_values]);
10670 glGetUniformiv(service_id, real_location, temp.get());
10671 GLfloat* dst = result->GetData();
10672 for (GLsizei ii = 0; ii < num_values; ++ii) {
10673 dst[ii] = (temp[ii] != 0);
10675 } else {
10676 glGetUniformfv(service_id, real_location, result->GetData());
10679 return error;
10682 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10683 uint32 immediate_data_size,
10684 const void* cmd_data) {
10685 const gles2::cmds::GetShaderPrecisionFormat& c =
10686 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
10687 GLenum shader_type = static_cast<GLenum>(c.shadertype);
10688 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
10689 typedef cmds::GetShaderPrecisionFormat::Result Result;
10690 Result* result = GetSharedMemoryAs<Result*>(
10691 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10692 if (!result) {
10693 return error::kOutOfBounds;
10695 // Check that the client initialized the result.
10696 if (result->success != 0) {
10697 return error::kInvalidArguments;
10699 if (!validators_->shader_type.IsValid(shader_type)) {
10700 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10701 "glGetShaderPrecisionFormat", shader_type, "shader_type");
10702 return error::kNoError;
10704 if (!validators_->shader_precision.IsValid(precision_type)) {
10705 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10706 "glGetShaderPrecisionFormat", precision_type, "precision_type");
10707 return error::kNoError;
10710 result->success = 1; // true
10712 GLint range[2] = { 0, 0 };
10713 GLint precision = 0;
10714 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
10716 result->min_range = range[0];
10717 result->max_range = range[1];
10718 result->precision = precision;
10720 return error::kNoError;
10723 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
10724 uint32 immediate_data_size,
10725 const void* cmd_data) {
10726 const gles2::cmds::GetAttachedShaders& c =
10727 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
10728 uint32 result_size = c.result_size;
10729 GLuint program_id = static_cast<GLuint>(c.program);
10730 Program* program = GetProgramInfoNotShader(
10731 program_id, "glGetAttachedShaders");
10732 if (!program) {
10733 return error::kNoError;
10735 typedef cmds::GetAttachedShaders::Result Result;
10736 uint32 max_count = Result::ComputeMaxResults(result_size);
10737 Result* result = GetSharedMemoryAs<Result*>(
10738 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
10739 if (!result) {
10740 return error::kOutOfBounds;
10742 // Check that the client initialized the result.
10743 if (result->size != 0) {
10744 return error::kInvalidArguments;
10746 GLsizei count = 0;
10747 glGetAttachedShaders(
10748 program->service_id(), max_count, &count, result->GetData());
10749 for (GLsizei ii = 0; ii < count; ++ii) {
10750 if (!shader_manager()->GetClientId(result->GetData()[ii],
10751 &result->GetData()[ii])) {
10752 NOTREACHED();
10753 return error::kGenericError;
10756 result->SetNumResults(count);
10757 return error::kNoError;
10760 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
10761 uint32 immediate_data_size,
10762 const void* cmd_data) {
10763 const gles2::cmds::GetActiveUniform& c =
10764 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
10765 GLuint program_id = c.program;
10766 GLuint index = c.index;
10767 uint32 name_bucket_id = c.name_bucket_id;
10768 typedef cmds::GetActiveUniform::Result Result;
10769 Result* result = GetSharedMemoryAs<Result*>(
10770 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10771 if (!result) {
10772 return error::kOutOfBounds;
10774 // Check that the client initialized the result.
10775 if (result->success != 0) {
10776 return error::kInvalidArguments;
10778 Program* program = GetProgramInfoNotShader(
10779 program_id, "glGetActiveUniform");
10780 if (!program) {
10781 return error::kNoError;
10783 const Program::UniformInfo* uniform_info =
10784 program->GetUniformInfo(index);
10785 if (!uniform_info) {
10786 LOCAL_SET_GL_ERROR(
10787 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
10788 return error::kNoError;
10790 result->success = 1; // true.
10791 result->size = uniform_info->size;
10792 result->type = uniform_info->type;
10793 Bucket* bucket = CreateBucket(name_bucket_id);
10794 bucket->SetFromString(uniform_info->name.c_str());
10795 return error::kNoError;
10798 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10799 uint32 immediate_data_size, const void* cmd_data) {
10800 if (!unsafe_es3_apis_enabled())
10801 return error::kUnknownCommand;
10802 const gles2::cmds::GetActiveUniformBlockiv& c =
10803 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
10804 GLuint program_id = c.program;
10805 GLuint index = static_cast<GLuint>(c.index);
10806 GLenum pname = static_cast<GLenum>(c.pname);
10807 Program* program = GetProgramInfoNotShader(
10808 program_id, "glGetActiveUniformBlockiv");
10809 if (!program) {
10810 return error::kNoError;
10812 GLuint service_id = program->service_id();
10813 GLint link_status = GL_FALSE;
10814 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10815 if (link_status != GL_TRUE) {
10816 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10817 "glGetActiveActiveUniformBlockiv", "program not linked");
10818 return error::kNoError;
10820 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10821 GLsizei num_values = 1;
10822 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
10823 GLint num = 0;
10824 glGetActiveUniformBlockiv(
10825 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
10826 GLenum error = glGetError();
10827 if (error != GL_NO_ERROR) {
10828 // Assume this will the same error if calling with pname.
10829 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10830 return error::kNoError;
10832 num_values = static_cast<GLsizei>(num);
10834 typedef cmds::GetActiveUniformBlockiv::Result Result;
10835 Result* result = GetSharedMemoryAs<Result*>(
10836 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
10837 GLint* params = result ? result->GetData() : NULL;
10838 if (params == NULL) {
10839 return error::kOutOfBounds;
10841 // Check that the client initialized the result.
10842 if (result->size != 0) {
10843 return error::kInvalidArguments;
10845 glGetActiveUniformBlockiv(service_id, index, pname, params);
10846 GLenum error = glGetError();
10847 if (error == GL_NO_ERROR) {
10848 result->SetNumResults(num_values);
10849 } else {
10850 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10852 return error::kNoError;
10855 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10856 uint32 immediate_data_size, const void* cmd_data) {
10857 if (!unsafe_es3_apis_enabled())
10858 return error::kUnknownCommand;
10859 const gles2::cmds::GetActiveUniformBlockName& c =
10860 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
10861 GLuint program_id = c.program;
10862 GLuint index = c.index;
10863 uint32 name_bucket_id = c.name_bucket_id;
10864 typedef cmds::GetActiveUniformBlockName::Result Result;
10865 Result* result = GetSharedMemoryAs<Result*>(
10866 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10867 if (!result) {
10868 return error::kOutOfBounds;
10870 // Check that the client initialized the result.
10871 if (*result != 0) {
10872 return error::kInvalidArguments;
10874 Program* program = GetProgramInfoNotShader(
10875 program_id, "glGetActiveUniformBlockName");
10876 if (!program) {
10877 return error::kNoError;
10879 GLuint service_id = program->service_id();
10880 GLint link_status = GL_FALSE;
10881 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10882 if (link_status != GL_TRUE) {
10883 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10884 "glGetActiveActiveUniformBlockName", "program not linked");
10885 return error::kNoError;
10887 GLint max_length = 0;
10888 glGetProgramiv(
10889 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
10890 // Increase one so &buffer[0] is always valid.
10891 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
10892 std::vector<char> buffer(buf_size);
10893 GLsizei length = 0;
10894 glGetActiveUniformBlockName(
10895 service_id, index, buf_size, &length, &buffer[0]);
10896 if (length == 0) {
10897 *result = 0;
10898 return error::kNoError;
10900 *result = 1;
10901 Bucket* bucket = CreateBucket(name_bucket_id);
10902 DCHECK_GT(buf_size, length);
10903 DCHECK_EQ(0, buffer[length]);
10904 bucket->SetFromString(&buffer[0]);
10905 return error::kNoError;
10908 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
10909 uint32 immediate_data_size, const void* cmd_data) {
10910 if (!unsafe_es3_apis_enabled())
10911 return error::kUnknownCommand;
10912 const gles2::cmds::GetActiveUniformsiv& c =
10913 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
10914 GLuint program_id = c.program;
10915 GLenum pname = static_cast<GLenum>(c.pname);
10916 Bucket* bucket = GetBucket(c.indices_bucket_id);
10917 if (!bucket) {
10918 return error::kInvalidArguments;
10920 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
10921 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
10922 typedef cmds::GetActiveUniformsiv::Result Result;
10923 Result* result = GetSharedMemoryAs<Result*>(
10924 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
10925 GLint* params = result ? result->GetData() : NULL;
10926 if (params == NULL) {
10927 return error::kOutOfBounds;
10929 // Check that the client initialized the result.
10930 if (result->size != 0) {
10931 return error::kInvalidArguments;
10933 Program* program = GetProgramInfoNotShader(
10934 program_id, "glGetActiveUniformsiv");
10935 if (!program) {
10936 return error::kNoError;
10938 GLuint service_id = program->service_id();
10939 GLint link_status = GL_FALSE;
10940 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10941 if (link_status != GL_TRUE) {
10942 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10943 "glGetActiveUniformsiv", "program not linked");
10944 return error::kNoError;
10946 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10947 glGetActiveUniformsiv(service_id, count, indices, pname, params);
10948 GLenum error = glGetError();
10949 if (error == GL_NO_ERROR) {
10950 result->SetNumResults(count);
10951 } else {
10952 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
10954 return error::kNoError;
10957 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
10958 const void* cmd_data) {
10959 const gles2::cmds::GetActiveAttrib& c =
10960 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
10961 GLuint program_id = c.program;
10962 GLuint index = c.index;
10963 uint32 name_bucket_id = c.name_bucket_id;
10964 typedef cmds::GetActiveAttrib::Result Result;
10965 Result* result = GetSharedMemoryAs<Result*>(
10966 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10967 if (!result) {
10968 return error::kOutOfBounds;
10970 // Check that the client initialized the result.
10971 if (result->success != 0) {
10972 return error::kInvalidArguments;
10974 Program* program = GetProgramInfoNotShader(
10975 program_id, "glGetActiveAttrib");
10976 if (!program) {
10977 return error::kNoError;
10979 const Program::VertexAttrib* attrib_info =
10980 program->GetAttribInfo(index);
10981 if (!attrib_info) {
10982 LOCAL_SET_GL_ERROR(
10983 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
10984 return error::kNoError;
10986 result->success = 1; // true.
10987 result->size = attrib_info->size;
10988 result->type = attrib_info->type;
10989 Bucket* bucket = CreateBucket(name_bucket_id);
10990 bucket->SetFromString(attrib_info->name.c_str());
10991 return error::kNoError;
10994 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
10995 const void* cmd_data) {
10996 #if 1 // No binary shader support.
10997 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
10998 return error::kNoError;
10999 #else
11000 GLsizei n = static_cast<GLsizei>(c.n);
11001 if (n < 0) {
11002 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
11003 return error::kNoError;
11005 GLsizei length = static_cast<GLsizei>(c.length);
11006 if (length < 0) {
11007 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
11008 return error::kNoError;
11010 uint32 data_size;
11011 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
11012 return error::kOutOfBounds;
11014 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
11015 c.shaders_shm_id, c.shaders_shm_offset, data_size);
11016 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
11017 const void* binary = GetSharedMemoryAs<const void*>(
11018 c.binary_shm_id, c.binary_shm_offset, length);
11019 if (shaders == NULL || binary == NULL) {
11020 return error::kOutOfBounds;
11022 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11023 for (GLsizei ii = 0; ii < n; ++ii) {
11024 Shader* shader = GetShader(shaders[ii]);
11025 if (!shader) {
11026 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
11027 return error::kNoError;
11029 service_ids[ii] = shader->service_id();
11031 // TODO(gman): call glShaderBinary
11032 return error::kNoError;
11033 #endif
11036 void GLES2DecoderImpl::DoSwapBuffers() {
11037 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
11039 int this_frame_number = frame_number_++;
11040 // TRACE_EVENT for gpu tests:
11041 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11042 TRACE_EVENT_SCOPE_THREAD,
11043 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11044 "width", (is_offscreen ? offscreen_size_.width() :
11045 surface_->GetSize().width()));
11046 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11047 "offscreen", is_offscreen,
11048 "frame", this_frame_number);
11050 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11053 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
11054 "GLES2Decoder", "SwapBuffer");
11056 bool is_tracing;
11057 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11058 &is_tracing);
11059 if (is_tracing) {
11060 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
11061 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
11062 is_offscreen ? offscreen_size_ : surface_->GetSize());
11065 // If offscreen then don't actually SwapBuffers to the display. Just copy
11066 // the rendered frame to another frame buffer.
11067 if (is_offscreen) {
11068 TRACE_EVENT2("gpu", "Offscreen",
11069 "width", offscreen_size_.width(), "height", offscreen_size_.height());
11070 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
11071 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11072 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11073 // fix this.
11074 if (workarounds().needs_offscreen_buffer_workaround) {
11075 offscreen_saved_frame_buffer_->Create();
11076 glFinish();
11079 // Allocate the offscreen saved color texture.
11080 DCHECK(offscreen_saved_color_format_);
11081 offscreen_saved_color_texture_->AllocateStorage(
11082 offscreen_size_, offscreen_saved_color_format_, false);
11084 offscreen_saved_frame_buffer_->AttachRenderTexture(
11085 offscreen_saved_color_texture_.get());
11086 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
11087 if (offscreen_saved_frame_buffer_->CheckStatus() !=
11088 GL_FRAMEBUFFER_COMPLETE) {
11089 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11090 << "because offscreen saved FBO was incomplete.";
11091 MarkContextLost(error::kUnknown);
11092 group_->LoseContexts(error::kUnknown);
11093 return;
11096 // Clear the offscreen color texture.
11097 // TODO(piman): Is this still necessary?
11099 ScopedFrameBufferBinder binder(this,
11100 offscreen_saved_frame_buffer_->id());
11101 glClearColor(0, 0, 0, 0);
11102 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
11103 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
11104 glClear(GL_COLOR_BUFFER_BIT);
11105 RestoreClearState();
11109 UpdateParentTextureInfo();
11112 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
11113 return;
11114 ScopedGLErrorSuppressor suppressor(
11115 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11117 if (IsOffscreenBufferMultisampled()) {
11118 // For multisampled buffers, resolve the frame buffer.
11119 ScopedResolvedFrameBufferBinder binder(this, true, false);
11120 } else {
11121 ScopedFrameBufferBinder binder(this,
11122 offscreen_target_frame_buffer_->id());
11124 if (offscreen_target_buffer_preserved_) {
11125 // Copy the target frame buffer to the saved offscreen texture.
11126 offscreen_saved_color_texture_->Copy(
11127 offscreen_saved_color_texture_->size(),
11128 offscreen_saved_color_format_);
11129 } else {
11130 // Flip the textures in the parent context via the texture manager.
11131 if (!!offscreen_saved_color_texture_info_.get())
11132 offscreen_saved_color_texture_info_->texture()->
11133 SetServiceId(offscreen_target_color_texture_->id());
11135 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
11136 offscreen_target_frame_buffer_->AttachRenderTexture(
11137 offscreen_target_color_texture_.get());
11140 // Ensure the side effects of the copy are visible to the parent
11141 // context. There is no need to do this for ANGLE because it uses a
11142 // single D3D device for all contexts.
11143 if (!feature_info_->gl_version_info().is_angle)
11144 glFlush();
11146 } else {
11147 if (surface_->SwapBuffers() == gfx::SwapResult::SWAP_FAILED) {
11148 LOG(ERROR) << "Context lost because SwapBuffers failed.";
11149 if (!CheckResetStatus()) {
11150 MarkContextLost(error::kUnknown);
11151 group_->LoseContexts(error::kUnknown);
11156 // This may be a slow command. Exit command processing to allow for
11157 // context preemption and GPU watchdog checks.
11158 ExitCommandProcessingEarly();
11161 void GLES2DecoderImpl::DoSwapInterval(int interval) {
11162 context_->SetSwapInterval(interval);
11165 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11166 uint32 immediate_data_size,
11167 const void* cmd_data) {
11168 const gles2::cmds::EnableFeatureCHROMIUM& c =
11169 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
11170 Bucket* bucket = GetBucket(c.bucket_id);
11171 if (!bucket || bucket->size() == 0) {
11172 return error::kInvalidArguments;
11174 typedef cmds::EnableFeatureCHROMIUM::Result Result;
11175 Result* result = GetSharedMemoryAs<Result*>(
11176 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11177 if (!result) {
11178 return error::kOutOfBounds;
11180 // Check that the client initialized the result.
11181 if (*result != 0) {
11182 return error::kInvalidArguments;
11184 std::string feature_str;
11185 if (!bucket->GetAsString(&feature_str)) {
11186 return error::kInvalidArguments;
11189 // TODO(gman): make this some kind of table to function pointer thingy.
11190 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11191 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11192 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
11193 buffer_manager()->set_allow_fixed_attribs(true);
11194 // TODO(gman): decide how to remove the need for this const_cast.
11195 // I could make validators_ non const but that seems bad as this is the only
11196 // place it is needed. I could make some special friend class of validators
11197 // just to allow this to set them. That seems silly. I could refactor this
11198 // code to use the extension mechanism or the initialization attributes to
11199 // turn this feature on. Given that the only real point of this is to make
11200 // the conformance tests pass and given that there is lots of real work that
11201 // needs to be done it seems like refactoring for one to one of those
11202 // methods is a very low priority.
11203 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
11204 } else {
11205 return error::kNoError;
11208 *result = 1; // true.
11209 return error::kNoError;
11212 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11213 uint32 immediate_data_size,
11214 const void* cmd_data) {
11215 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
11216 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
11217 cmd_data);
11218 Bucket* bucket = CreateBucket(c.bucket_id);
11219 scoped_refptr<FeatureInfo> info(new FeatureInfo());
11220 info->Initialize(disallowed_features_);
11221 bucket->SetFromString(info->extensions().c_str());
11222 return error::kNoError;
11225 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11226 uint32 immediate_data_size,
11227 const void* cmd_data) {
11228 const gles2::cmds::RequestExtensionCHROMIUM& c =
11229 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
11230 Bucket* bucket = GetBucket(c.bucket_id);
11231 if (!bucket || bucket->size() == 0) {
11232 return error::kInvalidArguments;
11234 std::string feature_str;
11235 if (!bucket->GetAsString(&feature_str)) {
11236 return error::kInvalidArguments;
11239 bool desire_standard_derivatives = false;
11240 bool desire_frag_depth = false;
11241 bool desire_draw_buffers = false;
11242 bool desire_shader_texture_lod = false;
11243 if (IsWebGLContext()) {
11244 desire_standard_derivatives =
11245 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
11246 desire_frag_depth =
11247 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
11248 desire_draw_buffers =
11249 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
11250 desire_shader_texture_lod =
11251 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
11254 if (desire_standard_derivatives != derivatives_explicitly_enabled_ ||
11255 desire_frag_depth != frag_depth_explicitly_enabled_ ||
11256 desire_draw_buffers != draw_buffers_explicitly_enabled_ ||
11257 desire_shader_texture_lod != shader_texture_lod_explicitly_enabled_) {
11258 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
11259 frag_depth_explicitly_enabled_ |= desire_frag_depth;
11260 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
11261 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
11262 InitializeShaderTranslator();
11265 UpdateCapabilities();
11267 return error::kNoError;
11270 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11271 uint32 immediate_data_size,
11272 const void* cmd_data) {
11273 const gles2::cmds::GetProgramInfoCHROMIUM& c =
11274 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
11275 GLuint program_id = static_cast<GLuint>(c.program);
11276 uint32 bucket_id = c.bucket_id;
11277 Bucket* bucket = CreateBucket(bucket_id);
11278 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
11279 Program* program = NULL;
11280 program = GetProgram(program_id);
11281 if (!program || !program->IsValid()) {
11282 return error::kNoError;
11284 program->GetProgramInfo(program_manager(), bucket);
11285 return error::kNoError;
11288 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11289 uint32 immediate_data_size, const void* cmd_data) {
11290 if (!unsafe_es3_apis_enabled())
11291 return error::kUnknownCommand;
11292 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
11293 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
11294 GLuint program_id = static_cast<GLuint>(c.program);
11295 uint32 bucket_id = c.bucket_id;
11296 Bucket* bucket = CreateBucket(bucket_id);
11297 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
11298 Program* program = NULL;
11299 program = GetProgram(program_id);
11300 if (!program || !program->IsValid()) {
11301 return error::kNoError;
11303 program->GetUniformBlocks(bucket);
11304 return error::kNoError;
11307 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11308 uint32 immediate_data_size, const void* cmd_data) {
11309 if (!unsafe_es3_apis_enabled())
11310 return error::kUnknownCommand;
11311 const gles2::cmds::GetUniformsES3CHROMIUM& c =
11312 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
11313 GLuint program_id = static_cast<GLuint>(c.program);
11314 uint32 bucket_id = c.bucket_id;
11315 Bucket* bucket = CreateBucket(bucket_id);
11316 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
11317 Program* program = NULL;
11318 program = GetProgram(program_id);
11319 if (!program || !program->IsValid()) {
11320 return error::kNoError;
11322 program->GetUniformsES3(bucket);
11323 return error::kNoError;
11326 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11327 uint32 immediate_data_size,
11328 const void* cmd_data) {
11329 if (!unsafe_es3_apis_enabled())
11330 return error::kUnknownCommand;
11331 const gles2::cmds::GetTransformFeedbackVarying& c =
11332 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
11333 GLuint program_id = c.program;
11334 GLuint index = c.index;
11335 uint32 name_bucket_id = c.name_bucket_id;
11336 typedef cmds::GetTransformFeedbackVarying::Result Result;
11337 Result* result = GetSharedMemoryAs<Result*>(
11338 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11339 if (!result) {
11340 return error::kOutOfBounds;
11342 // Check that the client initialized the result.
11343 if (result->success != 0) {
11344 return error::kInvalidArguments;
11346 Program* program = GetProgramInfoNotShader(
11347 program_id, "glGetTransformFeedbackVarying");
11348 if (!program) {
11349 return error::kNoError;
11351 GLuint service_id = program->service_id();
11352 GLint link_status = GL_FALSE;
11353 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11354 if (link_status != GL_TRUE) {
11355 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11356 "glGetTransformFeedbackVarying", "program not linked");
11357 return error::kNoError;
11359 GLint max_length = 0;
11360 glGetProgramiv(
11361 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
11362 max_length = std::max(1, max_length);
11363 std::vector<char> buffer(max_length);
11364 GLsizei length = 0;
11365 GLsizei size = 0;
11366 GLenum type = 0;
11367 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11368 glGetTransformFeedbackVarying(
11369 service_id, index, max_length, &length, &size, &type, &buffer[0]);
11370 GLenum error = glGetError();
11371 if (error != GL_NO_ERROR) {
11372 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
11373 return error::kNoError;
11375 result->success = 1; // true.
11376 result->size = static_cast<int32_t>(size);
11377 result->type = static_cast<uint32_t>(type);
11378 Bucket* bucket = CreateBucket(name_bucket_id);
11379 DCHECK(length >= 0 && length < max_length);
11380 buffer[length] = '\0'; // Just to be safe.
11381 bucket->SetFromString(&buffer[0]);
11382 return error::kNoError;
11385 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11386 uint32 immediate_data_size, const void* cmd_data) {
11387 if (!unsafe_es3_apis_enabled())
11388 return error::kUnknownCommand;
11389 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
11390 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
11391 cmd_data);
11392 GLuint program_id = static_cast<GLuint>(c.program);
11393 uint32 bucket_id = c.bucket_id;
11394 Bucket* bucket = CreateBucket(bucket_id);
11395 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
11396 Program* program = NULL;
11397 program = GetProgram(program_id);
11398 if (!program || !program->IsValid()) {
11399 return error::kNoError;
11401 program->GetTransformFeedbackVaryings(bucket);
11402 return error::kNoError;
11405 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
11406 return context_lost_reason_;
11409 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11410 GLenum reset_status) const {
11411 switch (reset_status) {
11412 case GL_NO_ERROR:
11413 // TODO(kbr): improve the precision of the error code in this case.
11414 // Consider delegating to context for error code if MakeCurrent fails.
11415 return error::kUnknown;
11416 case GL_GUILTY_CONTEXT_RESET_ARB:
11417 return error::kGuilty;
11418 case GL_INNOCENT_CONTEXT_RESET_ARB:
11419 return error::kInnocent;
11420 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11421 return error::kUnknown;
11424 NOTREACHED();
11425 return error::kUnknown;
11428 bool GLES2DecoderImpl::WasContextLost() const {
11429 return context_was_lost_;
11432 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11433 return WasContextLost() && reset_by_robustness_extension_;
11436 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
11437 // Only lose the context once.
11438 if (WasContextLost())
11439 return;
11441 // Don't make GL calls in here, the context might not be current.
11442 context_lost_reason_ = reason;
11443 current_decoder_error_ = error::kLostContext;
11444 context_was_lost_ = true;
11447 bool GLES2DecoderImpl::CheckResetStatus() {
11448 DCHECK(!WasContextLost());
11449 DCHECK(context_->IsCurrent(NULL));
11451 if (IsRobustnessSupported()) {
11452 // If the reason for the call was a GL error, we can try to determine the
11453 // reset status more accurately.
11454 GLenum driver_status = glGetGraphicsResetStatusARB();
11455 if (driver_status == GL_NO_ERROR)
11456 return false;
11458 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
11459 << " context lost via ARB/EXT_robustness. Reset status = "
11460 << GLES2Util::GetStringEnum(driver_status);
11462 // Don't pretend we know which client was responsible.
11463 if (workarounds().use_virtualized_gl_contexts)
11464 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
11466 switch (driver_status) {
11467 case GL_GUILTY_CONTEXT_RESET_ARB:
11468 MarkContextLost(error::kGuilty);
11469 break;
11470 case GL_INNOCENT_CONTEXT_RESET_ARB:
11471 MarkContextLost(error::kInnocent);
11472 break;
11473 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11474 MarkContextLost(error::kUnknown);
11475 break;
11476 default:
11477 NOTREACHED();
11478 return false;
11480 reset_by_robustness_extension_ = true;
11481 return true;
11483 return false;
11486 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11487 uint32 immediate_data_size,
11488 const void* cmd_data) {
11489 return error::kUnknownCommand;
11492 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11493 uint32 immediate_data_size,
11494 const void* cmd_data) {
11495 const gles2::cmds::WaitSyncPointCHROMIUM& c =
11496 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
11497 uint32 sync_point = c.sync_point;
11498 if (wait_sync_point_callback_.is_null())
11499 return error::kNoError;
11501 return wait_sync_point_callback_.Run(sync_point) ?
11502 error::kNoError : error::kDeferCommandUntilLater;
11505 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11506 uint32 immediate_data_size,
11507 const void* cmd_data) {
11508 if (surface_->DeferDraws())
11509 return error::kDeferCommandUntilLater;
11510 if (!surface_->SetBackbufferAllocation(false))
11511 return error::kLostContext;
11512 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
11513 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
11514 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
11515 return error::kNoError;
11518 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11519 GLsizei n, const GLuint* client_ids) {
11520 for (GLsizei ii = 0; ii < n; ++ii) {
11521 if (query_manager_->GetQuery(client_ids[ii])) {
11522 return false;
11525 query_manager_->GenQueries(n, client_ids);
11526 return true;
11529 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11530 GLsizei n, const GLuint* client_ids) {
11531 for (GLsizei ii = 0; ii < n; ++ii) {
11532 query_manager_->RemoveQuery(client_ids[ii]);
11536 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
11537 if (query_manager_.get() == NULL) {
11538 return false;
11540 if (!query_manager_->ProcessPendingQueries(did_finish)) {
11541 current_decoder_error_ = error::kOutOfBounds;
11543 return query_manager_->HavePendingQueries();
11546 // Note that if there are no pending readpixels right now,
11547 // this function will call the callback immediately.
11548 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
11549 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
11550 pending_readpixel_fences_.back()->callbacks.push_back(callback);
11551 } else {
11552 callback.Run();
11556 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish) {
11557 // Note: |did_finish| guarantees that the GPU has passed the fence but
11558 // we cannot assume that GLFence::HasCompleted() will return true yet as
11559 // that's not guaranteed by all GLFence implementations.
11560 while (!pending_readpixel_fences_.empty() &&
11561 (did_finish ||
11562 pending_readpixel_fences_.front()->fence->HasCompleted())) {
11563 std::vector<base::Closure> callbacks =
11564 pending_readpixel_fences_.front()->callbacks;
11565 pending_readpixel_fences_.pop();
11566 for (size_t i = 0; i < callbacks.size(); i++) {
11567 callbacks[i].Run();
11572 bool GLES2DecoderImpl::HasMoreIdleWork() {
11573 return !pending_readpixel_fences_.empty() ||
11574 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
11577 void GLES2DecoderImpl::PerformIdleWork() {
11578 ProcessPendingReadPixels(false);
11579 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
11580 return;
11581 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
11582 ProcessFinishedAsyncTransfers();
11585 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
11586 const void* cmd_data) {
11587 const gles2::cmds::BeginQueryEXT& c =
11588 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
11589 GLenum target = static_cast<GLenum>(c.target);
11590 GLuint client_id = static_cast<GLuint>(c.id);
11591 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11592 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11594 switch (target) {
11595 case GL_COMMANDS_ISSUED_CHROMIUM:
11596 case GL_LATENCY_QUERY_CHROMIUM:
11597 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
11598 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
11599 case GL_GET_ERROR_QUERY_CHROMIUM:
11600 break;
11601 case GL_COMMANDS_COMPLETED_CHROMIUM:
11602 if (!features().chromium_sync_query) {
11603 #if defined(OS_MACOSX)
11604 // TODO(dyen): Remove once we know what is failing.
11605 uint32_t boolean_flags = 0;
11606 if (gfx::g_driver_gl.ext.b_GL_ARB_sync)
11607 boolean_flags |= 1;
11608 if (gfx::g_driver_gl.ext.b_GL_APPLE_fence)
11609 boolean_flags |= 2;
11610 if (gfx::g_driver_gl.ext.b_GL_NV_fence)
11611 boolean_flags |= 4;
11613 CHECK(boolean_flags != 0) << "Nothing supported";
11614 CHECK(boolean_flags != 1) << "ARB";
11615 CHECK(boolean_flags != 2) << "APPLE";
11616 CHECK(boolean_flags != 3) << "ARB APPLE";
11617 CHECK(boolean_flags != 4) << "NV";
11618 CHECK(boolean_flags != 5) << "NV ARB";
11619 CHECK(boolean_flags != 6) << "NV APPLE";
11620 CHECK(boolean_flags != 7) << "NV ARB APPLE";
11621 CHECK(false) << "Unknown error.";
11622 #endif
11623 LOCAL_SET_GL_ERROR(
11624 GL_INVALID_OPERATION, "glBeginQueryEXT",
11625 "not enabled for commands completed queries");
11626 return error::kNoError;
11628 break;
11629 case GL_SAMPLES_PASSED:
11630 case GL_ANY_SAMPLES_PASSED:
11631 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
11632 if (!features().occlusion_query_boolean) {
11633 LOCAL_SET_GL_ERROR(
11634 GL_INVALID_OPERATION, "glBeginQueryEXT",
11635 "not enabled for occlusion queries");
11636 return error::kNoError;
11638 break;
11639 case GL_TIME_ELAPSED:
11640 if (!query_manager_->GPUTimingAvailable()) {
11641 LOCAL_SET_GL_ERROR(
11642 GL_INVALID_OPERATION, "glBeginQueryEXT",
11643 "not enabled for timing queries");
11644 return error::kNoError;
11646 break;
11647 default:
11648 LOCAL_SET_GL_ERROR(
11649 GL_INVALID_ENUM, "glBeginQueryEXT",
11650 "unknown query target");
11651 return error::kNoError;
11654 if (query_manager_->GetActiveQuery(target)) {
11655 #if defined(OS_MACOSX)
11656 // TODO(dyen): Remove once we know what is failing.
11657 CHECK(target != GL_COMMANDS_COMPLETED_CHROMIUM)
11658 << "Query already in progress";
11659 #endif
11660 LOCAL_SET_GL_ERROR(
11661 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
11662 return error::kNoError;
11665 if (client_id == 0) {
11666 #if defined(OS_MACOSX)
11667 // TODO(dyen): Remove once we know what is failing.
11668 CHECK(target != GL_COMMANDS_COMPLETED_CHROMIUM) << "Id is 0";
11669 #endif
11670 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
11671 return error::kNoError;
11674 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11675 if (!query) {
11676 if (!query_manager_->IsValidQuery(client_id)) {
11677 #if defined(OS_MACOSX)
11678 // TODO(dyen): Remove once we know what is failing.
11679 CHECK(target != GL_COMMANDS_COMPLETED_CHROMIUM) << "Invalid ID";
11680 #endif
11681 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11682 "glBeginQueryEXT",
11683 "id not made by glGenQueriesEXT");
11684 return error::kNoError;
11686 query = query_manager_->CreateQuery(
11687 target, client_id, sync_shm_id, sync_shm_offset);
11690 if (query->target() != target) {
11691 #if defined(OS_MACOSX)
11692 // TODO(dyen): Remove once we know what is failing.
11693 CHECK(target != GL_COMMANDS_COMPLETED_CHROMIUM) << "Non-Matching Target";
11694 #endif
11695 LOCAL_SET_GL_ERROR(
11696 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
11697 return error::kNoError;
11698 } else if (query->shm_id() != sync_shm_id ||
11699 query->shm_offset() != sync_shm_offset) {
11700 DLOG(ERROR) << "Shared memory used by query not the same as before";
11701 return error::kInvalidArguments;
11704 if (!query_manager_->BeginQuery(query)) {
11705 #if defined(OS_MACOSX)
11706 // TODO(dyen): Remove once we know what is failing.
11707 CHECK(target != GL_COMMANDS_COMPLETED_CHROMIUM) << "Out of bounds";
11708 #endif
11709 return error::kOutOfBounds;
11712 return error::kNoError;
11715 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
11716 const void* cmd_data) {
11717 const gles2::cmds::EndQueryEXT& c =
11718 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
11719 GLenum target = static_cast<GLenum>(c.target);
11720 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11722 QueryManager::Query* query = query_manager_->GetActiveQuery(target);
11723 if (!query) {
11724 #if defined(OS_MACOSX)
11725 // TODO(dyen): Remove once we know what is failing.
11726 CHECK(target != GL_COMMANDS_COMPLETED_CHROMIUM) << "Target not active";
11727 #endif
11728 LOCAL_SET_GL_ERROR(
11729 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
11730 return error::kNoError;
11733 if (!query_manager_->EndQuery(query, submit_count)) {
11734 #if defined(OS_MACOSX)
11735 // TODO(dyen): Remove once we know what is failing.
11736 CHECK(target != GL_COMMANDS_COMPLETED_CHROMIUM) << "Out of bounds";
11737 #endif
11738 return error::kOutOfBounds;
11741 query_manager_->ProcessPendingTransferQueries();
11743 return error::kNoError;
11746 error::Error GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size,
11747 const void* cmd_data) {
11748 const gles2::cmds::QueryCounterEXT& c =
11749 *static_cast<const gles2::cmds::QueryCounterEXT*>(cmd_data);
11750 GLuint client_id = static_cast<GLuint>(c.id);
11751 GLenum target = static_cast<GLenum>(c.target);
11752 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11753 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11754 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11756 switch (target) {
11757 case GL_TIMESTAMP:
11758 if (!query_manager_->GPUTimingAvailable()) {
11759 LOCAL_SET_GL_ERROR(
11760 GL_INVALID_OPERATION, "glQueryCounterEXT",
11761 "not enabled for timing queries");
11762 return error::kNoError;
11764 break;
11765 default:
11766 LOCAL_SET_GL_ERROR(
11767 GL_INVALID_ENUM, "glQueryCounterEXT",
11768 "unknown query target");
11769 return error::kNoError;
11772 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11773 if (!query) {
11774 if (!query_manager_->IsValidQuery(client_id)) {
11775 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11776 "glQueryCounterEXT",
11777 "id not made by glGenQueriesEXT");
11778 return error::kNoError;
11780 query = query_manager_->CreateQuery(
11781 target, client_id, sync_shm_id, sync_shm_offset);
11783 if (!query_manager_->QueryCounter(query, submit_count)) {
11784 return error::kOutOfBounds;
11787 return error::kNoError;
11790 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11791 GLsizei n, const GLuint* client_ids) {
11792 for (GLsizei ii = 0; ii < n; ++ii) {
11793 if (GetVertexAttribManager(client_ids[ii])) {
11794 return false;
11798 if (!features().native_vertex_array_object) {
11799 // Emulated VAO
11800 for (GLsizei ii = 0; ii < n; ++ii) {
11801 CreateVertexAttribManager(client_ids[ii], 0, true);
11803 } else {
11804 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11806 glGenVertexArraysOES(n, service_ids.get());
11807 for (GLsizei ii = 0; ii < n; ++ii) {
11808 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
11812 return true;
11815 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11816 GLsizei n, const GLuint* client_ids) {
11817 for (GLsizei ii = 0; ii < n; ++ii) {
11818 VertexAttribManager* vao =
11819 GetVertexAttribManager(client_ids[ii]);
11820 if (vao && !vao->IsDeleted()) {
11821 if (state_.vertex_attrib_manager.get() == vao) {
11822 DoBindVertexArrayOES(0);
11824 RemoveVertexAttribManager(client_ids[ii]);
11829 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
11830 VertexAttribManager* vao = NULL;
11831 if (client_id != 0) {
11832 vao = GetVertexAttribManager(client_id);
11833 if (!vao) {
11834 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11835 // only allows names that have been previously generated. As such, we do
11836 // not generate new names here.
11837 LOCAL_SET_GL_ERROR(
11838 GL_INVALID_OPERATION,
11839 "glBindVertexArrayOES", "bad vertex array id.");
11840 current_decoder_error_ = error::kNoError;
11841 return;
11843 } else {
11844 vao = state_.default_vertex_attrib_manager.get();
11847 // Only set the VAO state if it's changed
11848 if (state_.vertex_attrib_manager.get() != vao) {
11849 state_.vertex_attrib_manager = vao;
11850 if (!features().native_vertex_array_object) {
11851 EmulateVertexArrayState();
11852 } else {
11853 GLuint service_id = vao->service_id();
11854 glBindVertexArrayOES(service_id);
11859 // Used when OES_vertex_array_object isn't natively supported
11860 void GLES2DecoderImpl::EmulateVertexArrayState() {
11861 // Setup the Vertex attribute state
11862 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
11863 RestoreStateForAttrib(vv, true);
11866 // Setup the element buffer
11867 Buffer* element_array_buffer =
11868 state_.vertex_attrib_manager->element_array_buffer();
11869 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
11870 element_array_buffer ? element_array_buffer->service_id() : 0);
11873 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
11874 const VertexAttribManager* vao =
11875 GetVertexAttribManager(client_id);
11876 return vao && vao->IsValid() && !vao->IsDeleted();
11879 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id) {
11880 GLuint service_id = 0;
11881 return path_manager()->GetPath(client_id, &service_id) &&
11882 glIsPathNV(service_id) == GL_TRUE;
11885 #if defined(OS_MACOSX)
11886 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
11887 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
11888 texture_id);
11889 if (it != texture_to_io_surface_map_.end()) {
11890 // Found a previous IOSurface bound to this texture; release it.
11891 IOSurfaceRef surface = it->second;
11892 CFRelease(surface);
11893 texture_to_io_surface_map_.erase(it);
11896 #endif
11898 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11899 GLenum target, GLsizei width, GLsizei height,
11900 GLuint io_surface_id, GLuint plane) {
11901 #if defined(OS_MACOSX)
11902 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
11903 LOCAL_SET_GL_ERROR(
11904 GL_INVALID_OPERATION,
11905 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11906 return;
11909 if (target != GL_TEXTURE_RECTANGLE_ARB) {
11910 // This might be supported in the future, and if we could require
11911 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11912 // could delete a lot of code. For now, perform strict validation so we
11913 // know what's going on.
11914 LOCAL_SET_GL_ERROR(
11915 GL_INVALID_OPERATION,
11916 "glTexImageIOSurface2DCHROMIUM",
11917 "requires TEXTURE_RECTANGLE_ARB target");
11918 return;
11921 // Default target might be conceptually valid, but disallow it to avoid
11922 // accidents.
11923 TextureRef* texture_ref =
11924 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11925 if (!texture_ref) {
11926 LOCAL_SET_GL_ERROR(
11927 GL_INVALID_OPERATION,
11928 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11929 return;
11932 // Look up the new IOSurface. Note that because of asynchrony
11933 // between processes this might fail; during live resizing the
11934 // plugin process might allocate and release an IOSurface before
11935 // this process gets a chance to look it up. Hold on to any old
11936 // IOSurface in this case.
11937 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
11938 if (!surface) {
11939 LOCAL_SET_GL_ERROR(
11940 GL_INVALID_OPERATION,
11941 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11942 return;
11945 // Release any IOSurface previously bound to this texture.
11946 ReleaseIOSurfaceForTexture(texture_ref->service_id());
11948 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11949 texture_to_io_surface_map_.insert(
11950 std::make_pair(texture_ref->service_id(), surface));
11952 CGLContextObj context =
11953 static_cast<CGLContextObj>(context_->GetHandle());
11955 CGLError err = CGLTexImageIOSurface2D(
11956 context,
11957 target,
11958 GL_RGBA,
11959 width,
11960 height,
11961 GL_BGRA,
11962 GL_UNSIGNED_INT_8_8_8_8_REV,
11963 surface,
11964 plane);
11966 if (err != kCGLNoError) {
11967 LOCAL_SET_GL_ERROR(
11968 GL_INVALID_OPERATION,
11969 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11970 return;
11973 texture_manager()->SetLevelInfo(
11974 texture_ref, target, 0, GL_RGBA, width, height, 1, 0, GL_BGRA,
11975 GL_UNSIGNED_INT_8_8_8_8_REV, gfx::Rect(width, height));
11977 #else
11978 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11979 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11980 #endif
11983 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
11984 switch (internalformat) {
11985 case GL_R8:
11986 case GL_R8_SNORM:
11987 case GL_R16F:
11988 case GL_R32F:
11989 return GL_RED;
11990 case GL_R8UI:
11991 case GL_R8I:
11992 case GL_R16UI:
11993 case GL_R16I:
11994 case GL_R32UI:
11995 case GL_R32I:
11996 return GL_RED_INTEGER;
11997 case GL_RG8:
11998 case GL_RG8_SNORM:
11999 case GL_RG16F:
12000 case GL_RG32F:
12001 return GL_RG;
12002 case GL_RG8UI:
12003 case GL_RG8I:
12004 case GL_RG16UI:
12005 case GL_RG16I:
12006 case GL_RG32UI:
12007 case GL_RG32I:
12008 return GL_RG_INTEGER;
12009 case GL_RGB8:
12010 case GL_R11F_G11F_B10F:
12011 case GL_RGB565:
12012 case GL_RGB8_SNORM:
12013 case GL_RGB9_E5:
12014 case GL_RGB16F:
12015 case GL_RGB32F:
12016 return GL_RGB;
12017 case GL_RGB8UI:
12018 case GL_RGB8I:
12019 case GL_RGB16UI:
12020 case GL_RGB16I:
12021 case GL_RGB32UI:
12022 case GL_RGB32I:
12023 return GL_RGB_INTEGER;
12024 case GL_RGBA8:
12025 case GL_SRGB8_ALPHA8:
12026 case GL_RGBA8_SNORM:
12027 case GL_RGBA4:
12028 case GL_RGB5_A1:
12029 case GL_RGB10_A2:
12030 case GL_RGBA16F:
12031 case GL_RGBA32F:
12032 return GL_RGBA;
12033 case GL_RGBA8UI:
12034 case GL_RGBA8I:
12035 case GL_RGB10_A2UI:
12036 case GL_RGBA16UI:
12037 case GL_RGBA16I:
12038 case GL_RGBA32UI:
12039 case GL_RGBA32I:
12040 return GL_RGBA_INTEGER;
12041 case GL_DEPTH_COMPONENT16:
12042 case GL_DEPTH_COMPONENT24:
12043 case GL_DEPTH_COMPONENT32F:
12044 return GL_DEPTH_COMPONENT;
12045 case GL_DEPTH24_STENCIL8:
12046 case GL_DEPTH32F_STENCIL8:
12047 return GL_DEPTH_STENCIL;
12048 case GL_LUMINANCE8_ALPHA8_EXT:
12049 return GL_LUMINANCE_ALPHA;
12050 case GL_LUMINANCE8_EXT:
12051 return GL_LUMINANCE;
12052 case GL_ALPHA8_EXT:
12053 return GL_ALPHA;
12054 case GL_ALPHA32F_EXT:
12055 return GL_ALPHA;
12056 case GL_LUMINANCE32F_EXT:
12057 return GL_LUMINANCE;
12058 case GL_LUMINANCE_ALPHA32F_EXT:
12059 return GL_LUMINANCE_ALPHA;
12060 case GL_ALPHA16F_EXT:
12061 return GL_ALPHA;
12062 case GL_LUMINANCE16F_EXT:
12063 return GL_LUMINANCE;
12064 case GL_LUMINANCE_ALPHA16F_EXT:
12065 return GL_LUMINANCE_ALPHA;
12066 case GL_BGRA8_EXT:
12067 return GL_BGRA_EXT;
12068 default:
12069 return GL_NONE;
12073 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12074 const char* function_name,
12075 GLenum target,
12076 TextureRef* source_texture_ref,
12077 TextureRef* dest_texture_ref,
12078 GLenum dest_internal_format) {
12079 if (!source_texture_ref || !dest_texture_ref) {
12080 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12081 return false;
12084 if (GL_TEXTURE_2D != target) {
12085 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12086 "invalid texture target");
12087 return false;
12090 Texture* source_texture = source_texture_ref->texture();
12091 Texture* dest_texture = dest_texture_ref->texture();
12092 if (source_texture == dest_texture) {
12093 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12094 "source and destination textures are the same");
12095 return false;
12098 if (dest_texture->target() != GL_TEXTURE_2D ||
12099 (source_texture->target() != GL_TEXTURE_2D &&
12100 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12101 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12102 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12103 "invalid texture target binding");
12104 return false;
12107 GLenum source_type = 0;
12108 GLenum source_internal_format = 0;
12109 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12110 &source_internal_format);
12112 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12113 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12114 // renderable on some platforms.
12115 bool valid_dest_format = dest_internal_format == GL_RGB ||
12116 dest_internal_format == GL_RGBA ||
12117 dest_internal_format == GL_BGRA_EXT;
12118 bool valid_source_format =
12119 source_internal_format == GL_R8 || source_internal_format == GL_ALPHA ||
12120 source_internal_format == GL_RGB || source_internal_format == GL_RGBA ||
12121 source_internal_format == GL_LUMINANCE ||
12122 source_internal_format == GL_LUMINANCE_ALPHA ||
12123 source_internal_format == GL_BGRA_EXT;
12124 if (!valid_source_format || !valid_dest_format) {
12125 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12126 "invalid internal format");
12127 return false;
12129 return true;
12132 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12133 const char* function_name,
12134 GLenum target,
12135 TextureRef* source_texture_ref,
12136 TextureRef* dest_texture_ref) {
12137 if (!source_texture_ref || !dest_texture_ref) {
12138 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12139 return false;
12142 if (GL_TEXTURE_2D != target) {
12143 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12144 "invalid texture target");
12145 return false;
12148 Texture* source_texture = source_texture_ref->texture();
12149 Texture* dest_texture = dest_texture_ref->texture();
12150 if (source_texture == dest_texture) {
12151 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12152 "source and destination textures are the same");
12153 return false;
12156 if (dest_texture->target() != GL_TEXTURE_2D ||
12157 (source_texture->target() != GL_TEXTURE_2D &&
12158 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12159 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12160 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12161 "invalid texture target binding");
12162 return false;
12165 GLenum source_type = 0;
12166 GLenum source_internal_format = 0;
12167 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12168 &source_internal_format);
12170 bool valid_format =
12171 source_internal_format == GL_ATC_RGB_AMD ||
12172 source_internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD ||
12173 source_internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
12174 source_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ||
12175 source_internal_format == GL_ETC1_RGB8_OES;
12177 if (!valid_format) {
12178 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12179 "invalid internal format");
12180 return false;
12183 return true;
12186 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12187 GLenum target,
12188 GLuint source_id,
12189 GLuint dest_id,
12190 GLenum internal_format,
12191 GLenum dest_type,
12192 GLboolean unpack_flip_y,
12193 GLboolean unpack_premultiply_alpha,
12194 GLboolean unpack_unmultiply_alpha) {
12195 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12197 TextureRef* source_texture_ref = GetTexture(source_id);
12198 TextureRef* dest_texture_ref = GetTexture(dest_id);
12199 Texture* source_texture = source_texture_ref->texture();
12200 Texture* dest_texture = dest_texture_ref->texture();
12201 int source_width = 0;
12202 int source_height = 0;
12203 gfx::GLImage* image =
12204 source_texture->GetLevelImage(source_texture->target(), 0);
12205 if (image) {
12206 gfx::Size size = image->GetSize();
12207 source_width = size.width();
12208 source_height = size.height();
12209 if (source_width <= 0 || source_height <= 0) {
12210 LOCAL_SET_GL_ERROR(
12211 GL_INVALID_VALUE,
12212 "glCopyTextureChromium", "invalid image size");
12213 return;
12215 } else {
12216 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12217 &source_width, &source_height, nullptr)) {
12218 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12219 "glCopyTextureChromium",
12220 "source texture has no level 0");
12221 return;
12224 // Check that this type of texture is allowed.
12225 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12226 source_width, source_height, 1)) {
12227 LOCAL_SET_GL_ERROR(
12228 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
12229 return;
12233 GLenum source_type = 0;
12234 GLenum source_internal_format = 0;
12235 source_texture->GetLevelType(
12236 source_texture->target(), 0, &source_type, &source_internal_format);
12238 if (dest_texture->IsImmutable()) {
12239 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
12240 "texture is immutable");
12241 return;
12244 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
12245 source_texture_ref, dest_texture_ref,
12246 internal_format)) {
12247 return;
12250 // Clear the source texture if necessary.
12251 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12252 source_texture->target(), 0)) {
12253 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
12254 "dimensions too big");
12255 return;
12258 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12259 // needed because it takes 10s of milliseconds to initialize.
12260 if (!copy_texture_CHROMIUM_.get()) {
12261 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12262 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12263 copy_texture_CHROMIUM_->Initialize(this);
12264 RestoreCurrentFramebufferBindings();
12265 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12266 return;
12269 GLenum dest_type_previous = dest_type;
12270 GLenum dest_internal_format = internal_format;
12271 int dest_width = 0;
12272 int dest_height = 0;
12273 bool dest_level_defined = dest_texture->GetLevelSize(
12274 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12276 if (dest_level_defined) {
12277 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
12278 &dest_internal_format);
12281 // Resize the destination texture to the dimensions of the source texture.
12282 if (!dest_level_defined || dest_width != source_width ||
12283 dest_height != source_height ||
12284 dest_internal_format != internal_format ||
12285 dest_type_previous != dest_type) {
12286 // Ensure that the glTexImage2D succeeds.
12287 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12288 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12289 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
12290 0, internal_format, dest_type, NULL);
12291 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12292 if (error != GL_NO_ERROR) {
12293 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12294 return;
12297 texture_manager()->SetLevelInfo(
12298 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
12299 source_height, 1, 0, internal_format, dest_type,
12300 gfx::Rect(source_width, source_height));
12301 } else {
12302 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12303 true);
12306 ScopedModifyPixels modify(dest_texture_ref);
12308 // Try using GLImage::CopyTexSubImage when possible.
12309 bool unpack_premultiply_alpha_change =
12310 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12311 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12312 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12313 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12314 gfx::Rect(0, 0, source_width, source_height))) {
12315 return;
12319 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12321 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12322 // before presenting.
12323 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12324 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12325 // instead of using kIdentityMatrix crbug.com/226218.
12326 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12327 this, source_texture->target(), source_texture->service_id(),
12328 dest_texture->service_id(), source_width, source_height,
12329 unpack_flip_y == GL_TRUE,
12330 unpack_premultiply_alpha == GL_TRUE,
12331 unpack_unmultiply_alpha == GL_TRUE,
12332 kIdentityMatrix);
12333 } else {
12334 copy_texture_CHROMIUM_->DoCopyTexture(
12335 this, source_texture->target(), source_texture->service_id(),
12336 source_internal_format, dest_texture->service_id(), internal_format,
12337 source_width, source_height,
12338 unpack_flip_y == GL_TRUE,
12339 unpack_premultiply_alpha == GL_TRUE,
12340 unpack_unmultiply_alpha == GL_TRUE);
12343 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12346 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12347 GLenum target,
12348 GLuint source_id,
12349 GLuint dest_id,
12350 GLint xoffset,
12351 GLint yoffset,
12352 GLint x,
12353 GLint y,
12354 GLsizei width,
12355 GLsizei height,
12356 GLboolean unpack_flip_y,
12357 GLboolean unpack_premultiply_alpha,
12358 GLboolean unpack_unmultiply_alpha) {
12359 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12361 TextureRef* source_texture_ref = GetTexture(source_id);
12362 TextureRef* dest_texture_ref = GetTexture(dest_id);
12363 Texture* source_texture = source_texture_ref->texture();
12364 Texture* dest_texture = dest_texture_ref->texture();
12365 int source_width = 0;
12366 int source_height = 0;
12367 gfx::GLImage* image =
12368 source_texture->GetLevelImage(source_texture->target(), 0);
12369 if (image) {
12370 gfx::Size size = image->GetSize();
12371 source_width = size.width();
12372 source_height = size.height();
12373 if (source_width <= 0 || source_height <= 0) {
12374 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12375 "invalid image size");
12376 return;
12378 } else {
12379 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12380 &source_width, &source_height, nullptr)) {
12381 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12382 "source texture has no level 0");
12383 return;
12386 // Check that this type of texture is allowed.
12387 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12388 source_width, source_height, 1)) {
12389 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12390 "source texture bad dimensions");
12391 return;
12395 GLenum source_type = 0;
12396 GLenum source_internal_format = 0;
12397 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12398 &source_internal_format);
12399 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12400 width, height, 1, source_type)) {
12401 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12402 "source texture bad dimensions.");
12403 return;
12406 GLenum dest_type = 0;
12407 GLenum dest_internal_format = 0;
12408 bool dest_level_defined = dest_texture->GetLevelType(
12409 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12410 if (!dest_level_defined) {
12411 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
12412 "destination texture is not defined");
12413 return;
12415 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12416 yoffset, 0, width, height, 1, dest_type)) {
12417 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12418 "destination texture bad dimensions.");
12419 return;
12422 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
12423 source_texture_ref, dest_texture_ref,
12424 dest_internal_format)) {
12425 return;
12428 // Clear the source texture if necessary.
12429 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12430 source_texture->target(), 0)) {
12431 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12432 "source texture dimensions too big");
12433 return;
12436 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12437 // needed because it takes 10s of milliseconds to initialize.
12438 if (!copy_texture_CHROMIUM_.get()) {
12439 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12440 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12441 copy_texture_CHROMIUM_->Initialize(this);
12442 RestoreCurrentFramebufferBindings();
12443 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
12444 return;
12447 int dest_width = 0;
12448 int dest_height = 0;
12449 bool ok = dest_texture->GetLevelSize(
12450 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12451 DCHECK(ok);
12452 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12453 height != dest_height) {
12454 gfx::Rect cleared_rect;
12455 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
12456 gfx::Rect(xoffset, yoffset, width, height),
12457 &cleared_rect)) {
12458 DCHECK_GE(cleared_rect.size().GetArea(),
12459 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
12460 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
12461 cleared_rect);
12462 } else {
12463 // Otherwise clear part of texture level that is not already cleared.
12464 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12465 0)) {
12466 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12467 "destination texture dimensions too big");
12468 return;
12471 } else {
12472 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12473 true);
12476 ScopedModifyPixels modify(dest_texture_ref);
12478 // Try using GLImage::CopyTexSubImage when possible.
12479 bool unpack_premultiply_alpha_change =
12480 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12481 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12482 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12483 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12484 gfx::Rect(x, y, width, height))) {
12485 return;
12489 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12491 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12492 // crbug.com/226218.
12493 copy_texture_CHROMIUM_->DoCopySubTexture(
12494 this, source_texture->target(), source_texture->service_id(),
12495 source_internal_format, dest_texture->service_id(), dest_internal_format,
12496 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
12497 source_width, source_height,
12498 unpack_flip_y == GL_TRUE,
12499 unpack_premultiply_alpha == GL_TRUE,
12500 unpack_unmultiply_alpha == GL_TRUE);
12502 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12505 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target,
12506 GLuint source_id,
12507 GLuint dest_id) {
12508 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12510 TextureRef* source_texture_ref = GetTexture(source_id);
12511 TextureRef* dest_texture_ref = GetTexture(dest_id);
12512 Texture* source_texture = source_texture_ref->texture();
12513 Texture* dest_texture = dest_texture_ref->texture();
12514 int source_width = 0;
12515 int source_height = 0;
12516 gfx::GLImage* image =
12517 source_texture->GetLevelImage(source_texture->target(), 0);
12518 if (image) {
12519 gfx::Size size = image->GetSize();
12520 source_width = size.width();
12521 source_height = size.height();
12522 if (source_width <= 0 || source_height <= 0) {
12523 LOCAL_SET_GL_ERROR(
12524 GL_INVALID_VALUE,
12525 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12526 return;
12528 } else {
12529 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12530 &source_width, &source_height, nullptr)) {
12531 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12532 "glCompressedCopyTextureCHROMIUM",
12533 "source texture has no level 0");
12534 return;
12537 // Check that this type of texture is allowed.
12538 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12539 source_width, source_height, 1)) {
12540 LOCAL_SET_GL_ERROR(
12541 GL_INVALID_VALUE, "glCompressedCopyTextureCHROMIUM",
12542 "Bad dimensions");
12543 return;
12547 GLenum source_type = 0;
12548 GLenum source_internal_format = 0;
12549 source_texture->GetLevelType(
12550 source_texture->target(), 0, &source_type, &source_internal_format);
12552 if (dest_texture->IsImmutable()) {
12553 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12554 "glCompressedCopyTextureCHROMIUM",
12555 "texture is immutable");
12556 return;
12559 if (!ValidateCompressedCopyTextureCHROMIUM(
12560 "glCompressedCopyTextureCHROMIUM",
12561 target,
12562 source_texture_ref, dest_texture_ref)) {
12563 return;
12566 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12567 // needed because it takes 10s of milliseconds to initialize.
12568 if (!copy_texture_CHROMIUM_.get()) {
12569 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12570 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12571 copy_texture_CHROMIUM_->Initialize(this);
12572 RestoreCurrentFramebufferBindings();
12573 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12574 return;
12577 // Clear the source texture if necessary.
12578 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12579 source_texture->target(), 0)) {
12580 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopyTextureCHROMIUM",
12581 "dimensions too big");
12582 return;
12585 ScopedTextureBinder binder(
12586 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
12588 ScopedModifyPixels modify(dest_texture_ref);
12590 // Try using GLImage::CopyTexImage when possible.
12591 if (image) {
12592 GLenum dest_type = 0;
12593 GLenum dest_internal_format = 0;
12594 int dest_width = 0;
12595 int dest_height = 0;
12596 bool dest_level_defined = dest_texture->GetLevelSize(
12597 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12599 if (dest_level_defined) {
12600 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
12601 &dest_internal_format);
12604 // Resize the destination texture to the dimensions of the source texture.
12605 if (!dest_level_defined || dest_width != source_width ||
12606 dest_height != source_height ||
12607 dest_internal_format != source_internal_format) {
12608 GLsizei source_size = 0;
12610 bool did_get_size = GetCompressedTexSizeInBytes(
12611 "glCompressedCopyTextureCHROMIUM", source_width, source_height,
12612 1, source_internal_format, &source_size);
12613 DCHECK(did_get_size);
12615 // Ensure that the glCompressedTexImage2D succeeds.
12616 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12617 glCompressedTexImage2D(GL_TEXTURE_2D, 0, source_internal_format,
12618 source_width, source_height, 0, source_size,
12619 NULL);
12620 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12621 if (error != GL_NO_ERROR) {
12622 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12623 return;
12626 texture_manager()->SetLevelInfo(
12627 dest_texture_ref, GL_TEXTURE_2D, 0, source_internal_format,
12628 source_width, source_height, 1, 0, source_internal_format,
12629 source_type, gfx::Rect(source_width, source_height));
12630 } else {
12631 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12632 true);
12635 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12636 gfx::Rect(0, 0, source_width, source_height))) {
12637 return;
12641 TRACE_EVENT0(
12642 "gpu",
12643 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12645 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12647 // As a fallback, copy into a non-compressed GL_RGBA texture.
12648 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12649 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height,
12650 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
12651 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12652 if (error != GL_NO_ERROR) {
12653 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12654 return;
12657 texture_manager()->SetLevelInfo(
12658 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, source_width,
12659 source_height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12660 gfx::Rect(source_width, source_height));
12662 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12663 // before presenting.
12664 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12665 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12666 // instead of using kIdentityMatrix crbug.com/226218.
12667 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12668 this, source_texture->target(), source_texture->service_id(),
12669 dest_texture->service_id(), source_width, source_height,
12670 false, false, false, kIdentityMatrix);
12671 } else {
12672 copy_texture_CHROMIUM_->DoCopyTexture(
12673 this, source_texture->target(), source_texture->service_id(),
12674 source_internal_format, dest_texture->service_id(), GL_RGBA,
12675 source_width, source_height, false, false, false);
12678 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12681 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
12682 switch (internalformat) {
12683 case GL_R8:
12684 return GL_UNSIGNED_BYTE;
12685 case GL_R8_SNORM:
12686 return GL_BYTE;
12687 case GL_R16F:
12688 return GL_HALF_FLOAT;
12689 case GL_R32F:
12690 return GL_FLOAT;
12691 case GL_R8UI:
12692 return GL_UNSIGNED_BYTE;
12693 case GL_R8I:
12694 return GL_BYTE;
12695 case GL_R16UI:
12696 return GL_UNSIGNED_SHORT;
12697 case GL_R16I:
12698 return GL_SHORT;
12699 case GL_R32UI:
12700 return GL_UNSIGNED_INT;
12701 case GL_R32I:
12702 return GL_INT;
12703 case GL_RG8:
12704 return GL_UNSIGNED_BYTE;
12705 case GL_RG8_SNORM:
12706 return GL_BYTE;
12707 case GL_RG16F:
12708 return GL_HALF_FLOAT;
12709 case GL_RG32F:
12710 return GL_FLOAT;
12711 case GL_RG8UI:
12712 return GL_UNSIGNED_BYTE;
12713 case GL_RG8I:
12714 return GL_BYTE;
12715 case GL_RG16UI:
12716 return GL_UNSIGNED_SHORT;
12717 case GL_RG16I:
12718 return GL_SHORT;
12719 case GL_RG32UI:
12720 return GL_UNSIGNED_INT;
12721 case GL_RG32I:
12722 return GL_INT;
12723 case GL_RGB8:
12724 case GL_SRGB8:
12725 return GL_UNSIGNED_BYTE;
12726 case GL_R11F_G11F_B10F:
12727 return GL_UNSIGNED_INT_10F_11F_11F_REV;
12728 case GL_RGB565:
12729 return GL_UNSIGNED_SHORT_5_6_5;
12730 case GL_RGB8_SNORM:
12731 return GL_BYTE;
12732 case GL_RGB9_E5:
12733 return GL_UNSIGNED_INT_5_9_9_9_REV;
12734 case GL_RGB16F:
12735 return GL_HALF_FLOAT;
12736 case GL_RGB32F:
12737 return GL_FLOAT;
12738 case GL_RGB8UI:
12739 return GL_UNSIGNED_BYTE;
12740 case GL_RGB8I:
12741 return GL_BYTE;
12742 case GL_RGB16UI:
12743 return GL_UNSIGNED_SHORT;
12744 case GL_RGB16I:
12745 return GL_SHORT;
12746 case GL_RGB32UI:
12747 return GL_UNSIGNED_INT;
12748 case GL_RGB32I:
12749 return GL_INT;
12750 case GL_RGBA8:
12751 return GL_UNSIGNED_BYTE;
12752 case GL_SRGB8_ALPHA8:
12753 return GL_UNSIGNED_BYTE;
12754 case GL_RGBA8_SNORM:
12755 return GL_BYTE;
12756 case GL_RGBA4:
12757 return GL_UNSIGNED_SHORT_4_4_4_4;
12758 case GL_RGB10_A2:
12759 return GL_UNSIGNED_INT_2_10_10_10_REV;
12760 case GL_RGB5_A1:
12761 return GL_UNSIGNED_SHORT_5_5_5_1;
12762 case GL_RGBA16F:
12763 return GL_HALF_FLOAT;
12764 case GL_RGBA32F:
12765 return GL_FLOAT;
12766 case GL_RGBA8UI:
12767 return GL_UNSIGNED_BYTE;
12768 case GL_RGBA8I:
12769 return GL_BYTE;
12770 case GL_RGB10_A2UI:
12771 return GL_UNSIGNED_INT_2_10_10_10_REV;
12772 case GL_RGBA16UI:
12773 return GL_UNSIGNED_SHORT;
12774 case GL_RGBA16I:
12775 return GL_SHORT;
12776 case GL_RGBA32I:
12777 return GL_INT;
12778 case GL_RGBA32UI:
12779 return GL_UNSIGNED_INT;
12780 case GL_DEPTH_COMPONENT16:
12781 return GL_UNSIGNED_SHORT;
12782 case GL_DEPTH_COMPONENT24:
12783 return GL_UNSIGNED_INT;
12784 case GL_DEPTH_COMPONENT32F:
12785 return GL_FLOAT;
12786 case GL_DEPTH24_STENCIL8:
12787 return GL_UNSIGNED_INT_24_8;
12788 case GL_DEPTH32F_STENCIL8:
12789 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
12790 case GL_LUMINANCE8_ALPHA8_EXT:
12791 return GL_UNSIGNED_BYTE;
12792 case GL_LUMINANCE8_EXT:
12793 return GL_UNSIGNED_BYTE;
12794 case GL_ALPHA8_EXT:
12795 return GL_UNSIGNED_BYTE;
12796 case GL_ALPHA32F_EXT:
12797 return GL_FLOAT;
12798 case GL_LUMINANCE32F_EXT:
12799 return GL_FLOAT;
12800 case GL_LUMINANCE_ALPHA32F_EXT:
12801 return GL_FLOAT;
12802 case GL_ALPHA16F_EXT:
12803 return GL_HALF_FLOAT_OES;
12804 case GL_LUMINANCE16F_EXT:
12805 return GL_HALF_FLOAT_OES;
12806 case GL_LUMINANCE_ALPHA16F_EXT:
12807 return GL_HALF_FLOAT_OES;
12808 case GL_BGRA8_EXT:
12809 return GL_UNSIGNED_BYTE;
12810 default:
12811 return GL_NONE;
12815 void GLES2DecoderImpl::DoTexStorage2DEXT(
12816 GLenum target,
12817 GLint levels,
12818 GLenum internal_format,
12819 GLsizei width,
12820 GLsizei height) {
12821 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12822 "width", width, "height", height);
12823 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
12824 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
12825 LOCAL_SET_GL_ERROR(
12826 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
12827 return;
12829 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12830 &state_, target);
12831 if (!texture_ref) {
12832 LOCAL_SET_GL_ERROR(
12833 GL_INVALID_OPERATION,
12834 "glTexStorage2DEXT", "unknown texture for target");
12835 return;
12837 Texture* texture = texture_ref->texture();
12838 if (texture->IsAttachedToFramebuffer()) {
12839 framebuffer_state_.clear_state_dirty = true;
12841 if (texture->IsImmutable()) {
12842 LOCAL_SET_GL_ERROR(
12843 GL_INVALID_OPERATION,
12844 "glTexStorage2DEXT", "texture is immutable");
12845 return;
12848 GLenum format = ExtractFormatFromStorageFormat(internal_format);
12849 GLenum type = ExtractTypeFromStorageFormat(internal_format);
12852 GLsizei level_width = width;
12853 GLsizei level_height = height;
12854 uint32 estimated_size = 0;
12855 for (int ii = 0; ii < levels; ++ii) {
12856 uint32 level_size = 0;
12857 if (!GLES2Util::ComputeImageDataSizes(
12858 level_width, level_height, 1, format, type, state_.unpack_alignment,
12859 &estimated_size, NULL, NULL) ||
12860 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
12861 LOCAL_SET_GL_ERROR(
12862 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
12863 return;
12865 level_width = std::max(1, level_width >> 1);
12866 level_height = std::max(1, level_height >> 1);
12868 if (!EnsureGPUMemoryAvailable(estimated_size)) {
12869 LOCAL_SET_GL_ERROR(
12870 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
12871 return;
12875 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
12876 glTexStorage2DEXT(target, levels, internal_format, width, height);
12877 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
12878 if (error == GL_NO_ERROR) {
12879 GLsizei level_width = width;
12880 GLsizei level_height = height;
12881 for (int ii = 0; ii < levels; ++ii) {
12882 GLenum cur_format = feature_info_->IsES3Enabled() ?
12883 internal_format : format;
12884 texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format,
12885 level_width, level_height, 1, 0, format,
12886 type, gfx::Rect());
12887 level_width = std::max(1, level_width >> 1);
12888 level_height = std::max(1, level_height >> 1);
12890 texture->SetImmutable(true);
12894 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
12895 uint32 immediate_data_size,
12896 const void* cmd_data) {
12897 return error::kUnknownCommand;
12900 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
12901 const GLbyte* data) {
12902 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
12903 "context", logger_.GetLogPrefix(),
12904 "mailbox[0]", static_cast<unsigned char>(data[0]));
12906 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12907 &state_, target);
12908 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
12911 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
12912 GLenum target, const GLbyte* data) {
12913 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
12914 "context", logger_.GetLogPrefix(),
12915 "mailbox[0]", static_cast<unsigned char>(data[0]));
12917 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
12918 target, data);
12921 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
12922 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
12923 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12924 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
12925 "mailbox that was not generated by "
12926 "GenMailboxCHROMIUM.";
12928 if (!texture_ref) {
12929 LOCAL_SET_GL_ERROR(
12930 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
12931 return;
12934 Texture* produced = texture_manager()->Produce(texture_ref);
12935 if (!produced) {
12936 LOCAL_SET_GL_ERROR(
12937 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
12938 return;
12941 if (produced->target() != target) {
12942 LOCAL_SET_GL_ERROR(
12943 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
12944 return;
12947 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
12950 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
12951 const GLbyte* data) {
12952 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
12953 "context", logger_.GetLogPrefix(),
12954 "mailbox[0]", static_cast<unsigned char>(data[0]));
12955 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12956 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
12957 "mailbox that was not generated by "
12958 "GenMailboxCHROMIUM.";
12960 scoped_refptr<TextureRef> texture_ref =
12961 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12962 if (!texture_ref.get()) {
12963 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12964 "glConsumeTextureCHROMIUM",
12965 "unknown texture for target");
12966 return;
12968 GLuint client_id = texture_ref->client_id();
12969 if (!client_id) {
12970 LOCAL_SET_GL_ERROR(
12971 GL_INVALID_OPERATION,
12972 "glConsumeTextureCHROMIUM", "unknown texture for target");
12973 return;
12975 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
12976 if (!texture) {
12977 LOCAL_SET_GL_ERROR(
12978 GL_INVALID_OPERATION,
12979 "glConsumeTextureCHROMIUM", "invalid mailbox name");
12980 return;
12982 if (texture->target() != target) {
12983 LOCAL_SET_GL_ERROR(
12984 GL_INVALID_OPERATION,
12985 "glConsumeTextureCHROMIUM", "invalid target");
12986 return;
12989 DeleteTexturesHelper(1, &client_id);
12990 texture_ref = texture_manager()->Consume(client_id, texture);
12991 glBindTexture(target, texture_ref->service_id());
12993 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
12994 unit.bind_target = target;
12995 switch (target) {
12996 case GL_TEXTURE_2D:
12997 unit.bound_texture_2d = texture_ref;
12998 break;
12999 case GL_TEXTURE_CUBE_MAP:
13000 unit.bound_texture_cube_map = texture_ref;
13001 break;
13002 case GL_TEXTURE_EXTERNAL_OES:
13003 unit.bound_texture_external_oes = texture_ref;
13004 break;
13005 case GL_TEXTURE_RECTANGLE_ARB:
13006 unit.bound_texture_rectangle_arb = texture_ref;
13007 break;
13008 default:
13009 NOTREACHED(); // Validation should prevent us getting here.
13010 break;
13014 void GLES2DecoderImpl::EnsureTextureForClientId(
13015 GLenum target,
13016 GLuint client_id) {
13017 TextureRef* texture_ref = GetTexture(client_id);
13018 if (!texture_ref) {
13019 GLuint service_id;
13020 glGenTextures(1, &service_id);
13021 DCHECK_NE(0u, service_id);
13022 texture_ref = CreateTexture(client_id, service_id);
13023 texture_manager()->SetTarget(texture_ref, target);
13024 glBindTexture(target, service_id);
13025 RestoreCurrentTextureBindings(&state_, target);
13029 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13030 // provided is associated with a service_id/TextureRef for consistency, even if
13031 // the resulting texture is incomplete.
13032 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13033 uint32_t immediate_data_size,
13034 const void* cmd_data) {
13035 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
13036 *static_cast<
13037 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
13038 cmd_data);
13039 GLenum target = static_cast<GLenum>(c.target);
13040 uint32_t data_size;
13041 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
13042 return error::kOutOfBounds;
13044 if (data_size > immediate_data_size) {
13045 return error::kOutOfBounds;
13047 const GLbyte* mailbox =
13048 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
13049 if (!validators_->texture_bind_target.IsValid(target)) {
13050 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13051 "glCreateAndConsumeTextureCHROMIUM", target, "target");
13052 return error::kNoError;
13054 if (mailbox == NULL) {
13055 return error::kOutOfBounds;
13057 uint32_t client_id = c.client_id;
13058 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
13059 return error::kNoError;
13062 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
13063 const GLbyte* data, GLuint client_id) {
13064 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13065 "context", logger_.GetLogPrefix(),
13066 "mailbox[0]", static_cast<unsigned char>(data[0]));
13067 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13068 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13069 "passed a mailbox that was not "
13070 "generated by GenMailboxCHROMIUM.";
13072 TextureRef* texture_ref = GetTexture(client_id);
13073 if (texture_ref) {
13074 // No need to call EnsureTextureForClientId here, the client_id already has
13075 // an associated texture.
13076 LOCAL_SET_GL_ERROR(
13077 GL_INVALID_OPERATION,
13078 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13079 return;
13081 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13082 if (!texture) {
13083 EnsureTextureForClientId(target, client_id);
13084 LOCAL_SET_GL_ERROR(
13085 GL_INVALID_OPERATION,
13086 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13087 return;
13090 if (texture->target() != target) {
13091 EnsureTextureForClientId(target, client_id);
13092 LOCAL_SET_GL_ERROR(
13093 GL_INVALID_OPERATION,
13094 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13095 return;
13098 texture_ref = texture_manager()->Consume(client_id, texture);
13101 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
13102 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
13103 return valuebuffer && valuebuffer->IsValid();
13106 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
13107 GLuint client_id) {
13108 Valuebuffer* valuebuffer = NULL;
13109 if (client_id != 0) {
13110 valuebuffer = GetValuebuffer(client_id);
13111 if (!valuebuffer) {
13112 if (!group_->bind_generates_resource()) {
13113 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
13114 "id not generated by glBindValuebufferCHROMIUM");
13115 return;
13118 // It's a new id so make a valuebuffer for it.
13119 CreateValuebuffer(client_id);
13120 valuebuffer = GetValuebuffer(client_id);
13122 valuebuffer->MarkAsValid();
13124 state_.bound_valuebuffer = valuebuffer;
13127 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
13128 GLenum subscription) {
13129 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13130 return;
13132 state_.bound_valuebuffer.get()->AddSubscription(subscription);
13135 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
13136 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13137 return;
13139 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
13142 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
13143 GLenum target,
13144 GLenum subscription) {
13145 if (!CheckCurrentValuebufferForSubscription(
13146 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
13147 return;
13149 if (!CheckSubscriptionTarget(location, subscription,
13150 "glPopulateSubscribedValuesCHROMIUM")) {
13151 return;
13153 const ValueState* state =
13154 state_.bound_valuebuffer.get()->GetState(subscription);
13155 if (state) {
13156 switch (subscription) {
13157 case GL_MOUSE_POSITION_CHROMIUM:
13158 DoUniform2iv(location, 1, state->int_value);
13159 break;
13160 default:
13161 NOTREACHED() << "Unhandled uniform subscription target "
13162 << subscription;
13163 break;
13168 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13169 GLsizei length, const GLchar* marker) {
13170 if (!marker) {
13171 marker = "";
13173 debug_marker_manager_.SetMarker(
13174 length ? std::string(marker, length) : std::string(marker));
13177 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13178 GLsizei /*length*/, const GLchar* /*marker*/) {
13181 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13184 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13185 GLenum target, GLint image_id) {
13186 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13188 if (target == GL_TEXTURE_CUBE_MAP) {
13189 LOCAL_SET_GL_ERROR(
13190 GL_INVALID_ENUM,
13191 "glBindTexImage2DCHROMIUM", "invalid target");
13192 return;
13195 // Default target might be conceptually valid, but disallow it to avoid
13196 // accidents.
13197 TextureRef* texture_ref =
13198 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13199 if (!texture_ref) {
13200 LOCAL_SET_GL_ERROR(
13201 GL_INVALID_OPERATION,
13202 "glBindTexImage2DCHROMIUM", "no texture bound");
13203 return;
13206 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13207 if (!gl_image) {
13208 LOCAL_SET_GL_ERROR(
13209 GL_INVALID_OPERATION,
13210 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13211 return;
13215 ScopedGLErrorSuppressor suppressor(
13216 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13217 if (!gl_image->BindTexImage(target)) {
13218 LOCAL_SET_GL_ERROR(
13219 GL_INVALID_OPERATION,
13220 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13221 return;
13225 gfx::Size size = gl_image->GetSize();
13226 texture_manager()->SetLevelInfo(
13227 texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(),
13228 size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE,
13229 gfx::Rect(size));
13230 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
13233 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13234 GLenum target, GLint image_id) {
13235 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13237 // Default target might be conceptually valid, but disallow it to avoid
13238 // accidents.
13239 TextureRef* texture_ref =
13240 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13241 if (!texture_ref) {
13242 LOCAL_SET_GL_ERROR(
13243 GL_INVALID_OPERATION,
13244 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13245 return;
13248 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13249 if (!gl_image) {
13250 LOCAL_SET_GL_ERROR(
13251 GL_INVALID_OPERATION,
13252 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13253 return;
13256 // Do nothing when image is not currently bound.
13257 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
13258 return;
13261 ScopedGLErrorSuppressor suppressor(
13262 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13263 gl_image->ReleaseTexImage(target);
13266 texture_manager()->SetLevelInfo(
13267 texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0,
13268 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect());
13271 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13272 uint32 immediate_data_size,
13273 const void* cmd_data) {
13274 const gles2::cmds::TraceBeginCHROMIUM& c =
13275 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
13276 Bucket* category_bucket = GetBucket(c.category_bucket_id);
13277 Bucket* name_bucket = GetBucket(c.name_bucket_id);
13278 if (!category_bucket || category_bucket->size() == 0 ||
13279 !name_bucket || name_bucket->size() == 0) {
13280 return error::kInvalidArguments;
13283 std::string category_name;
13284 std::string trace_name;
13285 if (!category_bucket->GetAsString(&category_name) ||
13286 !name_bucket->GetAsString(&trace_name)) {
13287 return error::kInvalidArguments;
13290 debug_marker_manager_.PushGroup(trace_name);
13291 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
13292 LOCAL_SET_GL_ERROR(
13293 GL_INVALID_OPERATION,
13294 "glTraceBeginCHROMIUM", "unable to create begin trace");
13295 return error::kNoError;
13297 return error::kNoError;
13300 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13301 debug_marker_manager_.PopGroup();
13302 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
13303 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13304 "glTraceEndCHROMIUM", "no trace begin found");
13305 return;
13309 void GLES2DecoderImpl::DoDrawBuffersEXT(
13310 GLsizei count, const GLenum* bufs) {
13311 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
13312 LOCAL_SET_GL_ERROR(
13313 GL_INVALID_VALUE,
13314 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13315 return;
13318 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
13319 if (framebuffer) {
13320 for (GLsizei i = 0; i < count; ++i) {
13321 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
13322 bufs[i] != GL_NONE) {
13323 LOCAL_SET_GL_ERROR(
13324 GL_INVALID_OPERATION,
13325 "glDrawBuffersEXT",
13326 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13327 return;
13330 glDrawBuffersARB(count, bufs);
13331 framebuffer->SetDrawBuffers(count, bufs);
13332 } else { // backbuffer
13333 if (count > 1 ||
13334 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
13335 LOCAL_SET_GL_ERROR(
13336 GL_INVALID_OPERATION,
13337 "glDrawBuffersEXT",
13338 "more than one buffer or bufs not GL_NONE or GL_BACK");
13339 return;
13341 GLenum mapped_buf = bufs[0];
13342 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13343 bufs[0] == GL_BACK) {
13344 mapped_buf = GL_COLOR_ATTACHMENT0;
13346 glDrawBuffersARB(count, &mapped_buf);
13347 group_->set_draw_buffer(bufs[0]);
13351 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
13352 MarkContextLost(GetContextLostReasonFromResetStatus(current));
13353 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
13354 reset_by_robustness_extension_ = true;
13357 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13358 // On Adreno Android devices we need to use a workaround to force caches to
13359 // clear.
13360 if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) {
13361 context_->ReleaseCurrent(nullptr);
13362 context_->MakeCurrent(surface_.get());
13366 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
13367 const GLfloat* matrix) {
13368 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13369 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13370 if (!features().chromium_path_rendering) {
13371 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13372 "glMatrixLoadfCHROMIUM",
13373 "function not available");
13374 return;
13377 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13378 ? state_.projection_matrix
13379 : state_.modelview_matrix;
13380 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
13381 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13382 // since the values of the _NV and _CHROMIUM tokens match.
13383 glMatrixLoadfEXT(matrix_mode, matrix);
13386 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
13387 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13388 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13390 if (!features().chromium_path_rendering) {
13391 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13392 "glMatrixLoadIdentityCHROMIUM",
13393 "function not available");
13394 return;
13397 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13398 ? state_.projection_matrix
13399 : state_.modelview_matrix;
13400 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
13401 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13402 // since the values of the _NV and _CHROMIUM tokens match.
13403 glMatrixLoadIdentityEXT(matrix_mode);
13406 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13407 const char* function_name,
13408 TextureRef* texture_ref,
13409 GLenum target,
13410 GLint level,
13411 const void * data) {
13412 // We only support async uploads to 2D textures for now.
13413 if (GL_TEXTURE_2D != target) {
13414 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
13415 return false;
13417 // We only support uploads to level zero for now.
13418 if (level != 0) {
13419 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
13420 return false;
13422 // A transfer buffer must be bound, even for asyncTexImage2D.
13423 if (data == NULL) {
13424 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
13425 return false;
13427 // We only support one async transfer in progress.
13428 if (!texture_ref ||
13429 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
13430 LOCAL_SET_GL_ERROR(
13431 GL_INVALID_OPERATION,
13432 function_name, "transfer already in progress");
13433 return false;
13435 return true;
13438 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13439 uint32 async_upload_token,
13440 uint32 sync_data_shm_id,
13441 uint32 sync_data_shm_offset) {
13442 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
13443 if (!buffer.get() ||
13444 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
13445 return base::Closure();
13447 AsyncMemoryParams mem_params(buffer,
13448 sync_data_shm_offset,
13449 sizeof(AsyncUploadSync));
13451 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
13452 new AsyncUploadTokenCompletionObserver(async_upload_token));
13454 return base::Bind(
13455 &AsyncPixelTransferManager::AsyncNotifyCompletion,
13456 base::Unretained(GetAsyncPixelTransferManager()),
13457 mem_params,
13458 observer);
13461 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13462 uint32 immediate_data_size,
13463 const void* cmd_data) {
13464 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
13465 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
13466 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13467 GLenum target = static_cast<GLenum>(c.target);
13468 GLint level = static_cast<GLint>(c.level);
13469 GLenum internal_format = static_cast<GLenum>(c.internalformat);
13470 GLsizei width = static_cast<GLsizei>(c.width);
13471 GLsizei height = static_cast<GLsizei>(c.height);
13472 GLint border = static_cast<GLint>(c.border);
13473 GLenum format = static_cast<GLenum>(c.format);
13474 GLenum type = static_cast<GLenum>(c.type);
13475 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
13476 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
13477 uint32 pixels_size;
13478 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13479 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13480 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13482 base::ScopedClosureRunner scoped_completion_callback;
13483 if (async_upload_token) {
13484 base::Closure completion_closure =
13485 AsyncUploadTokenCompletionClosure(async_upload_token,
13486 sync_data_shm_id,
13487 sync_data_shm_offset);
13488 if (completion_closure.is_null())
13489 return error::kInvalidArguments;
13491 scoped_completion_callback.Reset(completion_closure);
13494 // TODO(epenner): Move this and copies of this memory validation
13495 // into ValidateTexImage2D step.
13496 if (!GLES2Util::ComputeImageDataSizes(
13497 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
13498 NULL, NULL)) {
13499 return error::kOutOfBounds;
13501 const void* pixels = NULL;
13502 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
13503 pixels = GetSharedMemoryAs<const void*>(
13504 pixels_shm_id, pixels_shm_offset, pixels_size);
13505 if (!pixels) {
13506 return error::kOutOfBounds;
13510 TextureManager::DoTexImageArguments args = {
13511 target, level, internal_format, width, height, 1, border, format, type,
13512 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
13513 TextureRef* texture_ref;
13514 // All the normal glTexSubImage2D validation.
13515 if (!texture_manager()->ValidateTexImage(
13516 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
13517 return error::kNoError;
13520 // Extra async validation.
13521 Texture* texture = texture_ref->texture();
13522 if (!ValidateAsyncTransfer(
13523 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
13524 return error::kNoError;
13526 // Don't allow async redefinition of a textures.
13527 if (texture->IsDefined()) {
13528 LOCAL_SET_GL_ERROR(
13529 GL_INVALID_OPERATION,
13530 "glAsyncTexImage2DCHROMIUM", "already defined");
13531 return error::kNoError;
13534 if (!EnsureGPUMemoryAvailable(pixels_size)) {
13535 LOCAL_SET_GL_ERROR(
13536 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
13537 return error::kNoError;
13540 // Setup the parameters.
13541 AsyncTexImage2DParams tex_params = {
13542 target, level, static_cast<GLenum>(internal_format),
13543 width, height, border, format, type};
13544 AsyncMemoryParams mem_params(
13545 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
13547 // Set up the async state if needed, and make the texture
13548 // immutable so the async state stays valid. The level info
13549 // is set up lazily when the transfer completes.
13550 AsyncPixelTransferDelegate* delegate =
13551 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
13552 tex_params);
13553 texture->SetImmutable(true);
13555 delegate->AsyncTexImage2D(
13556 tex_params,
13557 mem_params,
13558 base::Bind(&TextureManager::SetLevelInfoFromParams,
13559 // The callback is only invoked if the transfer delegate still
13560 // exists, which implies through manager->texture_ref->state
13561 // ownership that both of these pointers are valid.
13562 base::Unretained(texture_manager()),
13563 base::Unretained(texture_ref),
13564 tex_params));
13565 return error::kNoError;
13568 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13569 uint32 immediate_data_size,
13570 const void* cmd_data) {
13571 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
13572 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
13573 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13574 GLenum target = static_cast<GLenum>(c.target);
13575 GLint level = static_cast<GLint>(c.level);
13576 GLint xoffset = static_cast<GLint>(c.xoffset);
13577 GLint yoffset = static_cast<GLint>(c.yoffset);
13578 GLsizei width = static_cast<GLsizei>(c.width);
13579 GLsizei height = static_cast<GLsizei>(c.height);
13580 GLenum format = static_cast<GLenum>(c.format);
13581 GLenum type = static_cast<GLenum>(c.type);
13582 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13583 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13584 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13586 base::ScopedClosureRunner scoped_completion_callback;
13587 if (async_upload_token) {
13588 base::Closure completion_closure =
13589 AsyncUploadTokenCompletionClosure(async_upload_token,
13590 sync_data_shm_id,
13591 sync_data_shm_offset);
13592 if (completion_closure.is_null())
13593 return error::kInvalidArguments;
13595 scoped_completion_callback.Reset(completion_closure);
13598 // TODO(epenner): Move this and copies of this memory validation
13599 // into ValidateTexSubImage2D step.
13600 uint32 data_size;
13601 if (!GLES2Util::ComputeImageDataSizes(
13602 width, height, 1, format, type, state_.unpack_alignment, &data_size,
13603 NULL, NULL)) {
13604 return error::kOutOfBounds;
13606 const void* pixels = GetSharedMemoryAs<const void*>(
13607 c.data_shm_id, c.data_shm_offset, data_size);
13609 // All the normal glTexSubImage2D validation.
13610 error::Error error = error::kNoError;
13611 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
13612 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
13613 return error;
13616 // Extra async validation.
13617 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13618 &state_, target);
13619 Texture* texture = texture_ref->texture();
13620 if (!ValidateAsyncTransfer(
13621 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
13622 return error::kNoError;
13624 // Guarantee async textures are always 'cleared' as follows:
13625 // - AsyncTexImage2D can not redefine an existing texture
13626 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13627 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13628 // - Textures become immutable after an async call.
13629 // This way we know in all cases that an async texture is always clear.
13630 if (!texture->SafeToRenderFrom()) {
13631 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
13632 target, level)) {
13633 LOCAL_SET_GL_ERROR(
13634 GL_OUT_OF_MEMORY,
13635 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
13636 return error::kNoError;
13640 // Setup the parameters.
13641 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
13642 width, height, format, type};
13643 AsyncMemoryParams mem_params(
13644 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
13645 AsyncPixelTransferDelegate* delegate =
13646 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
13647 if (!delegate) {
13648 // TODO(epenner): We may want to enforce exclusive use
13649 // of async APIs in which case this should become an error,
13650 // (the texture should have been async defined).
13651 AsyncTexImage2DParams define_params = {target, level,
13652 0, 0, 0, 0, 0, 0};
13653 texture->GetLevelSize(
13654 target, level, &define_params.width, &define_params.height, nullptr);
13655 texture->GetLevelType(
13656 target, level, &define_params.type, &define_params.internal_format);
13657 // Set up the async state if needed, and make the texture
13658 // immutable so the async state stays valid.
13659 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
13660 texture_ref, define_params);
13661 texture->SetImmutable(true);
13664 delegate->AsyncTexSubImage2D(tex_params, mem_params);
13665 return error::kNoError;
13668 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
13669 uint32 immediate_data_size,
13670 const void* cmd_data) {
13671 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
13672 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
13673 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13674 GLenum target = static_cast<GLenum>(c.target);
13676 if (GL_TEXTURE_2D != target) {
13677 LOCAL_SET_GL_ERROR(
13678 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
13679 return error::kNoError;
13681 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13682 &state_, target);
13683 if (!texture_ref) {
13684 LOCAL_SET_GL_ERROR(
13685 GL_INVALID_OPERATION,
13686 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
13687 return error::kNoError;
13689 AsyncPixelTransferDelegate* delegate =
13690 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
13691 if (!delegate) {
13692 LOCAL_SET_GL_ERROR(
13693 GL_INVALID_OPERATION,
13694 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
13695 return error::kNoError;
13697 delegate->WaitForTransferCompletion();
13698 ProcessFinishedAsyncTransfers();
13699 return error::kNoError;
13702 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
13703 uint32 immediate_data_size,
13704 const void* data) {
13705 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13707 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
13708 ProcessFinishedAsyncTransfers();
13709 return error::kNoError;
13712 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
13713 uint32_t immediate_data_size, const void* cmd_data) {
13714 if (!unsafe_es3_apis_enabled())
13715 return error::kUnknownCommand;
13716 const gles2::cmds::UniformBlockBinding& c =
13717 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
13718 GLuint client_id = c.program;
13719 GLuint index = static_cast<GLuint>(c.index);
13720 GLuint binding = static_cast<GLuint>(c.binding);
13721 Program* program = GetProgramInfoNotShader(
13722 client_id, "glUniformBlockBinding");
13723 if (!program) {
13724 return error::kNoError;
13726 GLuint service_id = program->service_id();
13727 glUniformBlockBinding(service_id, index, binding);
13728 return error::kNoError;
13731 error::Error GLES2DecoderImpl::HandleClientWaitSync(
13732 uint32_t immediate_data_size, const void* cmd_data) {
13733 if (!unsafe_es3_apis_enabled())
13734 return error::kUnknownCommand;
13735 const gles2::cmds::ClientWaitSync& c =
13736 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
13737 GLuint sync = static_cast<GLuint>(c.sync);
13738 GLbitfield flags = static_cast<GLbitfield>(c.flags);
13739 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
13740 typedef cmds::ClientWaitSync::Result Result;
13741 Result* result_dst = GetSharedMemoryAs<Result*>(
13742 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
13743 if (!result_dst) {
13744 return error::kOutOfBounds;
13746 if (*result_dst != GL_WAIT_FAILED) {
13747 return error::kInvalidArguments;
13749 GLsync service_sync = 0;
13750 if (!group_->GetSyncServiceId(sync, &service_sync)) {
13751 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
13752 return error::kNoError;
13754 *result_dst = glClientWaitSync(service_sync, flags, timeout);
13755 return error::kNoError;
13758 error::Error GLES2DecoderImpl::HandleWaitSync(
13759 uint32_t immediate_data_size, const void* cmd_data) {
13760 if (!unsafe_es3_apis_enabled())
13761 return error::kUnknownCommand;
13762 const gles2::cmds::WaitSync& c =
13763 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
13764 GLuint sync = static_cast<GLuint>(c.sync);
13765 GLbitfield flags = static_cast<GLbitfield>(c.flags);
13766 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
13767 GLsync service_sync = 0;
13768 if (!group_->GetSyncServiceId(sync, &service_sync)) {
13769 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
13770 return error::kNoError;
13772 glWaitSync(service_sync, flags, timeout);
13773 return error::kNoError;
13776 error::Error GLES2DecoderImpl::HandleGetInternalformativ(
13777 uint32_t immediate_data_size, const void* cmd_data) {
13778 if (!unsafe_es3_apis_enabled())
13779 return error::kUnknownCommand;
13780 const gles2::cmds::GetInternalformativ& c =
13781 *static_cast<const gles2::cmds::GetInternalformativ*>(cmd_data);
13782 GLenum target = static_cast<GLenum>(c.target);
13783 GLenum format = static_cast<GLenum>(c.format);
13784 GLenum pname = static_cast<GLenum>(c.pname);
13785 if (!validators_->render_buffer_target.IsValid(target)) {
13786 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target, "target");
13787 return error::kNoError;
13789 if (!validators_->render_buffer_format.IsValid(format)) {
13790 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format, "format");
13791 return error::kNoError;
13793 if (!validators_->internal_format_parameter.IsValid(pname)) {
13794 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname, "pname");
13795 return error::kNoError;
13797 typedef cmds::GetInternalformativ::Result Result;
13798 GLsizei num_values = 0;
13799 switch (pname) {
13800 case GL_NUM_SAMPLE_COUNTS:
13801 num_values = 1;
13802 break;
13803 case GL_SAMPLES:
13805 GLint value = 0;
13806 glGetInternalformativ(target, format, GL_NUM_SAMPLE_COUNTS, 1, &value);
13807 num_values = static_cast<GLsizei>(value);
13809 break;
13810 default:
13811 NOTREACHED();
13812 break;
13814 Result* result = GetSharedMemoryAs<Result*>(
13815 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
13816 GLint* params = result ? result->GetData() : NULL;
13817 if (params == NULL) {
13818 return error::kOutOfBounds;
13820 // Check that the client initialized the result.
13821 if (result->size != 0) {
13822 return error::kInvalidArguments;
13824 glGetInternalformativ(target, format, pname, num_values, params);
13825 result->SetNumResults(num_values);
13826 return error::kNoError;
13829 error::Error GLES2DecoderImpl::HandleMapBufferRange(
13830 uint32_t immediate_data_size, const void* cmd_data) {
13831 if (!unsafe_es3_apis_enabled()) {
13832 return error::kUnknownCommand;
13834 const gles2::cmds::MapBufferRange& c =
13835 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
13836 GLenum target = static_cast<GLenum>(c.target);
13837 GLbitfield access = static_cast<GLbitfield>(c.access);
13838 GLintptr offset = static_cast<GLintptr>(c.offset);
13839 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
13841 typedef cmds::MapBufferRange::Result Result;
13842 Result* result = GetSharedMemoryAs<Result*>(
13843 c.result_shm_id, c.result_shm_offset, sizeof(*result));
13844 if (!result) {
13845 return error::kOutOfBounds;
13847 if (*result != 0) {
13848 *result = 0;
13849 return error::kInvalidArguments;
13851 int8_t* mem =
13852 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
13853 if (!mem) {
13854 return error::kOutOfBounds;
13857 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
13858 if ((access & mask) == mask) {
13859 // TODO(zmo): To be on the safe side, always map
13860 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13861 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
13862 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
13864 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
13865 // undefined behaviors.
13866 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
13867 if ((access & mask) == mask) {
13868 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
13869 "incompatible access bits");
13870 return error::kNoError;
13872 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
13873 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
13874 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
13875 access = (access | GL_MAP_READ_BIT);
13877 void* ptr = glMapBufferRange(target, offset, size, access);
13878 if (ptr == nullptr) {
13879 return error::kNoError;
13881 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
13882 DCHECK(buffer);
13883 buffer->SetMappedRange(offset, size, access, ptr,
13884 GetSharedMemoryBuffer(c.data_shm_id));
13885 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
13886 memcpy(mem, ptr, size);
13888 *result = 1;
13889 return error::kNoError;
13892 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
13893 uint32_t immediate_data_size, const void* cmd_data) {
13894 if (!unsafe_es3_apis_enabled()) {
13895 return error::kUnknownCommand;
13897 const gles2::cmds::UnmapBuffer& c =
13898 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
13899 GLenum target = static_cast<GLenum>(c.target);
13901 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
13902 if (!buffer) {
13903 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
13904 return error::kNoError;
13906 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
13907 if (!mapped_range) {
13908 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
13909 "buffer is unmapped");
13910 return error::kNoError;
13912 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
13913 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
13914 GL_MAP_FLUSH_EXPLICIT_BIT) {
13915 // If we don't need to write back, or explict flush is required, no copying
13916 // back is needed.
13917 } else {
13918 void* mem = mapped_range->GetShmPointer();
13919 if (!mem) {
13920 return error::kOutOfBounds;
13922 DCHECK(mapped_range->pointer);
13923 memcpy(mapped_range->pointer, mem, mapped_range->size);
13925 buffer->RemoveMappedRange();
13926 GLboolean rt = glUnmapBuffer(target);
13927 if (rt == GL_FALSE) {
13928 // At this point, we have already done the necessary validation, so
13929 // GL_FALSE indicates data corruption.
13930 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
13931 // the second unmap could still return GL_FALSE. For now, we simply lose
13932 // the contexts in the share group.
13933 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
13934 // Need to lose current context before broadcasting!
13935 MarkContextLost(error::kGuilty);
13936 group_->LoseContexts(error::kInnocent);
13937 return error::kLostContext;
13939 return error::kNoError;
13942 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
13943 TextureRef* texture_ref) {
13944 Texture* texture = texture_ref->texture();
13945 DoDidUseTexImageIfNeeded(texture, texture->target());
13948 // Note that GL_LOST_CONTEXT is specific to GLES.
13949 // For desktop GL we have to query the reset status proactively.
13950 void GLES2DecoderImpl::OnContextLostError() {
13951 if (!WasContextLost()) {
13952 // Need to lose current context before broadcasting!
13953 CheckResetStatus();
13954 group_->LoseContexts(error::kUnknown);
13955 reset_by_robustness_extension_ = true;
13959 void GLES2DecoderImpl::OnOutOfMemoryError() {
13960 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
13961 error::ContextLostReason other = error::kOutOfMemory;
13962 if (CheckResetStatus()) {
13963 other = error::kUnknown;
13964 } else {
13965 // Need to lose current context before broadcasting!
13966 MarkContextLost(error::kOutOfMemory);
13968 group_->LoseContexts(other);
13972 error::Error GLES2DecoderImpl::HandleGenPathsCHROMIUM(
13973 uint32 immediate_data_size,
13974 const void* cmd_data) {
13975 static const char kFunctionName[] = "glGenPathsCHROMIUM";
13976 const gles2::cmds::GenPathsCHROMIUM& c =
13977 *static_cast<const gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
13978 if (!features().chromium_path_rendering) {
13979 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
13980 "function not available");
13981 return error::kNoError;
13984 GLsizei range = static_cast<GLsizei>(c.range);
13985 if (range < 0) {
13986 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
13987 return error::kNoError;
13990 GLuint first_client_id = static_cast<GLuint>(c.first_client_id);
13991 if (first_client_id == 0)
13992 return error::kInvalidArguments;
13994 if (range == 0)
13995 return error::kNoError;
13997 if (!GenPathsCHROMIUMHelper(first_client_id, range))
13998 return error::kInvalidArguments;
14000 return error::kNoError;
14002 error::Error GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14003 uint32_t immediate_data_size,
14004 const void* cmd_data) {
14005 static const char kFunctionName[] = "glDeletePathsCHROMIUM";
14006 const gles2::cmds::DeletePathsCHROMIUM& c =
14007 *static_cast<const gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
14008 if (!features().chromium_path_rendering) {
14009 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14010 "function not available");
14011 return error::kNoError;
14014 GLsizei range = static_cast<GLsizei>(c.range);
14015 if (range < 0) {
14016 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14017 return error::kNoError;
14020 if (range == 0)
14021 return error::kNoError;
14023 GLuint first_client_id = c.first_client_id;
14024 // first_client_id can be 0, because non-existing path ids are skipped.
14026 if (!DeletePathsCHROMIUMHelper(first_client_id, range))
14027 return error::kInvalidArguments;
14029 return error::kNoError;
14032 error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14033 uint32 immediate_data_size,
14034 const void* cmd_data) {
14035 static const char kFunctionName[] = "glPathCommandsCHROMIUM";
14036 const gles2::cmds::PathCommandsCHROMIUM& c =
14037 *static_cast<const gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
14038 if (!features().chromium_path_rendering) {
14039 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14040 "function not available");
14041 return error::kNoError;
14044 GLuint service_id = 0;
14045 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14046 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14047 "invalid path name");
14048 return error::kNoError;
14051 GLsizei num_commands = static_cast<GLsizei>(c.numCommands);
14052 if (num_commands < 0) {
14053 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCommands < 0");
14054 return error::kNoError;
14057 GLsizei num_coords = static_cast<uint32>(c.numCoords);
14058 if (num_coords < 0) {
14059 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCoords < 0");
14060 return error::kNoError;
14063 GLenum coord_type = static_cast<uint32>(c.coordType);
14064 if (!validators_->path_coord_type.IsValid(static_cast<GLint>(coord_type))) {
14065 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid coordType");
14066 return error::kNoError;
14069 const GLubyte* commands = NULL;
14070 base::CheckedNumeric<GLsizei> num_coords_expected = 0;
14072 if (num_commands > 0) {
14073 uint32 commands_shm_id = static_cast<uint32>(c.commands_shm_id);
14074 uint32 commands_shm_offset = static_cast<uint32>(c.commands_shm_offset);
14075 if (commands_shm_id != 0 || commands_shm_offset != 0)
14076 commands = GetSharedMemoryAs<const GLubyte*>(
14077 commands_shm_id, commands_shm_offset, num_commands);
14079 if (!commands)
14080 return error::kOutOfBounds;
14082 for (GLsizei i = 0; i < num_commands; ++i) {
14083 switch (commands[i]) {
14084 case GL_CLOSE_PATH_CHROMIUM:
14085 // Close has no coords.
14086 break;
14087 case GL_MOVE_TO_CHROMIUM:
14088 // Fallthrough.
14089 case GL_LINE_TO_CHROMIUM:
14090 num_coords_expected += 2;
14091 break;
14092 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
14093 num_coords_expected += 4;
14094 break;
14095 case GL_CUBIC_CURVE_TO_CHROMIUM:
14096 num_coords_expected += 6;
14097 break;
14098 case GL_CONIC_CURVE_TO_CHROMIUM:
14099 num_coords_expected += 5;
14100 break;
14101 default:
14102 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid command");
14103 return error::kNoError;
14108 if (!num_coords_expected.IsValid() ||
14109 num_coords != num_coords_expected.ValueOrDie()) {
14110 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14111 "numCoords does not match commands");
14112 return error::kNoError;
14115 const void* coords = NULL;
14117 if (num_coords > 0) {
14118 uint32 coords_size = 0;
14119 uint32 coord_type_size =
14120 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
14121 if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size))
14122 return error::kOutOfBounds;
14124 uint32 coords_shm_id = static_cast<uint32>(c.coords_shm_id);
14125 uint32 coords_shm_offset = static_cast<uint32>(c.coords_shm_offset);
14126 if (coords_shm_id != 0 || coords_shm_offset != 0)
14127 coords = GetSharedMemoryAs<const void*>(coords_shm_id, coords_shm_offset,
14128 coords_size);
14130 if (!coords)
14131 return error::kOutOfBounds;
14134 glPathCommandsNV(service_id, num_commands, commands, num_coords, coord_type,
14135 coords);
14137 return error::kNoError;
14140 error::Error GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14141 uint32 immediate_data_size,
14142 const void* cmd_data) {
14143 static const char kFunctionName[] = "glPathParameterfCHROMIUM";
14144 const gles2::cmds::PathParameterfCHROMIUM& c =
14145 *static_cast<const gles2::cmds::PathParameterfCHROMIUM*>(cmd_data);
14146 if (!features().chromium_path_rendering) {
14147 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14148 "function not available");
14149 return error::kNoError;
14151 GLuint service_id = 0;
14152 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14153 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14154 "invalid path name");
14155 return error::kNoError;
14158 GLenum pname = static_cast<GLenum>(c.pname);
14159 GLfloat value = static_cast<GLfloat>(c.value);
14160 bool hasValueError = false;
14162 switch (pname) {
14163 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14164 case GL_PATH_MITER_LIMIT_CHROMIUM:
14165 hasValueError = std::isnan(value) || !std::isfinite(value) || value < 0;
14166 break;
14167 case GL_PATH_STROKE_BOUND_CHROMIUM:
14168 value = std::max(std::min(1.0f, value), 0.0f);
14169 break;
14170 case GL_PATH_END_CAPS_CHROMIUM:
14171 hasValueError = !validators_->path_parameter_cap_values.IsValid(
14172 static_cast<GLint>(value));
14173 break;
14174 case GL_PATH_JOIN_STYLE_CHROMIUM:
14175 hasValueError = !validators_->path_parameter_join_values.IsValid(
14176 static_cast<GLint>(value));
14177 break;
14178 default:
14179 DCHECK(!validators_->path_parameter.IsValid(pname));
14180 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14181 return error::kNoError;
14183 DCHECK(validators_->path_parameter.IsValid(pname));
14185 if (hasValueError) {
14186 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14187 return error::kNoError;
14190 glPathParameterfNV(service_id, pname, value);
14191 return error::kNoError;
14194 error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14195 uint32 immediate_data_size,
14196 const void* cmd_data) {
14197 static const char kFunctionName[] = "glPathParameteriCHROMIUM";
14198 const gles2::cmds::PathParameteriCHROMIUM& c =
14199 *static_cast<const gles2::cmds::PathParameteriCHROMIUM*>(cmd_data);
14200 if (!features().chromium_path_rendering) {
14201 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14202 "function not available");
14203 return error::kNoError;
14205 GLuint service_id = 0;
14206 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14207 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14208 "invalid path name");
14209 return error::kNoError;
14212 GLenum pname = static_cast<GLenum>(c.pname);
14213 GLint value = static_cast<GLint>(c.value);
14214 bool hasValueError = false;
14216 switch (pname) {
14217 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14218 case GL_PATH_MITER_LIMIT_CHROMIUM:
14219 hasValueError = value < 0;
14220 break;
14221 case GL_PATH_STROKE_BOUND_CHROMIUM:
14222 value = std::max(std::min(1, value), 0);
14223 break;
14224 case GL_PATH_END_CAPS_CHROMIUM:
14225 hasValueError = !validators_->path_parameter_cap_values.IsValid(value);
14226 break;
14227 case GL_PATH_JOIN_STYLE_CHROMIUM:
14228 hasValueError = !validators_->path_parameter_join_values.IsValid(value);
14229 break;
14230 default:
14231 DCHECK(!validators_->path_parameter.IsValid(pname));
14232 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14233 return error::kNoError;
14235 DCHECK(validators_->path_parameter.IsValid(pname));
14237 if (hasValueError) {
14238 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14239 return error::kNoError;
14242 glPathParameteriNV(service_id, pname, value);
14243 return error::kNoError;
14246 error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14247 uint32 immediate_data_size,
14248 const void* cmd_data) {
14249 static const char kFunctionName[] = "glStencilFillPathCHROMIUM";
14250 const gles2::cmds::StencilFillPathCHROMIUM& c =
14251 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(cmd_data);
14252 if (!features().chromium_path_rendering) {
14253 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14254 "function not available");
14255 return error::kNoError;
14257 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14258 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14259 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14260 return error::kNoError;
14262 GLuint mask = static_cast<GLuint>(c.mask);
14263 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14264 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14265 GLES2Util::IsNPOT(mask + 1)) {
14266 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14267 "mask + 1 is not power of two");
14268 return error::kNoError;
14270 GLuint service_id = 0;
14271 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14272 // "If /path/ does not name an existing path object, the command does
14273 // nothing (and no error is generated)."
14274 // This holds for other rendering functions, too.
14275 return error::kNoError;
14277 ApplyDirtyState();
14278 glStencilFillPathNV(service_id, fill_mode, mask);
14279 return error::kNoError;
14282 error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14283 uint32 immediate_data_size,
14284 const void* cmd_data) {
14285 static const char kFunctionName[] = "glStencilStrokePathCHROMIUM";
14286 const gles2::cmds::StencilStrokePathCHROMIUM& c =
14287 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data);
14288 if (!features().chromium_path_rendering) {
14289 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14290 "function not available");
14291 return error::kNoError;
14293 GLuint service_id = 0;
14294 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14295 return error::kNoError;
14297 GLint reference = static_cast<GLint>(c.reference);
14298 GLuint mask = static_cast<GLuint>(c.mask);
14299 ApplyDirtyState();
14300 glStencilStrokePathNV(service_id, reference, mask);
14301 return error::kNoError;
14304 error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14305 uint32 immediate_data_size,
14306 const void* cmd_data) {
14307 static const char kFunctionName[] = "glCoverFillPathCHROMIUM";
14308 const gles2::cmds::CoverFillPathCHROMIUM& c =
14309 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data);
14310 if (!features().chromium_path_rendering) {
14311 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14312 "function not available");
14313 return error::kNoError;
14315 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14316 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14317 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14318 return error::kNoError;
14320 GLuint service_id = 0;
14321 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14322 return error::kNoError;
14324 ApplyDirtyState();
14325 glCoverFillPathNV(service_id, cover_mode);
14326 return error::kNoError;
14329 error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14330 uint32 immediate_data_size,
14331 const void* cmd_data) {
14332 static const char kFunctionName[] = "glCoverStrokePathCHROMIUM";
14333 const gles2::cmds::CoverStrokePathCHROMIUM& c =
14334 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data);
14335 if (!features().chromium_path_rendering) {
14336 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14337 "function not available");
14338 return error::kNoError;
14340 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14341 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14342 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14343 return error::kNoError;
14345 GLuint service_id = 0;
14346 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14347 return error::kNoError;
14349 ApplyDirtyState();
14350 glCoverStrokePathNV(service_id, cover_mode);
14351 return error::kNoError;
14354 error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14355 uint32 immediate_data_size,
14356 const void* cmd_data) {
14357 static const char kFunctionName[] = "glStencilThenCoverFillPathCHROMIUM";
14358 const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
14359 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
14360 cmd_data);
14361 if (!features().chromium_path_rendering) {
14362 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14363 "function not available");
14364 return error::kNoError;
14366 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14367 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14368 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14369 return error::kNoError;
14371 GLuint mask = static_cast<GLuint>(c.mask);
14372 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14373 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14374 GLES2Util::IsNPOT(mask + 1)) {
14375 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14376 "mask + 1 is not power of two");
14377 return error::kNoError;
14379 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14380 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14381 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14382 return error::kNoError;
14384 GLuint service_id = 0;
14385 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14386 return error::kNoError;
14388 ApplyDirtyState();
14389 glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode);
14390 return error::kNoError;
14393 error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14394 uint32 immediate_data_size,
14395 const void* cmd_data) {
14396 static const char kFunctionName[] = "glStencilThenCoverStrokePathCHROMIUM";
14397 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
14398 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
14399 cmd_data);
14400 if (!features().chromium_path_rendering) {
14401 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14402 "function not available");
14403 return error::kNoError;
14405 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14406 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14407 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14408 return error::kNoError;
14410 GLuint service_id = 0;
14411 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14412 return error::kNoError;
14414 GLint reference = static_cast<GLint>(c.reference);
14415 GLuint mask = static_cast<GLuint>(c.mask);
14416 ApplyDirtyState();
14417 glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode);
14418 return error::kNoError;
14421 // Include the auto-generated part of this file. We split this because it means
14422 // we can easily edit the non-auto generated parts right here in this file
14423 // instead of having to edit some template or the code generator.
14424 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14426 } // namespace gles2
14427 } // namespace gpu