Elim cr-checkbox
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob5310f38639c8a99e9d856604b13986641dfbfceb
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
7 #include <stdio.h>
9 #include <algorithm>
10 #include <cmath>
11 #include <list>
12 #include <map>
13 #include <queue>
15 #include "base/callback.h"
16 #include "base/callback_helpers.h"
17 #include "base/command_line.h"
18 #include "base/logging.h"
19 #include "base/memory/linked_ptr.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/numerics/safe_math.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/trace_event/trace_event.h"
25 #include "base/trace_event/trace_event_synthetic_delay.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/mailbox.h"
32 #include "gpu/command_buffer/service/buffer_manager.h"
33 #include "gpu/command_buffer/service/context_group.h"
34 #include "gpu/command_buffer/service/context_state.h"
35 #include "gpu/command_buffer/service/error_state.h"
36 #include "gpu/command_buffer/service/feature_info.h"
37 #include "gpu/command_buffer/service/framebuffer_manager.h"
38 #include "gpu/command_buffer/service/gl_utils.h"
39 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
40 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
41 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
42 #include "gpu/command_buffer/service/gpu_state_tracer.h"
43 #include "gpu/command_buffer/service/gpu_switches.h"
44 #include "gpu/command_buffer/service/gpu_tracer.h"
45 #include "gpu/command_buffer/service/image_manager.h"
46 #include "gpu/command_buffer/service/logger.h"
47 #include "gpu/command_buffer/service/mailbox_manager.h"
48 #include "gpu/command_buffer/service/memory_tracking.h"
49 #include "gpu/command_buffer/service/path_manager.h"
50 #include "gpu/command_buffer/service/program_manager.h"
51 #include "gpu/command_buffer/service/query_manager.h"
52 #include "gpu/command_buffer/service/renderbuffer_manager.h"
53 #include "gpu/command_buffer/service/shader_manager.h"
54 #include "gpu/command_buffer/service/shader_translator.h"
55 #include "gpu/command_buffer/service/texture_manager.h"
56 #include "gpu/command_buffer/service/valuebuffer_manager.h"
57 #include "gpu/command_buffer/service/vertex_array_manager.h"
58 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
59 #include "third_party/smhasher/src/City.h"
60 #include "ui/gfx/geometry/point.h"
61 #include "ui/gfx/geometry/rect.h"
62 #include "ui/gfx/geometry/size.h"
63 #include "ui/gfx/overlay_transform.h"
64 #include "ui/gl/gl_bindings.h"
65 #include "ui/gl/gl_context.h"
66 #include "ui/gl/gl_fence.h"
67 #include "ui/gl/gl_image.h"
68 #include "ui/gl/gl_implementation.h"
69 #include "ui/gl/gl_surface.h"
70 #include "ui/gl/gl_version_info.h"
71 #include "ui/gl/gpu_timing.h"
73 #if defined(OS_MACOSX)
74 #include <IOSurface/IOSurface.h>
75 // Note that this must be included after gl_bindings.h to avoid conflicts.
76 #include <OpenGL/CGLIOSurface.h>
77 #endif
79 namespace gpu {
80 namespace gles2 {
82 namespace {
84 const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
85 const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
86 const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
87 const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
89 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
90 0.0f, 1.0f, 0.0f, 0.0f,
91 0.0f, 0.0f, 1.0f, 0.0f,
92 0.0f, 0.0f, 0.0f, 1.0f};
94 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
95 GLint rangeMax,
96 GLint precision) {
97 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
100 void GetShaderPrecisionFormatImpl(GLenum shader_type,
101 GLenum precision_type,
102 GLint* range, GLint* precision) {
103 switch (precision_type) {
104 case GL_LOW_INT:
105 case GL_MEDIUM_INT:
106 case GL_HIGH_INT:
107 // These values are for a 32-bit twos-complement integer format.
108 range[0] = 31;
109 range[1] = 30;
110 *precision = 0;
111 break;
112 case GL_LOW_FLOAT:
113 case GL_MEDIUM_FLOAT:
114 case GL_HIGH_FLOAT:
115 // These values are for an IEEE single-precision floating-point format.
116 range[0] = 127;
117 range[1] = 127;
118 *precision = 23;
119 break;
120 default:
121 NOTREACHED();
122 break;
125 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
126 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
127 // This function is sometimes defined even though it's really just
128 // a stub, so we need to set range and precision as if it weren't
129 // defined before calling it.
130 // On Mac OS with some GPUs, calling this generates a
131 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
132 // platforms.
133 glGetShaderPrecisionFormat(shader_type, precision_type,
134 range, precision);
136 // TODO(brianderson): Make the following official workarounds.
138 // Some drivers have bugs where they report the ranges as a negative number.
139 // Taking the absolute value here shouldn't hurt because negative numbers
140 // aren't expected anyway.
141 range[0] = abs(range[0]);
142 range[1] = abs(range[1]);
144 // If the driver reports a precision for highp float that isn't actually
145 // highp, don't pretend like it's supported because shader compilation will
146 // fail anyway.
147 if (precision_type == GL_HIGH_FLOAT &&
148 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
149 range[0] = 0;
150 range[1] = 0;
151 *precision = 0;
156 gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
157 switch (plane_transform) {
158 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
159 return gfx::OVERLAY_TRANSFORM_NONE;
160 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
161 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
162 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
163 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
164 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
165 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
166 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
168 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
170 default:
171 return gfx::OVERLAY_TRANSFORM_INVALID;
175 template <typename MANAGER_TYPE, typename OBJECT_TYPE>
176 GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) {
177 DCHECK(manager);
178 GLuint client_id = 0;
179 if (object) {
180 manager->GetClientId(object->service_id(), &client_id);
182 return client_id;
185 struct Vec4f {
186 explicit Vec4f(const Vec4& data) {
187 data.GetValues(v);
190 GLfloat v[4];
193 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
194 // contains the other rectangle or shares an edge with the other rectangle.
195 bool CombineAdjacentRects(const gfx::Rect& rect1,
196 const gfx::Rect& rect2,
197 gfx::Rect* result) {
198 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
199 if (rect1.IsEmpty() || rect2.Contains(rect1)) {
200 *result = rect2;
201 return true;
204 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
205 if (rect2.IsEmpty() || rect1.Contains(rect2)) {
206 *result = rect1;
207 return true;
210 // Return the union of |rect1| and |rect2| if they share an edge.
211 if (rect1.SharesEdgeWith(rect2)) {
212 *result = gfx::UnionRects(rect1, rect2);
213 return true;
216 // Return false if it's not possible to combine |rect1| and |rect2|.
217 return false;
220 } // namespace
222 class GLES2DecoderImpl;
224 // Local versions of the SET_GL_ERROR macros
225 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
226 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
227 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
228 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
229 function_name, value, label)
230 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
231 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
232 function_name, pname)
233 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
234 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
235 function_name)
236 #define LOCAL_PEEK_GL_ERROR(function_name) \
237 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
238 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
239 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
240 #define LOCAL_PERFORMANCE_WARNING(msg) \
241 PerformanceWarning(__FILE__, __LINE__, msg)
242 #define LOCAL_RENDER_WARNING(msg) \
243 RenderWarning(__FILE__, __LINE__, msg)
245 // Check that certain assumptions the code makes are true. There are places in
246 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
247 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
248 // a few others) are 32bits. If they are not 32bits the code will have to change
249 // to call those GL functions with service side memory and then copy the results
250 // to shared memory, converting the sizes.
251 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
252 "GLint should be the same size as uint32");
253 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
254 "GLsizei should be the same size as uint32");
255 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
256 "GLfloat should be the same size as float");
258 // TODO(kbr): the use of this anonymous namespace core dumps the
259 // linker on Mac OS X 10.6 when the symbol ordering file is used
260 // namespace {
262 // Returns the address of the first byte after a struct.
263 template <typename T>
264 const void* AddressAfterStruct(const T& pod) {
265 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
268 // Returns the address of the frst byte after the struct or NULL if size >
269 // immediate_data_size.
270 template <typename RETURN_TYPE, typename COMMAND_TYPE>
271 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
272 uint32 size,
273 uint32 immediate_data_size) {
274 return (size <= immediate_data_size) ?
275 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
276 NULL;
279 // Computes the data size for certain gl commands like glUniform.
280 bool ComputeDataSize(
281 GLuint count,
282 size_t size,
283 unsigned int elements_per_unit,
284 uint32* dst) {
285 uint32 value;
286 if (!SafeMultiplyUint32(count, size, &value)) {
287 return false;
289 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
290 return false;
292 *dst = value;
293 return true;
296 // Return true if a character belongs to the ASCII subset as defined in
297 // GLSL ES 1.0 spec section 3.1.
298 static bool CharacterIsValidForGLES(unsigned char c) {
299 // Printing characters are valid except " $ ` @ \ ' DEL.
300 if (c >= 32 && c <= 126 &&
301 c != '"' &&
302 c != '$' &&
303 c != '`' &&
304 c != '@' &&
305 c != '\\' &&
306 c != '\'') {
307 return true;
309 // Horizontal tab, line feed, vertical tab, form feed, carriage return
310 // are also valid.
311 if (c >= 9 && c <= 13) {
312 return true;
315 return false;
318 static bool StringIsValidForGLES(const char* str) {
319 for (; *str; ++str) {
320 if (!CharacterIsValidForGLES(*str)) {
321 return false;
324 return true;
327 // This class prevents any GL errors that occur when it is in scope from
328 // being reported to the client.
329 class ScopedGLErrorSuppressor {
330 public:
331 explicit ScopedGLErrorSuppressor(
332 const char* function_name, ErrorState* error_state);
333 ~ScopedGLErrorSuppressor();
334 private:
335 const char* function_name_;
336 ErrorState* error_state_;
337 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
340 // Temporarily changes a decoder's bound texture and restore it when this
341 // object goes out of scope. Also temporarily switches to using active texture
342 // unit zero in case the client has changed that to something invalid.
343 class ScopedTextureBinder {
344 public:
345 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
346 ~ScopedTextureBinder();
348 private:
349 ContextState* state_;
350 GLenum target_;
351 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
354 // Temporarily changes a decoder's bound render buffer and restore it when this
355 // object goes out of scope.
356 class ScopedRenderBufferBinder {
357 public:
358 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
359 ~ScopedRenderBufferBinder();
361 private:
362 ContextState* state_;
363 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
366 // Temporarily changes a decoder's bound frame buffer and restore it when this
367 // object goes out of scope.
368 class ScopedFrameBufferBinder {
369 public:
370 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
371 ~ScopedFrameBufferBinder();
373 private:
374 GLES2DecoderImpl* decoder_;
375 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
378 // Temporarily changes a decoder's bound frame buffer to a resolved version of
379 // the multisampled offscreen render buffer if that buffer is multisampled, and,
380 // if it is bound or enforce_internal_framebuffer is true. If internal is
381 // true, the resolved framebuffer is not visible to the parent.
382 class ScopedResolvedFrameBufferBinder {
383 public:
384 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
385 bool enforce_internal_framebuffer,
386 bool internal);
387 ~ScopedResolvedFrameBufferBinder();
389 private:
390 GLES2DecoderImpl* decoder_;
391 bool resolve_and_bind_;
392 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
395 class ScopedModifyPixels {
396 public:
397 explicit ScopedModifyPixels(TextureRef* ref);
398 ~ScopedModifyPixels();
400 private:
401 TextureRef* ref_;
404 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
405 if (ref_)
406 ref_->texture()->OnWillModifyPixels();
409 ScopedModifyPixels::~ScopedModifyPixels() {
410 if (ref_)
411 ref_->texture()->OnDidModifyPixels();
414 class ScopedRenderTo {
415 public:
416 explicit ScopedRenderTo(Framebuffer* framebuffer)
417 : ScopedRenderTo(framebuffer, 0) {}
418 ScopedRenderTo(Framebuffer* framebuffer, GLenum attachment);
419 ~ScopedRenderTo();
421 private:
422 const Framebuffer* framebuffer_;
423 GLenum attachment_;
426 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer, GLenum attachment)
427 : framebuffer_(framebuffer),
428 attachment_(attachment) {
429 if (framebuffer_)
430 framebuffer_->OnWillRenderTo(attachment_);
433 ScopedRenderTo::~ScopedRenderTo() {
434 if (framebuffer_)
435 framebuffer_->OnDidRenderTo(attachment_);
438 // Encapsulates an OpenGL texture.
439 class BackTexture {
440 public:
441 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
442 ~BackTexture();
444 // Create a new render texture.
445 void Create();
447 // Set the initial size and format of a render texture or resize it.
448 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
450 // Copy the contents of the currently bound frame buffer.
451 void Copy(const gfx::Size& size, GLenum format);
453 // Destroy the render texture. This must be explicitly called before
454 // destroying this object.
455 void Destroy();
457 // Invalidate the texture. This can be used when a context is lost and it is
458 // not possible to make it current in order to free the resource.
459 void Invalidate();
461 GLuint id() const {
462 return id_;
465 gfx::Size size() const {
466 return size_;
469 private:
470 MemoryTypeTracker memory_tracker_;
471 ContextState* state_;
472 size_t bytes_allocated_;
473 GLuint id_;
474 gfx::Size size_;
475 DISALLOW_COPY_AND_ASSIGN(BackTexture);
478 // Encapsulates an OpenGL render buffer of any format.
479 class BackRenderbuffer {
480 public:
481 explicit BackRenderbuffer(
482 RenderbufferManager* renderbuffer_manager,
483 MemoryTracker* memory_tracker,
484 ContextState* state);
485 ~BackRenderbuffer();
487 // Create a new render buffer.
488 void Create();
490 // Set the initial size and format of a render buffer or resize it.
491 bool AllocateStorage(const FeatureInfo* feature_info,
492 const gfx::Size& size,
493 GLenum format,
494 GLsizei samples);
496 // Destroy the render buffer. This must be explicitly called before destroying
497 // this object.
498 void Destroy();
500 // Invalidate the render buffer. This can be used when a context is lost and
501 // it is not possible to make it current in order to free the resource.
502 void Invalidate();
504 GLuint id() const {
505 return id_;
508 private:
509 RenderbufferManager* renderbuffer_manager_;
510 MemoryTypeTracker memory_tracker_;
511 ContextState* state_;
512 size_t bytes_allocated_;
513 GLuint id_;
514 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
517 // Encapsulates an OpenGL frame buffer.
518 class BackFramebuffer {
519 public:
520 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
521 ~BackFramebuffer();
523 // Create a new frame buffer.
524 void Create();
526 // Attach a color render buffer to a frame buffer.
527 void AttachRenderTexture(BackTexture* texture);
529 // Attach a render buffer to a frame buffer. Note that this unbinds any
530 // currently bound frame buffer.
531 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
533 // Destroy the frame buffer. This must be explicitly called before destroying
534 // this object.
535 void Destroy();
537 // Invalidate the frame buffer. This can be used when a context is lost and it
538 // is not possible to make it current in order to free the resource.
539 void Invalidate();
541 // See glCheckFramebufferStatusEXT.
542 GLenum CheckStatus();
544 GLuint id() const {
545 return id_;
548 private:
549 GLES2DecoderImpl* decoder_;
550 GLuint id_;
551 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
554 struct FenceCallback {
555 FenceCallback()
556 : fence(gfx::GLFence::Create()) {
557 DCHECK(fence);
559 std::vector<base::Closure> callbacks;
560 scoped_ptr<gfx::GLFence> fence;
563 // } // anonymous namespace.
565 // static
566 const unsigned int GLES2Decoder::kDefaultStencilMask =
567 static_cast<unsigned int>(-1);
569 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
570 uint32* service_texture_id) {
571 return false;
574 GLES2Decoder::GLES2Decoder()
575 : initialized_(false),
576 debug_(false),
577 log_commands_(false),
578 unsafe_es3_apis_enabled_(false) {
581 GLES2Decoder::~GLES2Decoder() {
584 void GLES2Decoder::BeginDecoding() {}
586 void GLES2Decoder::EndDecoding() {}
588 // This class implements GLES2Decoder so we don't have to expose all the GLES2
589 // cmd stuff to outside this class.
590 class GLES2DecoderImpl : public GLES2Decoder,
591 public FramebufferManager::TextureDetachObserver,
592 public ErrorStateClient {
593 public:
594 explicit GLES2DecoderImpl(ContextGroup* group);
595 ~GLES2DecoderImpl() override;
597 // Overridden from AsyncAPIInterface.
598 Error DoCommand(unsigned int command,
599 unsigned int arg_count,
600 const void* args) override;
602 error::Error DoCommands(unsigned int num_commands,
603 const void* buffer,
604 int num_entries,
605 int* entries_processed) override;
607 template <bool DebugImpl>
608 error::Error DoCommandsImpl(unsigned int num_commands,
609 const void* buffer,
610 int num_entries,
611 int* entries_processed);
613 // Overridden from AsyncAPIInterface.
614 const char* GetCommandName(unsigned int command_id) const override;
616 // Overridden from GLES2Decoder.
617 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
618 const scoped_refptr<gfx::GLContext>& context,
619 bool offscreen,
620 const gfx::Size& offscreen_size,
621 const DisallowedFeatures& disallowed_features,
622 const std::vector<int32>& attribs) override;
623 void Destroy(bool have_context) override;
624 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
625 void ProduceFrontBuffer(const Mailbox& mailbox) override;
626 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
627 void UpdateParentTextureInfo();
628 bool MakeCurrent() override;
629 GLES2Util* GetGLES2Util() override { return &util_; }
630 gfx::GLContext* GetGLContext() override { return context_.get(); }
631 ContextGroup* GetContextGroup() override { return group_.get(); }
632 Capabilities GetCapabilities() override;
633 void RestoreState(const ContextState* prev_state) override;
635 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
636 void RestoreAllTextureUnitBindings(
637 const ContextState* prev_state) const override {
638 state_.RestoreAllTextureUnitBindings(prev_state);
640 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
641 state_.RestoreActiveTextureUnitBinding(target);
643 void RestoreBufferBindings() const override {
644 state_.RestoreBufferBindings();
646 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
647 void RestoreProgramBindings() const override {
648 state_.RestoreProgramBindings();
650 void RestoreTextureUnitBindings(unsigned unit) const override {
651 state_.RestoreTextureUnitBindings(unit, NULL);
653 void RestoreFramebufferBindings() const override;
654 void RestoreRenderbufferBindings() override;
655 void RestoreTextureState(unsigned service_id) const override;
657 void ClearAllAttributes() const override;
658 void RestoreAllAttributes() const override;
660 QueryManager* GetQueryManager() override { return query_manager_.get(); }
661 VertexArrayManager* GetVertexArrayManager() override {
662 return vertex_array_manager_.get();
664 ImageManager* GetImageManager() override { return image_manager_.get(); }
666 ValuebufferManager* GetValuebufferManager() override {
667 return valuebuffer_manager();
670 bool HasPendingQueries() const override;
671 void ProcessPendingQueries(bool did_finish) override;
673 bool HasMoreIdleWork() const override;
674 void PerformIdleWork() override;
676 void WaitForReadPixels(base::Closure callback) override;
678 void SetResizeCallback(
679 const base::Callback<void(gfx::Size, float)>& callback) override;
681 Logger* GetLogger() override;
683 void BeginDecoding() override;
684 void EndDecoding() override;
686 ErrorState* GetErrorState() override;
687 const ContextState* GetContextState() override { return &state_; }
689 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
690 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
692 void SetIgnoreCachedStateForTest(bool ignore) override;
693 void ProcessFinishedAsyncTransfers();
695 bool GetServiceTextureId(uint32 client_texture_id,
696 uint32* service_texture_id) override;
698 uint32 GetTextureUploadCount() override;
699 base::TimeDelta GetTotalTextureUploadTime() override;
700 base::TimeDelta GetTotalProcessingCommandsTime() override;
701 void AddProcessingCommandsTime(base::TimeDelta) override;
703 // Restores the current state to the user's settings.
704 void RestoreCurrentFramebufferBindings();
706 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
707 void ApplyDirtyState();
709 // These check the state of the currently bound framebuffer or the
710 // backbuffer if no framebuffer is bound.
711 // Check with all attached and enabled color attachments.
712 bool BoundFramebufferHasColorAttachmentWithAlpha();
713 bool BoundFramebufferHasDepthAttachment();
714 bool BoundFramebufferHasStencilAttachment();
716 error::ContextLostReason GetContextLostReason() override;
718 // Overridden from FramebufferManager::TextureDetachObserver:
719 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
721 // Overriden from ErrorStateClient.
722 void OnContextLostError() override;
723 void OnOutOfMemoryError() override;
725 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
726 void EnsureRenderbufferBound();
728 // Helpers to facilitate calling into compatible extensions.
729 static void RenderbufferStorageMultisampleHelper(
730 const FeatureInfo* feature_info,
731 GLenum target,
732 GLsizei samples,
733 GLenum internal_format,
734 GLsizei width,
735 GLsizei height);
737 void BlitFramebufferHelper(GLint srcX0,
738 GLint srcY0,
739 GLint srcX1,
740 GLint srcY1,
741 GLint dstX0,
742 GLint dstY0,
743 GLint dstX1,
744 GLint dstY1,
745 GLbitfield mask,
746 GLenum filter);
748 private:
749 friend class ScopedFrameBufferBinder;
750 friend class ScopedResolvedFrameBufferBinder;
751 friend class BackFramebuffer;
753 // Initialize or re-initialize the shader translator.
754 bool InitializeShaderTranslator();
756 void UpdateCapabilities();
758 // Helpers for the glGen and glDelete functions.
759 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
760 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
761 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
762 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
763 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
764 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
765 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
766 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
767 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
768 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
769 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
770 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
771 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
772 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
773 bool GenPathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
774 bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
776 // Workarounds
777 void OnFboChanged() const;
778 void OnUseFramebuffer() const;
780 error::ContextLostReason GetContextLostReasonFromResetStatus(
781 GLenum reset_status) const;
783 // TODO(gman): Cache these pointers?
784 BufferManager* buffer_manager() {
785 return group_->buffer_manager();
788 RenderbufferManager* renderbuffer_manager() {
789 return group_->renderbuffer_manager();
792 FramebufferManager* framebuffer_manager() {
793 return group_->framebuffer_manager();
796 ValuebufferManager* valuebuffer_manager() {
797 return group_->valuebuffer_manager();
800 PathManager* path_manager() { return group_->path_manager(); }
802 ProgramManager* program_manager() {
803 return group_->program_manager();
806 ShaderManager* shader_manager() {
807 return group_->shader_manager();
810 ShaderTranslatorCache* shader_translator_cache() {
811 return group_->shader_translator_cache();
814 const TextureManager* texture_manager() const {
815 return group_->texture_manager();
818 TextureManager* texture_manager() {
819 return group_->texture_manager();
822 MailboxManager* mailbox_manager() {
823 return group_->mailbox_manager();
826 ImageManager* image_manager() { return image_manager_.get(); }
828 VertexArrayManager* vertex_array_manager() {
829 return vertex_array_manager_.get();
832 MemoryTracker* memory_tracker() {
833 return group_->memory_tracker();
836 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
837 MemoryTracker* tracker = memory_tracker();
838 if (tracker) {
839 return tracker->EnsureGPUMemoryAvailable(estimated_size);
841 return true;
844 bool IsWebGLContext() const {
845 return webgl_version_ == 1 || webgl_version_ == 2;
848 bool IsOffscreenBufferMultisampled() const {
849 return offscreen_target_samples_ > 1;
852 // Creates a Texture for the given texture.
853 TextureRef* CreateTexture(
854 GLuint client_id, GLuint service_id) {
855 return texture_manager()->CreateTexture(client_id, service_id);
858 // Gets the texture info for the given texture. Returns NULL if none exists.
859 TextureRef* GetTexture(GLuint client_id) const {
860 return texture_manager()->GetTexture(client_id);
863 // Deletes the texture info for the given texture.
864 void RemoveTexture(GLuint client_id) {
865 texture_manager()->RemoveTexture(client_id);
868 // Get the size (in pixels) of the currently bound frame buffer (either FBO
869 // or regular back buffer).
870 gfx::Size GetBoundReadFrameBufferSize();
872 // Get the format/type of the currently bound frame buffer (either FBO or
873 // regular back buffer).
874 // If the color image is a renderbuffer, returns 0 for type.
875 GLenum GetBoundReadFrameBufferTextureType();
876 GLenum GetBoundReadFrameBufferInternalFormat();
878 // Get the i-th draw buffer's internal format from the bound framebuffer.
879 // If no framebuffer is bound, or no image is attached, or the DrawBuffers
880 // setting for that image is GL_NONE, return 0.
881 GLenum GetBoundColorDrawBufferInternalFormat(GLint drawbuffer_i);
883 void MarkDrawBufferAsCleared(GLenum buffer, GLint drawbuffer_i);
885 // Wrapper for CompressedTexImage2D commands.
886 error::Error DoCompressedTexImage2D(
887 GLenum target,
888 GLint level,
889 GLenum internal_format,
890 GLsizei width,
891 GLsizei height,
892 GLint border,
893 GLsizei image_size,
894 const void* data);
896 // Wrapper for CompressedTexImage3D commands.
897 error::Error DoCompressedTexImage3D(
898 GLenum target,
899 GLint level,
900 GLenum internal_format,
901 GLsizei width,
902 GLsizei height,
903 GLsizei depth,
904 GLint border,
905 GLsizei image_size,
906 const void* data);
908 // Wrapper for CompressedTexSubImage2D.
909 void DoCompressedTexSubImage2D(
910 GLenum target,
911 GLint level,
912 GLint xoffset,
913 GLint yoffset,
914 GLsizei width,
915 GLsizei height,
916 GLenum format,
917 GLsizei imageSize,
918 const void * data);
920 // Wrapper for CompressedTexSubImage3D.
921 void DoCompressedTexSubImage3D(
922 GLenum target,
923 GLint level,
924 GLint xoffset,
925 GLint yoffset,
926 GLint zoffset,
927 GLsizei width,
928 GLsizei height,
929 GLsizei depth,
930 GLenum format,
931 GLsizei image_size,
932 const void* data);
934 // Wrapper for CopyTexImage2D.
935 void DoCopyTexImage2D(
936 GLenum target,
937 GLint level,
938 GLenum internal_format,
939 GLint x,
940 GLint y,
941 GLsizei width,
942 GLsizei height,
943 GLint border);
945 // Wrapper for SwapBuffers.
946 void DoSwapBuffers();
948 // Wrapper for SwapInterval.
949 void DoSwapInterval(int interval);
951 // Wrapper for CopyTexSubImage2D.
952 void DoCopyTexSubImage2D(
953 GLenum target,
954 GLint level,
955 GLint xoffset,
956 GLint yoffset,
957 GLint x,
958 GLint y,
959 GLsizei width,
960 GLsizei height);
962 // Validation for TexSubImage2D.
963 bool ValidateTexSubImage2D(
964 error::Error* error,
965 const char* function_name,
966 GLenum target,
967 GLint level,
968 GLint xoffset,
969 GLint yoffset,
970 GLsizei width,
971 GLsizei height,
972 GLenum format,
973 GLenum type,
974 const void * data);
976 // Wrapper for TexSubImage2D.
977 error::Error DoTexSubImage2D(
978 GLenum target,
979 GLint level,
980 GLint xoffset,
981 GLint yoffset,
982 GLsizei width,
983 GLsizei height,
984 GLenum format,
985 GLenum type,
986 const void * data);
988 // Wrapper for TexSubImage3D.
989 error::Error DoTexSubImage3D(
990 GLenum target,
991 GLint level,
992 GLint xoffset,
993 GLint yoffset,
994 GLint zoffset,
995 GLsizei width,
996 GLsizei height,
997 GLsizei depth,
998 GLenum format,
999 GLenum type,
1000 const void * data);
1002 // Wrapper for TexImageIOSurface2DCHROMIUM.
1003 void DoTexImageIOSurface2DCHROMIUM(
1004 GLenum target,
1005 GLsizei width,
1006 GLsizei height,
1007 GLuint io_surface_id,
1008 GLuint plane);
1010 void DoCopyTextureCHROMIUM(GLenum target,
1011 GLuint source_id,
1012 GLuint dest_id,
1013 GLenum internal_format,
1014 GLenum dest_type,
1015 GLboolean unpack_flip_y,
1016 GLboolean unpack_premultiply_alpha,
1017 GLboolean unpack_unmultiply_alpha);
1019 void DoCopySubTextureCHROMIUM(GLenum target,
1020 GLuint source_id,
1021 GLuint dest_id,
1022 GLint xoffset,
1023 GLint yoffset,
1024 GLint x,
1025 GLint y,
1026 GLsizei width,
1027 GLsizei height,
1028 GLboolean unpack_flip_y,
1029 GLboolean unpack_premultiply_alpha,
1030 GLboolean unpack_unmultiply_alpha);
1032 void DoCompressedCopyTextureCHROMIUM(GLenum target,
1033 GLuint source_id,
1034 GLuint dest_id);
1036 void DoCompressedCopySubTextureCHROMIUM(GLenum target,
1037 GLuint source_id,
1038 GLuint dest_id,
1039 GLint xoffset,
1040 GLint yoffset,
1041 GLint x,
1042 GLint y,
1043 GLsizei width,
1044 GLsizei height);
1046 // Wrapper for TexStorage2DEXT.
1047 void DoTexStorage2DEXT(
1048 GLenum target,
1049 GLint levels,
1050 GLenum internal_format,
1051 GLsizei width,
1052 GLsizei height);
1054 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
1055 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
1056 const GLbyte* key);
1057 void ProduceTextureRef(const char* func_name,
1058 TextureRef* texture_ref,
1059 GLenum target,
1060 const GLbyte* data);
1062 void EnsureTextureForClientId(GLenum target, GLuint client_id);
1063 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
1064 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
1065 GLuint client_id);
1066 void DoApplyScreenSpaceAntialiasingCHROMIUM();
1068 bool DoIsValuebufferCHROMIUM(GLuint client_id);
1069 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
1070 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
1071 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
1072 void DoUniformValueBufferCHROMIUM(GLint location,
1073 GLenum target,
1074 GLenum subscription);
1076 void DoBindTexImage2DCHROMIUM(
1077 GLenum target,
1078 GLint image_id);
1079 void DoReleaseTexImage2DCHROMIUM(
1080 GLenum target,
1081 GLint image_id);
1083 void DoTraceEndCHROMIUM(void);
1085 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1087 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1089 void DoFlushDriverCachesCHROMIUM(void);
1091 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1092 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1094 // Creates a Program for the given program.
1095 Program* CreateProgram(
1096 GLuint client_id, GLuint service_id) {
1097 return program_manager()->CreateProgram(client_id, service_id);
1100 // Gets the program info for the given program. Returns NULL if none exists.
1101 Program* GetProgram(GLuint client_id) {
1102 return program_manager()->GetProgram(client_id);
1105 #if defined(NDEBUG)
1106 void LogClientServiceMapping(
1107 const char* /* function_name */,
1108 GLuint /* client_id */,
1109 GLuint /* service_id */) {
1111 template<typename T>
1112 void LogClientServiceForInfo(
1113 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1115 #else
1116 void LogClientServiceMapping(
1117 const char* function_name, GLuint client_id, GLuint service_id) {
1118 if (service_logging_) {
1119 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1120 << ": client_id = " << client_id
1121 << ", service_id = " << service_id;
1124 template<typename T>
1125 void LogClientServiceForInfo(
1126 T* info, GLuint client_id, const char* function_name) {
1127 if (info) {
1128 LogClientServiceMapping(function_name, client_id, info->service_id());
1131 #endif
1133 // Gets the program info for the given program. If it's not a program
1134 // generates a GL error. Returns NULL if not program.
1135 Program* GetProgramInfoNotShader(
1136 GLuint client_id, const char* function_name) {
1137 Program* program = GetProgram(client_id);
1138 if (!program) {
1139 if (GetShader(client_id)) {
1140 LOCAL_SET_GL_ERROR(
1141 GL_INVALID_OPERATION, function_name, "shader passed for program");
1142 } else {
1143 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1146 LogClientServiceForInfo(program, client_id, function_name);
1147 return program;
1151 // Creates a Shader for the given shader.
1152 Shader* CreateShader(
1153 GLuint client_id,
1154 GLuint service_id,
1155 GLenum shader_type) {
1156 return shader_manager()->CreateShader(
1157 client_id, service_id, shader_type);
1160 // Gets the shader info for the given shader. Returns NULL if none exists.
1161 Shader* GetShader(GLuint client_id) {
1162 return shader_manager()->GetShader(client_id);
1165 // Gets the shader info for the given shader. If it's not a shader generates a
1166 // GL error. Returns NULL if not shader.
1167 Shader* GetShaderInfoNotProgram(
1168 GLuint client_id, const char* function_name) {
1169 Shader* shader = GetShader(client_id);
1170 if (!shader) {
1171 if (GetProgram(client_id)) {
1172 LOCAL_SET_GL_ERROR(
1173 GL_INVALID_OPERATION, function_name, "program passed for shader");
1174 } else {
1175 LOCAL_SET_GL_ERROR(
1176 GL_INVALID_VALUE, function_name, "unknown shader");
1179 LogClientServiceForInfo(shader, client_id, function_name);
1180 return shader;
1183 // Creates a buffer info for the given buffer.
1184 void CreateBuffer(GLuint client_id, GLuint service_id) {
1185 return buffer_manager()->CreateBuffer(client_id, service_id);
1188 // Gets the buffer info for the given buffer.
1189 Buffer* GetBuffer(GLuint client_id) {
1190 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1191 return buffer;
1194 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1195 // on glDeleteBuffers so we can make sure the user does not try to render
1196 // with deleted buffers.
1197 void RemoveBuffer(GLuint client_id);
1199 // Creates a framebuffer info for the given framebuffer.
1200 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1201 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1204 // Gets the framebuffer info for the given framebuffer.
1205 Framebuffer* GetFramebuffer(GLuint client_id) {
1206 return framebuffer_manager()->GetFramebuffer(client_id);
1209 // Removes the framebuffer info for the given framebuffer.
1210 void RemoveFramebuffer(GLuint client_id) {
1211 framebuffer_manager()->RemoveFramebuffer(client_id);
1214 // Creates a renderbuffer info for the given renderbuffer.
1215 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1216 return renderbuffer_manager()->CreateRenderbuffer(
1217 client_id, service_id);
1220 // Gets the renderbuffer info for the given renderbuffer.
1221 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1222 return renderbuffer_manager()->GetRenderbuffer(client_id);
1225 // Removes the renderbuffer info for the given renderbuffer.
1226 void RemoveRenderbuffer(GLuint client_id) {
1227 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1230 // Creates a valuebuffer info for the given valuebuffer.
1231 void CreateValuebuffer(GLuint client_id) {
1232 return valuebuffer_manager()->CreateValuebuffer(client_id);
1235 // Gets the valuebuffer info for a given valuebuffer.
1236 Valuebuffer* GetValuebuffer(GLuint client_id) {
1237 return valuebuffer_manager()->GetValuebuffer(client_id);
1240 // Removes the valuebuffer info for the given valuebuffer.
1241 void RemoveValuebuffer(GLuint client_id) {
1242 valuebuffer_manager()->RemoveValuebuffer(client_id);
1245 // Gets the vertex attrib manager for the given vertex array.
1246 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1247 VertexAttribManager* info =
1248 vertex_array_manager()->GetVertexAttribManager(client_id);
1249 return info;
1252 // Removes the vertex attrib manager for the given vertex array.
1253 void RemoveVertexAttribManager(GLuint client_id) {
1254 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1257 // Creates a vertex attrib manager for the given vertex array.
1258 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1259 GLuint client_id,
1260 GLuint service_id,
1261 bool client_visible) {
1262 return vertex_array_manager()->CreateVertexAttribManager(
1263 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1266 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1267 void DoBindUniformLocationCHROMIUM(
1268 GLuint client_id, GLint location, const char* name);
1270 error::Error GetAttribLocationHelper(
1271 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1272 const std::string& name_str);
1274 error::Error GetUniformLocationHelper(
1275 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1276 const std::string& name_str);
1278 error::Error GetFragDataLocationHelper(
1279 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1280 const std::string& name_str);
1282 // Wrapper for glShaderSource.
1283 void DoShaderSource(
1284 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1286 // Wrapper for glTransformFeedbackVaryings.
1287 void DoTransformFeedbackVaryings(
1288 GLuint client_program_id, GLsizei count, const char* const* varyings,
1289 GLenum buffer_mode);
1291 // Clear any textures used by the current program.
1292 bool ClearUnclearedTextures();
1294 // Clears any uncleared attachments attached to the given frame buffer.
1295 // Returns false if there was a generated GL error.
1296 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1298 // overridden from GLES2Decoder
1299 bool ClearLevel(Texture* texture,
1300 unsigned target,
1301 int level,
1302 unsigned format,
1303 unsigned type,
1304 int xoffset,
1305 int yoffset,
1306 int width,
1307 int height) override;
1309 // Restore all GL state that affects clearing.
1310 void RestoreClearState();
1312 // Remembers the state of some capabilities.
1313 // Returns: true if glEnable/glDisable should actually be called.
1314 bool SetCapabilityState(GLenum cap, bool enabled);
1316 // Check that the currently bound framebuffers are valid.
1317 // Generates GL error if not.
1318 bool CheckBoundFramebuffersValid(const char* func_name);
1320 // Check that the currently bound read framebuffer has a color image
1321 // attached. Generates GL error if not.
1322 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1324 // Check that the currently bound read framebuffer's color image
1325 // isn't the target texture of the glCopyTex{Sub}Image2D.
1326 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1328 // Check if a framebuffer meets our requirements.
1329 bool CheckFramebufferValid(
1330 Framebuffer* framebuffer,
1331 GLenum target,
1332 const char* func_name);
1334 bool CheckBoundDrawFramebufferValid(const char* func_name);
1336 // Check if the current valuebuffer exists and is valid. If not generates
1337 // the appropriate GL error. Returns true if the current valuebuffer is in
1338 // a usable state.
1339 bool CheckCurrentValuebuffer(const char* function_name);
1341 // Check if the current valuebuffer exists and is valiud and that the
1342 // value buffer is actually subscribed to the given subscription
1343 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1344 const char* function_name);
1346 // Check if the location can be used for the given subscription target. If not
1347 // generates the appropriate GL error. Returns true if the location is usable
1348 bool CheckSubscriptionTarget(GLint location,
1349 GLenum subscription,
1350 const char* function_name);
1352 // Checks if the current program exists and is valid. If not generates the
1353 // appropriate GL error. Returns true if the current program is in a usable
1354 // state.
1355 bool CheckCurrentProgram(const char* function_name);
1357 // Checks if the current program exists and is valid and that location is not
1358 // -1. If the current program is not valid generates the appropriate GL
1359 // error. Returns true if the current program is in a usable state and
1360 // location is not -1.
1361 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1363 // Checks if the current program samples a texture that is also the color
1364 // image of the current bound framebuffer, i.e., the source and destination
1365 // of the draw operation are the same.
1366 bool CheckDrawingFeedbackLoops();
1368 // Checks if |api_type| is valid for the given uniform
1369 // If the api type is not valid generates the appropriate GL
1370 // error. Returns true if |api_type| is valid for the uniform
1371 bool CheckUniformForApiType(const Program::UniformInfo* info,
1372 const char* function_name,
1373 Program::UniformApiType api_type);
1375 // Gets the type of a uniform for a location in the current program. Sets GL
1376 // errors if the current program is not valid. Returns true if the current
1377 // program is valid and the location exists. Adjusts count so it
1378 // does not overflow the uniform.
1379 bool PrepForSetUniformByLocation(GLint fake_location,
1380 const char* function_name,
1381 Program::UniformApiType api_type,
1382 GLint* real_location,
1383 GLenum* type,
1384 GLsizei* count);
1386 // Gets the service id for any simulated backbuffer fbo.
1387 GLuint GetBackbufferServiceId() const;
1389 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1390 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1392 // Helper for glGetVertexAttrib
1393 void GetVertexAttribHelper(
1394 const VertexAttrib* attrib, GLenum pname, GLint* param);
1396 // Wrapper for glActiveTexture
1397 void DoActiveTexture(GLenum texture_unit);
1399 // Wrapper for glAttachShader
1400 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1402 // Wrapper for glBindBuffer since we need to track the current targets.
1403 void DoBindBuffer(GLenum target, GLuint buffer);
1405 // Wrapper for glBindBufferBase since we need to track the current targets.
1406 void DoBindBufferBase(GLenum target, GLuint index, GLuint buffer);
1408 // Wrapper for glBindBufferRange since we need to track the current targets.
1409 void DoBindBufferRange(GLenum target, GLuint index, GLuint buffer,
1410 GLintptr offset, GLsizeiptr size);
1412 // Wrapper for glBindFramebuffer since we need to track the current targets.
1413 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1415 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1416 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1418 // Wrapper for glBindTexture since we need to track the current targets.
1419 void DoBindTexture(GLenum target, GLuint texture);
1421 // Wrapper for glBindVertexArrayOES
1422 void DoBindVertexArrayOES(GLuint array);
1423 void EmulateVertexArrayState();
1425 // Wrapper for glBlitFramebufferCHROMIUM.
1426 void DoBlitFramebufferCHROMIUM(
1427 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1428 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1429 GLbitfield mask, GLenum filter);
1431 // Wrapper for glBufferSubData.
1432 void DoBufferSubData(
1433 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1435 // Wrapper for glCheckFramebufferStatus
1436 GLenum DoCheckFramebufferStatus(GLenum target);
1438 // Wrapper for glClear*()
1439 error::Error DoClear(GLbitfield mask);
1440 void DoClearBufferiv(
1441 GLenum buffer, GLint drawbuffer, const GLint* value);
1442 void DoClearBufferuiv(
1443 GLenum buffer, GLint drawbuffer, const GLuint* value);
1444 void DoClearBufferfv(
1445 GLenum buffer, GLint drawbuffer, const GLfloat* value);
1446 void DoClearBufferfi(
1447 GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
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 glGetBufferParameteri64v.
1537 void DoGetBufferParameteri64v(
1538 GLenum target, GLenum pname, GLint64* params);
1540 // Wrapper for glGetBufferParameteriv.
1541 void DoGetBufferParameteriv(
1542 GLenum target, GLenum pname, GLint* params);
1544 // Wrapper for glGetProgramiv.
1545 void DoGetProgramiv(
1546 GLuint program_id, GLenum pname, GLint* params);
1548 // Wrapper for glRenderbufferParameteriv.
1549 void DoGetRenderbufferParameteriv(
1550 GLenum target, GLenum pname, GLint* params);
1552 // Wrapper for glGetShaderiv
1553 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1555 // Wrappers for glGetTexParameter.
1556 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1557 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1558 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1560 // Wrappers for glGetVertexAttrib.
1561 template <typename T>
1562 void DoGetVertexAttribImpl(GLuint index, GLenum pname, T* params);
1563 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
1564 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
1565 void DoGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
1566 void DoGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
1568 // Wrappers for glIsXXX functions.
1569 bool DoIsEnabled(GLenum cap);
1570 bool DoIsBuffer(GLuint client_id);
1571 bool DoIsFramebuffer(GLuint client_id);
1572 bool DoIsProgram(GLuint client_id);
1573 bool DoIsRenderbuffer(GLuint client_id);
1574 bool DoIsShader(GLuint client_id);
1575 bool DoIsTexture(GLuint client_id);
1576 bool DoIsVertexArrayOES(GLuint client_id);
1577 bool DoIsPathCHROMIUM(GLuint client_id);
1579 // Wrapper for glLinkProgram
1580 void DoLinkProgram(GLuint program);
1582 // Wrapper for glReadBuffer
1583 void DoReadBuffer(GLenum src);
1585 // Wrapper for glRenderbufferStorage.
1586 void DoRenderbufferStorage(
1587 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1589 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1590 void DoRenderbufferStorageMultisampleCHROMIUM(
1591 GLenum target, GLsizei samples, GLenum internalformat,
1592 GLsizei width, GLsizei height);
1594 // Handler for glRenderbufferStorageMultisampleEXT
1595 // (multisampled_render_to_texture).
1596 void DoRenderbufferStorageMultisampleEXT(
1597 GLenum target, GLsizei samples, GLenum internalformat,
1598 GLsizei width, GLsizei height);
1600 // Common validation for multisample extensions.
1601 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1602 GLenum internalformat,
1603 GLsizei width,
1604 GLsizei height);
1606 // Verifies that the currently bound multisample renderbuffer is valid
1607 // Very slow! Only done on platforms with driver bugs that return invalid
1608 // buffers under memory pressure
1609 bool VerifyMultisampleRenderbufferIntegrity(
1610 GLuint renderbuffer, GLenum format);
1612 // Wrapper for glReleaseShaderCompiler.
1613 void DoReleaseShaderCompiler() { }
1615 // Wrappers for glSamplerParameter*v functions.
1616 void DoSamplerParameterfv(
1617 GLuint sampler, GLenum pname, const GLfloat* params);
1618 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1620 // Wrappers for glTexParameter functions.
1621 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1622 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1623 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1624 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1626 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1627 // spec only these 2 functions can be used to set sampler uniforms.
1628 void DoUniform1i(GLint fake_location, GLint v0);
1629 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1630 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1631 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1632 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1634 void DoUniform1ui(GLint fake_location, GLuint v0);
1635 void DoUniform1uiv(GLint fake_location, GLsizei count, const GLuint* value);
1636 void DoUniform2uiv(GLint fake_location, GLsizei count, const GLuint* value);
1637 void DoUniform3uiv(GLint fake_location, GLsizei count, const GLuint* value);
1638 void DoUniform4uiv(GLint fake_location, GLsizei count, const GLuint* value);
1640 // Wrappers for glUniformfv because some drivers don't correctly accept
1641 // bool uniforms.
1642 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1643 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1644 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1645 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1647 void DoUniformMatrix2fv(
1648 GLint fake_location, GLsizei count, GLboolean transpose,
1649 const GLfloat* value);
1650 void DoUniformMatrix3fv(
1651 GLint fake_location, GLsizei count, GLboolean transpose,
1652 const GLfloat* value);
1653 void DoUniformMatrix4fv(
1654 GLint fake_location, GLsizei count, GLboolean transpose,
1655 const GLfloat* value);
1656 void DoUniformMatrix2x3fv(
1657 GLint fake_location, GLsizei count, GLboolean transpose,
1658 const GLfloat* value);
1659 void DoUniformMatrix2x4fv(
1660 GLint fake_location, GLsizei count, GLboolean transpose,
1661 const GLfloat* value);
1662 void DoUniformMatrix3x2fv(
1663 GLint fake_location, GLsizei count, GLboolean transpose,
1664 const GLfloat* value);
1665 void DoUniformMatrix3x4fv(
1666 GLint fake_location, GLsizei count, GLboolean transpose,
1667 const GLfloat* value);
1668 void DoUniformMatrix4x2fv(
1669 GLint fake_location, GLsizei count, GLboolean transpose,
1670 const GLfloat* value);
1671 void DoUniformMatrix4x3fv(
1672 GLint fake_location, GLsizei count, GLboolean transpose,
1673 const GLfloat* value);
1675 template <typename T>
1676 bool SetVertexAttribValue(
1677 const char* function_name, GLuint index, const T* value);
1679 // Wrappers for glVertexAttrib??
1680 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1681 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1682 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1683 void DoVertexAttrib4f(
1684 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1685 void DoVertexAttrib1fv(GLuint index, const GLfloat* v);
1686 void DoVertexAttrib2fv(GLuint index, const GLfloat* v);
1687 void DoVertexAttrib3fv(GLuint index, const GLfloat* v);
1688 void DoVertexAttrib4fv(GLuint index, const GLfloat* v);
1689 void DoVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
1690 void DoVertexAttribI4iv(GLuint index, const GLint* v);
1691 void DoVertexAttribI4ui(
1692 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
1693 void DoVertexAttribI4uiv(GLuint index, const GLuint* v);
1695 // Wrapper for glViewport
1696 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1698 // Wrapper for glUseProgram
1699 void DoUseProgram(GLuint program);
1701 // Wrapper for glValidateProgram.
1702 void DoValidateProgram(GLuint program_client_id);
1704 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1705 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1706 void DoPopGroupMarkerEXT(void);
1708 // Gets the number of values that will be returned by glGetXXX. Returns
1709 // false if pname is unknown.
1710 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1712 // Checks if the current program and vertex attributes are valid for drawing.
1713 bool IsDrawValid(
1714 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1715 GLsizei primcount);
1717 // Returns true if successful, simulated will be true if attrib0 was
1718 // simulated.
1719 bool SimulateAttrib0(
1720 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1721 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1723 // If an image is bound to texture, this will call Will/DidUseTexImage
1724 // if needed.
1725 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1726 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1728 // Returns false if textures were replaced.
1729 bool PrepareTexturesForRender();
1730 void RestoreStateForTextures();
1732 // Returns true if GL_FIXED attribs were simulated.
1733 bool SimulateFixedAttribs(
1734 const char* function_name,
1735 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1736 void RestoreStateForSimulatedFixedAttribs();
1738 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1739 // cases (primcount is always 1 for non-instanced).
1740 error::Error DoDrawArrays(
1741 const char* function_name,
1742 bool instanced, GLenum mode, GLint first, GLsizei count,
1743 GLsizei primcount);
1744 error::Error DoDrawElements(
1745 const char* function_name,
1746 bool instanced, GLenum mode, GLsizei count, GLenum type,
1747 int32 offset, GLsizei primcount);
1749 GLenum GetBindTargetForSamplerType(GLenum type) {
1750 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1751 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1752 switch (type) {
1753 case GL_SAMPLER_2D:
1754 return GL_TEXTURE_2D;
1755 case GL_SAMPLER_CUBE:
1756 return GL_TEXTURE_CUBE_MAP;
1757 case GL_SAMPLER_EXTERNAL_OES:
1758 return GL_TEXTURE_EXTERNAL_OES;
1759 case GL_SAMPLER_2D_RECT_ARB:
1760 return GL_TEXTURE_RECTANGLE_ARB;
1763 NOTREACHED();
1764 return 0;
1767 // Gets the framebuffer info for a particular target.
1768 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1769 Framebuffer* framebuffer = NULL;
1770 switch (target) {
1771 case GL_FRAMEBUFFER:
1772 case GL_DRAW_FRAMEBUFFER_EXT:
1773 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1774 break;
1775 case GL_READ_FRAMEBUFFER_EXT:
1776 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1777 break;
1778 default:
1779 NOTREACHED();
1780 break;
1782 return framebuffer;
1785 Renderbuffer* GetRenderbufferInfoForTarget(
1786 GLenum target) {
1787 Renderbuffer* renderbuffer = NULL;
1788 switch (target) {
1789 case GL_RENDERBUFFER:
1790 renderbuffer = state_.bound_renderbuffer.get();
1791 break;
1792 default:
1793 NOTREACHED();
1794 break;
1796 return renderbuffer;
1799 // Validates the program and location for a glGetUniform call and returns
1800 // a SizeResult setup to receive the result. Returns true if glGetUniform
1801 // should be called.
1802 template <class T>
1803 bool GetUniformSetup(GLuint program,
1804 GLint fake_location,
1805 uint32 shm_id,
1806 uint32 shm_offset,
1807 error::Error* error,
1808 GLint* real_location,
1809 GLuint* service_id,
1810 SizedResult<T>** result,
1811 GLenum* result_type,
1812 GLsizei* result_size);
1814 bool WasContextLost() const override;
1815 bool WasContextLostByRobustnessExtension() const override;
1816 void MarkContextLost(error::ContextLostReason reason) override;
1817 bool CheckResetStatus();
1819 #if defined(OS_MACOSX)
1820 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1821 #endif
1823 bool GetCompressedTexSizeInBytes(
1824 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1825 GLenum format, GLsizei* size_in_bytes);
1827 bool ValidateCompressedTexDimensions(
1828 const char* function_name, GLenum target, GLint level,
1829 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1830 bool ValidateCompressedTexFuncData(
1831 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1832 GLenum format, GLsizei size);
1833 bool ValidateCompressedTexSubDimensions(
1834 const char* function_name,
1835 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1836 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1837 Texture* texture);
1838 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1839 GLenum target,
1840 TextureRef* source_texture_ref,
1841 TextureRef* dest_texture_ref,
1842 GLenum dest_internal_format);
1843 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name,
1844 GLenum target,
1845 TextureRef* source_texture_ref,
1846 TextureRef* dest_texture_ref);
1848 void RenderWarning(const char* filename, int line, const std::string& msg);
1849 void PerformanceWarning(
1850 const char* filename, int line, const std::string& msg);
1852 const FeatureInfo::FeatureFlags& features() const {
1853 return feature_info_->feature_flags();
1856 const FeatureInfo::Workarounds& workarounds() const {
1857 return feature_info_->workarounds();
1860 bool ShouldDeferDraws() {
1861 return !offscreen_target_frame_buffer_.get() &&
1862 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1863 surface_->DeferDraws();
1866 bool ShouldDeferReads() {
1867 return !offscreen_target_frame_buffer_.get() &&
1868 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1869 surface_->DeferDraws();
1872 bool IsRobustnessSupported() {
1873 return has_robustness_extension_ &&
1874 context_->WasAllocatedUsingRobustnessExtension();
1877 error::Error WillAccessBoundFramebufferForDraw() {
1878 if (ShouldDeferDraws())
1879 return error::kDeferCommandUntilLater;
1880 if (!offscreen_target_frame_buffer_.get() &&
1881 !framebuffer_state_.bound_draw_framebuffer.get() &&
1882 !surface_->SetBackbufferAllocation(true))
1883 return error::kLostContext;
1884 return error::kNoError;
1887 error::Error WillAccessBoundFramebufferForRead() {
1888 if (ShouldDeferReads())
1889 return error::kDeferCommandUntilLater;
1890 if (!offscreen_target_frame_buffer_.get() &&
1891 !framebuffer_state_.bound_read_framebuffer.get() &&
1892 !surface_->SetBackbufferAllocation(true))
1893 return error::kLostContext;
1894 return error::kNoError;
1897 bool BackBufferHasAlpha() const {
1898 if (back_buffer_draw_buffer_ == GL_NONE)
1899 return false;
1900 if (offscreen_target_frame_buffer_.get()) {
1901 return (offscreen_target_color_format_ == GL_RGBA ||
1902 offscreen_target_color_format_ == GL_RGBA8);
1904 return (back_buffer_color_format_ == GL_RGBA ||
1905 back_buffer_color_format_ == GL_RGBA8);
1908 // Set remaining commands to process to 0 to force DoCommands to return
1909 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1910 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1912 void ProcessPendingReadPixels(bool did_finish);
1913 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1915 // Generate a member function prototype for each command in an automated and
1916 // typesafe way.
1917 #define GLES2_CMD_OP(name) \
1918 Error Handle##name(uint32 immediate_data_size, const void* data);
1920 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1922 #undef GLES2_CMD_OP
1924 // The GL context this decoder renders to on behalf of the client.
1925 scoped_refptr<gfx::GLSurface> surface_;
1926 scoped_refptr<gfx::GLContext> context_;
1928 // The ContextGroup for this decoder uses to track resources.
1929 scoped_refptr<ContextGroup> group_;
1931 DebugMarkerManager debug_marker_manager_;
1932 Logger logger_;
1934 // All the state for this context.
1935 ContextState state_;
1937 // Current width and height of the offscreen frame buffer.
1938 gfx::Size offscreen_size_;
1940 // Util to help with GL.
1941 GLES2Util util_;
1943 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1944 GLuint attrib_0_buffer_id_;
1946 // The value currently in attrib_0.
1947 Vec4 attrib_0_value_;
1949 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1950 bool attrib_0_buffer_matches_value_;
1952 // The size of attrib 0.
1953 GLsizei attrib_0_size_;
1955 // The buffer used to simulate GL_FIXED attribs.
1956 GLuint fixed_attrib_buffer_id_;
1958 // The size of fiixed attrib buffer.
1959 GLsizei fixed_attrib_buffer_size_;
1961 // The offscreen frame buffer that the client renders to. With EGL, the
1962 // depth and stencil buffers are separate. With regular GL there is a single
1963 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1964 // offscreen_target_stencil_render_buffer_ is unused.
1965 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1966 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1967 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1968 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1969 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1970 GLenum offscreen_target_color_format_;
1971 GLenum offscreen_target_depth_format_;
1972 GLenum offscreen_target_stencil_format_;
1973 GLsizei offscreen_target_samples_;
1974 GLboolean offscreen_target_buffer_preserved_;
1976 // The copy that is saved when SwapBuffers is called.
1977 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1978 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1979 scoped_refptr<TextureRef>
1980 offscreen_saved_color_texture_info_;
1982 // The copy that is used as the destination for multi-sample resolves.
1983 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1984 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1985 GLenum offscreen_saved_color_format_;
1987 scoped_ptr<QueryManager> query_manager_;
1989 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1991 scoped_ptr<ImageManager> image_manager_;
1993 base::Callback<void(gfx::Size, float)> resize_callback_;
1995 WaitSyncPointCallback wait_sync_point_callback_;
1997 ShaderCacheCallback shader_cache_callback_;
1999 // The format of the back buffer_
2000 GLenum back_buffer_color_format_;
2001 bool back_buffer_has_depth_;
2002 bool back_buffer_has_stencil_;
2004 // Tracks read buffer and draw buffer for backbuffer, whether it's onscreen
2005 // or offscreen.
2006 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
2007 // setting is set correctly when SwapBuffers().
2008 GLenum back_buffer_read_buffer_;
2009 GLenum back_buffer_draw_buffer_;
2011 bool surfaceless_;
2013 // Backbuffer attachments that are currently undefined.
2014 uint32 backbuffer_needs_clear_bits_;
2016 // The current decoder error communicates the decoder error through command
2017 // processing functions that do not return the error value. Should be set only
2018 // if not returning an error.
2019 error::Error current_decoder_error_;
2021 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
2022 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
2024 DisallowedFeatures disallowed_features_;
2026 // Cached from ContextGroup
2027 const Validators* validators_;
2028 scoped_refptr<FeatureInfo> feature_info_;
2030 int frame_number_;
2032 // Number of commands remaining to be processed in DoCommands().
2033 int commands_to_process_;
2035 bool has_robustness_extension_;
2036 error::ContextLostReason context_lost_reason_;
2037 bool context_was_lost_;
2038 bool reset_by_robustness_extension_;
2039 bool supports_post_sub_buffer_;
2041 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2042 // 0: other types
2043 // 1: WebGL 1
2044 // 2: WebGL 2
2045 unsigned webgl_version_;
2047 // These flags are used to override the state of the shared feature_info_
2048 // member. Because the same FeatureInfo instance may be shared among many
2049 // contexts, the assumptions on the availablity of extensions in WebGL
2050 // contexts may be broken. These flags override the shared state to preserve
2051 // WebGL semantics.
2052 bool derivatives_explicitly_enabled_;
2053 bool frag_depth_explicitly_enabled_;
2054 bool draw_buffers_explicitly_enabled_;
2055 bool shader_texture_lod_explicitly_enabled_;
2057 bool compile_shader_always_succeeds_;
2059 // An optional behaviour to lose the context and group when OOM.
2060 bool lose_context_when_out_of_memory_;
2062 // Log extra info.
2063 bool service_logging_;
2065 #if defined(OS_MACOSX)
2066 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
2067 TextureToIOSurfaceMap texture_to_io_surface_map_;
2068 #endif
2070 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
2071 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
2073 // Cached values of the currently assigned viewport dimensions.
2074 GLsizei viewport_max_width_;
2075 GLsizei viewport_max_height_;
2077 // Command buffer stats.
2078 base::TimeDelta total_processing_commands_time_;
2080 // States related to each manager.
2081 DecoderTextureState texture_state_;
2082 DecoderFramebufferState framebuffer_state_;
2084 scoped_ptr<GPUTracer> gpu_tracer_;
2085 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
2086 const unsigned char* gpu_decoder_category_;
2087 int gpu_trace_level_;
2088 bool gpu_trace_commands_;
2089 bool gpu_debug_commands_;
2091 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
2093 // Used to validate multisample renderbuffers if needed
2094 GLuint validation_texture_;
2095 GLuint validation_fbo_multisample_;
2096 GLuint validation_fbo_;
2098 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
2099 uint32 immediate_data_size,
2100 const void* data);
2102 // A struct to hold info about each command.
2103 struct CommandInfo {
2104 CmdHandler cmd_handler;
2105 uint8 arg_flags; // How to handle the arguments for this command
2106 uint8 cmd_flags; // How to handle this command
2107 uint16 arg_count; // How many arguments are expected for this command.
2110 // A table of CommandInfo for all the commands.
2111 static const CommandInfo command_info[kNumCommands - kStartPoint];
2113 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
2116 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
2117 #define GLES2_CMD_OP(name) \
2119 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2120 cmds::name::cmd_flags, \
2121 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2123 , /* NOLINT */
2124 GLES2_COMMAND_LIST(GLES2_CMD_OP)
2125 #undef GLES2_CMD_OP
2128 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2129 const char* function_name, ErrorState* error_state)
2130 : function_name_(function_name),
2131 error_state_(error_state) {
2132 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
2135 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2136 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
2139 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
2140 TextureUnit& info = state->texture_units[0];
2141 GLuint last_id;
2142 scoped_refptr<TextureRef> texture_ref;
2143 switch (target) {
2144 case GL_TEXTURE_2D:
2145 texture_ref = info.bound_texture_2d;
2146 break;
2147 case GL_TEXTURE_CUBE_MAP:
2148 texture_ref = info.bound_texture_cube_map;
2149 break;
2150 case GL_TEXTURE_EXTERNAL_OES:
2151 texture_ref = info.bound_texture_external_oes;
2152 break;
2153 case GL_TEXTURE_RECTANGLE_ARB:
2154 texture_ref = info.bound_texture_rectangle_arb;
2155 break;
2156 default:
2157 NOTREACHED();
2158 break;
2160 if (texture_ref.get()) {
2161 last_id = texture_ref->service_id();
2162 } else {
2163 last_id = 0;
2166 glBindTexture(target, last_id);
2167 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2170 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2171 GLuint id,
2172 GLenum target)
2173 : state_(state),
2174 target_(target) {
2175 ScopedGLErrorSuppressor suppressor(
2176 "ScopedTextureBinder::ctor", state_->GetErrorState());
2178 // TODO(apatrick): Check if there are any other states that need to be reset
2179 // before binding a new texture.
2180 glActiveTexture(GL_TEXTURE0);
2181 glBindTexture(target, id);
2184 ScopedTextureBinder::~ScopedTextureBinder() {
2185 ScopedGLErrorSuppressor suppressor(
2186 "ScopedTextureBinder::dtor", state_->GetErrorState());
2187 RestoreCurrentTextureBindings(state_, target_);
2190 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2191 GLuint id)
2192 : state_(state) {
2193 ScopedGLErrorSuppressor suppressor(
2194 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2195 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2198 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2199 ScopedGLErrorSuppressor suppressor(
2200 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2201 state_->RestoreRenderbufferBindings();
2204 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2205 GLuint id)
2206 : decoder_(decoder) {
2207 ScopedGLErrorSuppressor suppressor(
2208 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2209 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2210 decoder->OnFboChanged();
2213 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2214 ScopedGLErrorSuppressor suppressor(
2215 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2216 decoder_->RestoreCurrentFramebufferBindings();
2219 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2220 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2221 : decoder_(decoder) {
2222 resolve_and_bind_ = (
2223 decoder_->offscreen_target_frame_buffer_.get() &&
2224 decoder_->IsOffscreenBufferMultisampled() &&
2225 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2226 enforce_internal_framebuffer));
2227 if (!resolve_and_bind_)
2228 return;
2230 ScopedGLErrorSuppressor suppressor(
2231 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2232 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2233 decoder_->offscreen_target_frame_buffer_->id());
2234 GLuint targetid;
2235 if (internal) {
2236 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2237 decoder_->offscreen_resolved_frame_buffer_.reset(
2238 new BackFramebuffer(decoder_));
2239 decoder_->offscreen_resolved_frame_buffer_->Create();
2240 decoder_->offscreen_resolved_color_texture_.reset(
2241 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2242 decoder_->offscreen_resolved_color_texture_->Create();
2244 DCHECK(decoder_->offscreen_saved_color_format_);
2245 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2246 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2247 false);
2248 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2249 decoder_->offscreen_resolved_color_texture_.get());
2250 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2251 GL_FRAMEBUFFER_COMPLETE) {
2252 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2253 << "because offscreen resolved FBO was incomplete.";
2254 return;
2257 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2258 } else {
2259 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2261 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2262 const int width = decoder_->offscreen_size_.width();
2263 const int height = decoder_->offscreen_size_.height();
2264 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2265 decoder->BlitFramebufferHelper(0,
2267 width,
2268 height,
2271 width,
2272 height,
2273 GL_COLOR_BUFFER_BIT,
2274 GL_NEAREST);
2275 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2278 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2279 if (!resolve_and_bind_)
2280 return;
2282 ScopedGLErrorSuppressor suppressor(
2283 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2284 decoder_->RestoreCurrentFramebufferBindings();
2285 if (decoder_->state_.enable_flags.scissor_test) {
2286 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2290 BackTexture::BackTexture(
2291 MemoryTracker* memory_tracker,
2292 ContextState* state)
2293 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2294 state_(state),
2295 bytes_allocated_(0),
2296 id_(0) {
2299 BackTexture::~BackTexture() {
2300 // This does not destroy the render texture because that would require that
2301 // the associated GL context was current. Just check that it was explicitly
2302 // destroyed.
2303 DCHECK_EQ(id_, 0u);
2306 void BackTexture::Create() {
2307 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2308 state_->GetErrorState());
2309 Destroy();
2310 glGenTextures(1, &id_);
2311 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2313 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2314 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2315 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2317 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2318 // never called on an offscreen context, no data will ever be uploaded to the
2319 // saved offscreen color texture (it is deferred until to when SwapBuffers
2320 // is called). My idea is that some nvidia drivers might have a bug where
2321 // deleting a texture that has never been populated might cause a
2322 // crash.
2323 glTexImage2D(
2324 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2326 bytes_allocated_ = 16u * 16u * 4u;
2327 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2330 bool BackTexture::AllocateStorage(
2331 const gfx::Size& size, GLenum format, bool zero) {
2332 DCHECK_NE(id_, 0u);
2333 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2334 state_->GetErrorState());
2335 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2336 uint32 image_size = 0;
2337 GLES2Util::ComputeImageDataSizes(
2338 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2339 NULL, NULL);
2341 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2342 return false;
2345 scoped_ptr<char[]> zero_data;
2346 if (zero) {
2347 zero_data.reset(new char[image_size]);
2348 memset(zero_data.get(), 0, image_size);
2351 glTexImage2D(GL_TEXTURE_2D,
2352 0, // mip level
2353 format,
2354 size.width(),
2355 size.height(),
2356 0, // border
2357 format,
2358 GL_UNSIGNED_BYTE,
2359 zero_data.get());
2361 size_ = size;
2363 bool success = glGetError() == GL_NO_ERROR;
2364 if (success) {
2365 memory_tracker_.TrackMemFree(bytes_allocated_);
2366 bytes_allocated_ = image_size;
2367 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2369 return success;
2372 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2373 DCHECK_NE(id_, 0u);
2374 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2375 state_->GetErrorState());
2376 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2377 glCopyTexImage2D(GL_TEXTURE_2D,
2378 0, // level
2379 format,
2380 0, 0,
2381 size.width(),
2382 size.height(),
2383 0); // border
2386 void BackTexture::Destroy() {
2387 if (id_ != 0) {
2388 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2389 state_->GetErrorState());
2390 glDeleteTextures(1, &id_);
2391 id_ = 0;
2393 memory_tracker_.TrackMemFree(bytes_allocated_);
2394 bytes_allocated_ = 0;
2397 void BackTexture::Invalidate() {
2398 id_ = 0;
2401 BackRenderbuffer::BackRenderbuffer(
2402 RenderbufferManager* renderbuffer_manager,
2403 MemoryTracker* memory_tracker,
2404 ContextState* state)
2405 : renderbuffer_manager_(renderbuffer_manager),
2406 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2407 state_(state),
2408 bytes_allocated_(0),
2409 id_(0) {
2412 BackRenderbuffer::~BackRenderbuffer() {
2413 // This does not destroy the render buffer because that would require that
2414 // the associated GL context was current. Just check that it was explicitly
2415 // destroyed.
2416 DCHECK_EQ(id_, 0u);
2419 void BackRenderbuffer::Create() {
2420 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2421 state_->GetErrorState());
2422 Destroy();
2423 glGenRenderbuffersEXT(1, &id_);
2426 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2427 const gfx::Size& size,
2428 GLenum format,
2429 GLsizei samples) {
2430 ScopedGLErrorSuppressor suppressor(
2431 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2432 ScopedRenderBufferBinder binder(state_, id_);
2434 uint32 estimated_size = 0;
2435 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2436 size.width(), size.height(), samples, format, &estimated_size)) {
2437 return false;
2440 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2441 return false;
2444 if (samples <= 1) {
2445 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2446 format,
2447 size.width(),
2448 size.height());
2449 } else {
2450 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2451 GL_RENDERBUFFER,
2452 samples,
2453 format,
2454 size.width(),
2455 size.height());
2457 bool success = glGetError() == GL_NO_ERROR;
2458 if (success) {
2459 // Mark the previously allocated bytes as free.
2460 memory_tracker_.TrackMemFree(bytes_allocated_);
2461 bytes_allocated_ = estimated_size;
2462 // Track the newly allocated bytes.
2463 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2465 return success;
2468 void BackRenderbuffer::Destroy() {
2469 if (id_ != 0) {
2470 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2471 state_->GetErrorState());
2472 glDeleteRenderbuffersEXT(1, &id_);
2473 id_ = 0;
2475 memory_tracker_.TrackMemFree(bytes_allocated_);
2476 bytes_allocated_ = 0;
2479 void BackRenderbuffer::Invalidate() {
2480 id_ = 0;
2483 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2484 : decoder_(decoder),
2485 id_(0) {
2488 BackFramebuffer::~BackFramebuffer() {
2489 // This does not destroy the frame buffer because that would require that
2490 // the associated GL context was current. Just check that it was explicitly
2491 // destroyed.
2492 DCHECK_EQ(id_, 0u);
2495 void BackFramebuffer::Create() {
2496 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2497 decoder_->GetErrorState());
2498 Destroy();
2499 glGenFramebuffersEXT(1, &id_);
2502 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2503 DCHECK_NE(id_, 0u);
2504 ScopedGLErrorSuppressor suppressor(
2505 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2506 ScopedFrameBufferBinder binder(decoder_, id_);
2507 GLuint attach_id = texture ? texture->id() : 0;
2508 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2509 GL_COLOR_ATTACHMENT0,
2510 GL_TEXTURE_2D,
2511 attach_id,
2515 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2516 BackRenderbuffer* render_buffer) {
2517 DCHECK_NE(id_, 0u);
2518 ScopedGLErrorSuppressor suppressor(
2519 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2520 ScopedFrameBufferBinder binder(decoder_, id_);
2521 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2522 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2523 target,
2524 GL_RENDERBUFFER,
2525 attach_id);
2528 void BackFramebuffer::Destroy() {
2529 if (id_ != 0) {
2530 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2531 decoder_->GetErrorState());
2532 glDeleteFramebuffersEXT(1, &id_);
2533 id_ = 0;
2537 void BackFramebuffer::Invalidate() {
2538 id_ = 0;
2541 GLenum BackFramebuffer::CheckStatus() {
2542 DCHECK_NE(id_, 0u);
2543 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2544 decoder_->GetErrorState());
2545 ScopedFrameBufferBinder binder(decoder_, id_);
2546 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2549 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2550 return new GLES2DecoderImpl(group);
2553 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2554 : GLES2Decoder(),
2555 group_(group),
2556 logger_(&debug_marker_manager_),
2557 state_(group_->feature_info(), this, &logger_),
2558 attrib_0_buffer_id_(0),
2559 attrib_0_buffer_matches_value_(true),
2560 attrib_0_size_(0),
2561 fixed_attrib_buffer_id_(0),
2562 fixed_attrib_buffer_size_(0),
2563 offscreen_target_color_format_(0),
2564 offscreen_target_depth_format_(0),
2565 offscreen_target_stencil_format_(0),
2566 offscreen_target_samples_(0),
2567 offscreen_target_buffer_preserved_(true),
2568 offscreen_saved_color_format_(0),
2569 back_buffer_color_format_(0),
2570 back_buffer_has_depth_(false),
2571 back_buffer_has_stencil_(false),
2572 back_buffer_read_buffer_(GL_BACK),
2573 back_buffer_draw_buffer_(GL_BACK),
2574 surfaceless_(false),
2575 backbuffer_needs_clear_bits_(0),
2576 current_decoder_error_(error::kNoError),
2577 validators_(group_->feature_info()->validators()),
2578 feature_info_(group_->feature_info()),
2579 frame_number_(0),
2580 has_robustness_extension_(false),
2581 context_lost_reason_(error::kUnknown),
2582 context_was_lost_(false),
2583 reset_by_robustness_extension_(false),
2584 supports_post_sub_buffer_(false),
2585 webgl_version_(0),
2586 derivatives_explicitly_enabled_(false),
2587 frag_depth_explicitly_enabled_(false),
2588 draw_buffers_explicitly_enabled_(false),
2589 shader_texture_lod_explicitly_enabled_(false),
2590 compile_shader_always_succeeds_(false),
2591 lose_context_when_out_of_memory_(false),
2592 service_logging_(base::CommandLine::InitializedForCurrentProcess()
2593 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2594 switches::kEnableGPUServiceLoggingGPU)
2595 : false),
2596 viewport_max_width_(0),
2597 viewport_max_height_(0),
2598 texture_state_(group_->feature_info()->workarounds()),
2599 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2600 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2601 gpu_trace_level_(2),
2602 gpu_trace_commands_(false),
2603 gpu_debug_commands_(false),
2604 validation_texture_(0),
2605 validation_fbo_multisample_(0),
2606 validation_fbo_(0) {
2607 DCHECK(group);
2610 GLES2DecoderImpl::~GLES2DecoderImpl() {
2613 bool GLES2DecoderImpl::Initialize(
2614 const scoped_refptr<gfx::GLSurface>& surface,
2615 const scoped_refptr<gfx::GLContext>& context,
2616 bool offscreen,
2617 const gfx::Size& offscreen_size,
2618 const DisallowedFeatures& disallowed_features,
2619 const std::vector<int32>& attribs) {
2620 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2621 DCHECK(context->IsCurrent(surface.get()));
2622 DCHECK(!context_.get());
2623 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2625 ContextCreationAttribHelper attrib_parser;
2626 if (!attrib_parser.Parse(attribs))
2627 return false;
2628 webgl_version_ = attrib_parser.webgl_version;
2630 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2632 set_initialized();
2633 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2635 if (base::CommandLine::InitializedForCurrentProcess()) {
2636 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2637 switches::kEnableGPUDebugging)) {
2638 set_debug(true);
2641 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2642 switches::kEnableGPUCommandLogging)) {
2643 set_log_commands(true);
2646 compile_shader_always_succeeds_ =
2647 base::CommandLine::ForCurrentProcess()->HasSwitch(
2648 switches::kCompileShaderAlwaysSucceeds);
2651 // Take ownership of the context and surface. The surface can be replaced with
2652 // SetSurface.
2653 context_ = context;
2654 surface_ = surface;
2656 // Create GPU Tracer for timing values.
2657 gpu_tracer_.reset(new GPUTracer(this));
2659 if (feature_info_->workarounds().disable_timestamp_queries) {
2660 // Forcing time elapsed query for any GPU Timing Client forces it for all
2661 // clients in the context.
2662 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2665 // Save the loseContextWhenOutOfMemory context creation attribute.
2666 lose_context_when_out_of_memory_ =
2667 attrib_parser.lose_context_when_out_of_memory;
2669 // If the failIfMajorPerformanceCaveat context creation attribute was true
2670 // and we are using a software renderer, fail.
2671 if (attrib_parser.fail_if_major_perf_caveat &&
2672 feature_info_->feature_flags().is_swiftshader) {
2673 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2674 Destroy(true);
2675 return false;
2678 disallowed_features_ = disallowed_features;
2679 if (webgl_version_ == 1) {
2680 disallowed_features_.npot_support = true;
2683 if (!group_->Initialize(this,
2684 ContextGroup::GetContextType(webgl_version_),
2685 disallowed_features_)) {
2686 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2687 Destroy(true);
2688 return false;
2690 CHECK_GL_ERROR();
2692 if (webgl_version_ == 2) {
2693 if (!feature_info_->IsES3Capable()) {
2694 LOG(ERROR) << "Underlying driver does not support ES3.";
2695 Destroy(true);
2696 return false;
2698 feature_info_->EnableES3Validators();
2699 set_unsafe_es3_apis_enabled(true);
2701 frag_depth_explicitly_enabled_ = true;
2702 draw_buffers_explicitly_enabled_ = true;
2703 // TODO(zmo): Look into shader_texture_lod_explicitly_enabled_ situation.
2706 state_.attrib_values.resize(group_->max_vertex_attribs());
2707 vertex_array_manager_.reset(new VertexArrayManager());
2709 GLuint default_vertex_attrib_service_id = 0;
2710 if (features().native_vertex_array_object) {
2711 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2712 glBindVertexArrayOES(default_vertex_attrib_service_id);
2715 state_.default_vertex_attrib_manager =
2716 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2718 state_.default_vertex_attrib_manager->Initialize(
2719 group_->max_vertex_attribs(),
2720 feature_info_->workarounds().init_vertex_attributes);
2722 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2723 DoBindVertexArrayOES(0);
2725 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2727 image_manager_.reset(new ImageManager);
2729 util_.set_num_compressed_texture_formats(
2730 validators_->compressed_texture_format.GetValues().size());
2732 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2733 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2734 // OpenGL ES 2.0 does not have this issue.
2735 glEnableVertexAttribArray(0);
2737 glGenBuffersARB(1, &attrib_0_buffer_id_);
2738 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2739 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2740 glBindBuffer(GL_ARRAY_BUFFER, 0);
2741 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2743 state_.texture_units.resize(group_->max_texture_units());
2744 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2745 glActiveTexture(GL_TEXTURE0 + tt);
2746 // We want the last bind to be 2D.
2747 TextureRef* ref;
2748 if (features().oes_egl_image_external) {
2749 ref = texture_manager()->GetDefaultTextureInfo(
2750 GL_TEXTURE_EXTERNAL_OES);
2751 state_.texture_units[tt].bound_texture_external_oes = ref;
2752 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2754 if (features().arb_texture_rectangle) {
2755 ref = texture_manager()->GetDefaultTextureInfo(
2756 GL_TEXTURE_RECTANGLE_ARB);
2757 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2758 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2760 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2761 state_.texture_units[tt].bound_texture_cube_map = ref;
2762 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2763 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2764 state_.texture_units[tt].bound_texture_2d = ref;
2765 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2767 glActiveTexture(GL_TEXTURE0);
2768 CHECK_GL_ERROR();
2770 // cache ALPHA_BITS result for re-use with clear behaviour
2771 GLint alpha_bits = 0;
2773 if (offscreen) {
2774 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2775 features().chromium_framebuffer_multisample) {
2776 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2777 // max_sample_count must be initialized to a sane value. If
2778 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2779 GLint max_sample_count = 1;
2780 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2781 offscreen_target_samples_ = std::min(attrib_parser.samples,
2782 max_sample_count);
2783 } else {
2784 offscreen_target_samples_ = 1;
2786 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2788 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2789 const bool rgb8_supported =
2790 context_->HasExtension("GL_OES_rgb8_rgba8");
2791 // The only available default render buffer formats in GLES2 have very
2792 // little precision. Don't enable multisampling unless 8-bit render
2793 // buffer formats are available--instead fall back to 8-bit textures.
2794 if (rgb8_supported && offscreen_target_samples_ > 1) {
2795 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2796 GL_RGBA8 : GL_RGB8;
2797 } else {
2798 offscreen_target_samples_ = 1;
2799 offscreen_target_color_format_ =
2800 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2801 ? GL_RGBA
2802 : GL_RGB;
2805 // ANGLE only supports packed depth/stencil formats, so use it if it is
2806 // available.
2807 const bool depth24_stencil8_supported =
2808 feature_info_->feature_flags().packed_depth24_stencil8;
2809 VLOG(1) << "GL_OES_packed_depth_stencil "
2810 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2811 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2812 depth24_stencil8_supported) {
2813 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2814 offscreen_target_stencil_format_ = 0;
2815 } else {
2816 // It may be the case that this depth/stencil combination is not
2817 // supported, but this will be checked later by CheckFramebufferStatus.
2818 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2819 GL_DEPTH_COMPONENT16 : 0;
2820 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2821 GL_STENCIL_INDEX8 : 0;
2823 } else {
2824 offscreen_target_color_format_ =
2825 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2826 ? GL_RGBA
2827 : GL_RGB;
2829 // If depth is requested at all, use the packed depth stencil format if
2830 // it's available, as some desktop GL drivers don't support any non-packed
2831 // formats for depth attachments.
2832 const bool depth24_stencil8_supported =
2833 feature_info_->feature_flags().packed_depth24_stencil8;
2834 VLOG(1) << "GL_EXT_packed_depth_stencil "
2835 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2837 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2838 depth24_stencil8_supported) {
2839 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2840 offscreen_target_stencil_format_ = 0;
2841 } else {
2842 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2843 GL_DEPTH_COMPONENT : 0;
2844 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2845 GL_STENCIL_INDEX : 0;
2849 offscreen_saved_color_format_ =
2850 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2851 ? GL_RGBA
2852 : GL_RGB;
2854 // Create the target frame buffer. This is the one that the client renders
2855 // directly to.
2856 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2857 offscreen_target_frame_buffer_->Create();
2858 // Due to GLES2 format limitations, either the color texture (for
2859 // non-multisampling) or the color render buffer (for multisampling) will be
2860 // attached to the offscreen frame buffer. The render buffer has more
2861 // limited formats available to it, but the texture can't do multisampling.
2862 if (IsOffscreenBufferMultisampled()) {
2863 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2864 renderbuffer_manager(), memory_tracker(), &state_));
2865 offscreen_target_color_render_buffer_->Create();
2866 } else {
2867 offscreen_target_color_texture_.reset(new BackTexture(
2868 memory_tracker(), &state_));
2869 offscreen_target_color_texture_->Create();
2871 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2872 renderbuffer_manager(), memory_tracker(), &state_));
2873 offscreen_target_depth_render_buffer_->Create();
2874 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2875 renderbuffer_manager(), memory_tracker(), &state_));
2876 offscreen_target_stencil_render_buffer_->Create();
2878 // Create the saved offscreen texture. The target frame buffer is copied
2879 // here when SwapBuffers is called.
2880 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2881 offscreen_saved_frame_buffer_->Create();
2883 offscreen_saved_color_texture_.reset(new BackTexture(
2884 memory_tracker(), &state_));
2885 offscreen_saved_color_texture_->Create();
2887 // Allocate the render buffers at their initial size and check the status
2888 // of the frame buffers is okay.
2889 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2890 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2891 Destroy(true);
2892 return false;
2895 state_.viewport_width = offscreen_size.width();
2896 state_.viewport_height = offscreen_size.height();
2898 // Allocate the offscreen saved color texture.
2899 DCHECK(offscreen_saved_color_format_);
2900 offscreen_saved_color_texture_->AllocateStorage(
2901 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2903 offscreen_saved_frame_buffer_->AttachRenderTexture(
2904 offscreen_saved_color_texture_.get());
2905 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2906 GL_FRAMEBUFFER_COMPLETE) {
2907 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2908 Destroy(true);
2909 return false;
2912 // Bind to the new default frame buffer (the offscreen target frame buffer).
2913 // This should now be associated with ID zero.
2914 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2915 } else {
2916 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2917 // These are NOT if the back buffer has these proprorties. They are
2918 // if we want the command buffer to enforce them regardless of what
2919 // the real backbuffer is assuming the real back buffer gives us more than
2920 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2921 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2922 // can't do anything about that.
2924 if (!surfaceless_) {
2925 GLint depth_bits = 0;
2926 GLint stencil_bits = 0;
2928 bool default_fb = (GetBackbufferServiceId() == 0);
2930 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2931 glGetFramebufferAttachmentParameterivEXT(
2932 GL_FRAMEBUFFER,
2933 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2934 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2935 glGetFramebufferAttachmentParameterivEXT(
2936 GL_FRAMEBUFFER,
2937 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2938 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2939 glGetFramebufferAttachmentParameterivEXT(
2940 GL_FRAMEBUFFER,
2941 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2942 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2943 } else {
2944 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2945 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2946 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2949 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2950 // the user requested RGB then RGB. If the user did not specify a
2951 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2952 back_buffer_color_format_ =
2953 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2954 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2955 back_buffer_has_stencil_ =
2956 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2959 state_.viewport_width = surface->GetSize().width();
2960 state_.viewport_height = surface->GetSize().height();
2963 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2964 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2965 // isn't well documented; it was discovered in the Khronos OpenGL ES
2966 // mailing list archives. It also implicitly enables the desktop GL
2967 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2968 // variable in fragment shaders.
2969 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2970 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2971 glEnable(GL_POINT_SPRITE);
2974 has_robustness_extension_ =
2975 context->HasExtension("GL_ARB_robustness") ||
2976 context->HasExtension("GL_KHR_robustness") ||
2977 context->HasExtension("GL_EXT_robustness");
2979 if (!InitializeShaderTranslator()) {
2980 return false;
2983 GLint viewport_params[4] = { 0 };
2984 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2985 viewport_max_width_ = viewport_params[0];
2986 viewport_max_height_ = viewport_params[1];
2988 state_.scissor_width = state_.viewport_width;
2989 state_.scissor_height = state_.viewport_height;
2991 // Set all the default state because some GL drivers get it wrong.
2992 state_.InitCapabilities(NULL);
2993 state_.InitState(NULL);
2994 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2996 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2997 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2998 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2999 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
3000 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
3002 bool call_gl_clear = !surfaceless_;
3003 #if defined(OS_ANDROID)
3004 // Temporary workaround for Android WebView because this clear ignores the
3005 // clip and corrupts that external UI of the App. Not calling glClear is ok
3006 // because the system already clears the buffer before each draw. Proper
3007 // fix might be setting the scissor clip properly before initialize. See
3008 // crbug.com/259023 for details.
3009 call_gl_clear = surface_->GetHandle();
3010 #endif
3011 if (call_gl_clear) {
3012 // On configs where we report no alpha, if the underlying surface has
3013 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
3014 bool clear_alpha = back_buffer_color_format_ == GL_RGB && alpha_bits > 0;
3015 if (clear_alpha) {
3016 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3019 // Clear the backbuffer.
3020 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3022 // Restore alpha clear value if we changed it.
3023 if (clear_alpha) {
3024 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3028 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
3029 if (feature_info_->workarounds()
3030 .disable_post_sub_buffers_for_onscreen_surfaces &&
3031 !surface->IsOffscreen())
3032 supports_post_sub_buffer_ = false;
3034 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
3035 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
3038 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
3039 context_->SetUnbindFboOnMakeCurrent();
3042 // Only compositor contexts are known to use only the subset of GL
3043 // that can be safely migrated between the iGPU and the dGPU. Mark
3044 // those contexts as safe to forcibly transition between the GPUs.
3045 // http://crbug.com/180876, http://crbug.com/227228
3046 if (!offscreen)
3047 context_->SetSafeToForceGpuSwitch();
3049 if (workarounds().gl_clear_broken) {
3050 DCHECK(!clear_framebuffer_blit_.get());
3051 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3052 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
3053 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
3054 return false;
3057 framebuffer_manager()->AddObserver(this);
3059 return true;
3062 Capabilities GLES2DecoderImpl::GetCapabilities() {
3063 DCHECK(initialized());
3064 Capabilities caps;
3065 caps.VisitPrecisions([](GLenum shader, GLenum type,
3066 Capabilities::ShaderPrecision* shader_precision) {
3067 GLint range[2] = {0, 0};
3068 GLint precision = 0;
3069 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
3070 shader_precision->min_range = range[0];
3071 shader_precision->max_range = range[1];
3072 shader_precision->precision = precision;
3074 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
3075 &caps.max_combined_texture_image_units);
3076 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
3077 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
3078 &caps.max_fragment_uniform_vectors);
3079 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
3080 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
3081 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
3082 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
3083 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
3084 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
3085 &caps.max_vertex_texture_image_units);
3086 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
3087 &caps.max_vertex_uniform_vectors);
3088 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
3089 &caps.num_compressed_texture_formats);
3090 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
3091 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
3092 &caps.bind_generates_resource_chromium);
3093 if (unsafe_es3_apis_enabled()) {
3094 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3095 // but for now we clamp them to 32-bit max.
3096 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
3097 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
3098 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
3099 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
3100 &caps.max_combined_fragment_uniform_components);
3101 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
3102 &caps.max_combined_uniform_blocks);
3103 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
3104 &caps.max_combined_vertex_uniform_components);
3105 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
3106 DoGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
3107 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
3108 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
3109 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
3110 &caps.max_fragment_input_components);
3111 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
3112 &caps.max_fragment_uniform_blocks);
3113 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
3114 &caps.max_fragment_uniform_components);
3115 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
3116 &caps.max_program_texel_offset);
3117 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
3118 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3119 // returned.
3120 if (caps.max_server_wait_timeout < 0)
3121 caps.max_server_wait_timeout = 0;
3122 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps.max_texture_lod_bias);
3123 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
3124 &caps.max_transform_feedback_interleaved_components);
3125 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
3126 &caps.max_transform_feedback_separate_attribs);
3127 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
3128 &caps.max_transform_feedback_separate_components);
3129 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
3130 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
3131 &caps.max_uniform_buffer_bindings);
3132 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
3133 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
3134 &caps.max_vertex_output_components);
3135 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
3136 &caps.max_vertex_uniform_blocks);
3137 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
3138 &caps.max_vertex_uniform_components);
3139 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
3140 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
3141 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
3142 &caps.num_program_binary_formats);
3143 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
3144 &caps.uniform_buffer_offset_alignment);
3145 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3146 caps.major_version = 3;
3147 caps.minor_version = 0;
3149 if (feature_info_->feature_flags().multisampled_render_to_texture ||
3150 feature_info_->feature_flags().chromium_framebuffer_multisample ||
3151 unsafe_es3_apis_enabled()) {
3152 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
3155 caps.egl_image_external =
3156 feature_info_->feature_flags().oes_egl_image_external;
3157 caps.texture_format_astc =
3158 feature_info_->feature_flags().ext_texture_format_astc;
3159 caps.texture_format_atc =
3160 feature_info_->feature_flags().ext_texture_format_atc;
3161 caps.texture_format_bgra8888 =
3162 feature_info_->feature_flags().ext_texture_format_bgra8888;
3163 caps.texture_format_dxt1 =
3164 feature_info_->feature_flags().ext_texture_format_dxt1;
3165 caps.texture_format_dxt5 =
3166 feature_info_->feature_flags().ext_texture_format_dxt5;
3167 caps.texture_format_etc1 =
3168 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
3169 caps.texture_format_etc1_npot =
3170 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
3171 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
3172 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
3173 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
3174 caps.discard_framebuffer =
3175 feature_info_->feature_flags().ext_discard_framebuffer;
3176 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3178 #if defined(OS_MACOSX)
3179 // This is unconditionally true on mac, no need to test for it at runtime.
3180 caps.iosurface = true;
3181 #endif
3183 caps.post_sub_buffer = supports_post_sub_buffer_;
3184 caps.image = true;
3185 caps.surfaceless = surfaceless_;
3187 caps.blend_equation_advanced =
3188 feature_info_->feature_flags().blend_equation_advanced;
3189 caps.blend_equation_advanced_coherent =
3190 feature_info_->feature_flags().blend_equation_advanced_coherent;
3191 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3192 caps.image_ycbcr_422 =
3193 feature_info_->feature_flags().chromium_image_ycbcr_422;
3194 caps.max_copy_texture_chromium_size =
3195 feature_info_->workarounds().max_copy_texture_chromium_size;
3196 caps.render_buffer_format_bgra8888 =
3197 feature_info_->feature_flags().ext_render_buffer_format_bgra8888;
3198 caps.occlusion_query_boolean =
3199 feature_info_->feature_flags().occlusion_query_boolean;
3200 caps.timer_queries =
3201 query_manager_->GPUTimingAvailable();
3202 return caps;
3205 void GLES2DecoderImpl::UpdateCapabilities() {
3206 util_.set_num_compressed_texture_formats(
3207 validators_->compressed_texture_format.GetValues().size());
3208 util_.set_num_shader_binary_formats(
3209 validators_->shader_binary_format.GetValues().size());
3212 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3213 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3214 if (feature_info_->disable_shader_translator()) {
3215 return true;
3217 ShBuiltInResources resources;
3218 ShInitBuiltInResources(&resources);
3219 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3220 resources.MaxVertexUniformVectors =
3221 group_->max_vertex_uniform_vectors();
3222 resources.MaxVaryingVectors = group_->max_varying_vectors();
3223 resources.MaxVertexTextureImageUnits =
3224 group_->max_vertex_texture_image_units();
3225 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3226 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3227 resources.MaxFragmentUniformVectors =
3228 group_->max_fragment_uniform_vectors();
3229 resources.MaxDrawBuffers = group_->max_draw_buffers();
3230 resources.MaxExpressionComplexity = 256;
3231 resources.MaxCallStackDepth = 256;
3233 GLint range[2] = { 0, 0 };
3234 GLint precision = 0;
3235 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3236 range, &precision);
3237 resources.FragmentPrecisionHigh =
3238 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3240 if (IsWebGLContext()) {
3241 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3242 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3243 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3244 if (!draw_buffers_explicitly_enabled_)
3245 resources.MaxDrawBuffers = 1;
3246 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3247 resources.NV_draw_buffers =
3248 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3249 } else {
3250 resources.OES_standard_derivatives =
3251 features().oes_standard_derivatives ? 1 : 0;
3252 resources.ARB_texture_rectangle =
3253 features().arb_texture_rectangle ? 1 : 0;
3254 resources.OES_EGL_image_external =
3255 features().oes_egl_image_external ? 1 : 0;
3256 resources.EXT_draw_buffers =
3257 features().ext_draw_buffers ? 1 : 0;
3258 resources.EXT_frag_depth =
3259 features().ext_frag_depth ? 1 : 0;
3260 resources.EXT_shader_texture_lod =
3261 features().ext_shader_texture_lod ? 1 : 0;
3262 resources.NV_draw_buffers =
3263 features().nv_draw_buffers ? 1 : 0;
3266 ShShaderSpec shader_spec;
3267 if (IsWebGLContext()) {
3268 shader_spec = webgl_version_ == 2 ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3269 } else {
3270 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3273 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3274 features().enable_shader_name_hashing)
3275 resources.HashFunction = &CityHash64;
3276 else
3277 resources.HashFunction = NULL;
3279 int driver_bug_workarounds = 0;
3280 if (workarounds().needs_glsl_built_in_function_emulation)
3281 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3282 if (workarounds().init_gl_position_in_vertex_shader)
3283 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3284 if (workarounds().unfold_short_circuit_as_ternary_operation)
3285 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3286 if (workarounds().init_varyings_without_static_use)
3287 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3288 if (workarounds().unroll_for_loop_with_sampler_array_index)
3289 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3290 if (workarounds().scalarize_vec_and_mat_constructor_args)
3291 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3292 if (workarounds().regenerate_struct_names)
3293 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3294 if (workarounds().remove_pow_with_constant_exponent)
3295 driver_bug_workarounds |= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT;
3297 if (base::CommandLine::InitializedForCurrentProcess() &&
3298 base::CommandLine::ForCurrentProcess()->HasSwitch(
3299 switches::kEmulateShaderPrecision))
3300 resources.WEBGL_debug_shader_precision = true;
3302 ShShaderOutput shader_output_language =
3303 ShaderTranslator::GetShaderOutputLanguageForContext(
3304 feature_info_->gl_version_info());
3306 vertex_translator_ = shader_translator_cache()->GetTranslator(
3307 GL_VERTEX_SHADER, shader_spec, &resources, shader_output_language,
3308 static_cast<ShCompileOptions>(driver_bug_workarounds));
3309 if (!vertex_translator_.get()) {
3310 LOG(ERROR) << "Could not initialize vertex shader translator.";
3311 Destroy(true);
3312 return false;
3315 fragment_translator_ = shader_translator_cache()->GetTranslator(
3316 GL_FRAGMENT_SHADER, shader_spec, &resources, shader_output_language,
3317 static_cast<ShCompileOptions>(driver_bug_workarounds));
3318 if (!fragment_translator_.get()) {
3319 LOG(ERROR) << "Could not initialize fragment shader translator.";
3320 Destroy(true);
3321 return false;
3323 return true;
3326 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3327 for (GLsizei ii = 0; ii < n; ++ii) {
3328 if (GetBuffer(client_ids[ii])) {
3329 return false;
3332 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3333 glGenBuffersARB(n, service_ids.get());
3334 for (GLsizei ii = 0; ii < n; ++ii) {
3335 CreateBuffer(client_ids[ii], service_ids[ii]);
3337 return true;
3340 bool GLES2DecoderImpl::GenFramebuffersHelper(
3341 GLsizei n, const GLuint* client_ids) {
3342 for (GLsizei ii = 0; ii < n; ++ii) {
3343 if (GetFramebuffer(client_ids[ii])) {
3344 return false;
3347 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3348 glGenFramebuffersEXT(n, service_ids.get());
3349 for (GLsizei ii = 0; ii < n; ++ii) {
3350 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3352 return true;
3355 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3356 GLsizei n, const GLuint* client_ids) {
3357 for (GLsizei ii = 0; ii < n; ++ii) {
3358 if (GetRenderbuffer(client_ids[ii])) {
3359 return false;
3362 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3363 glGenRenderbuffersEXT(n, service_ids.get());
3364 for (GLsizei ii = 0; ii < n; ++ii) {
3365 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3367 return true;
3370 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3371 const GLuint* client_ids) {
3372 for (GLsizei ii = 0; ii < n; ++ii) {
3373 if (GetValuebuffer(client_ids[ii])) {
3374 return false;
3377 for (GLsizei ii = 0; ii < n; ++ii) {
3378 CreateValuebuffer(client_ids[ii]);
3380 return true;
3383 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3384 for (GLsizei ii = 0; ii < n; ++ii) {
3385 if (GetTexture(client_ids[ii])) {
3386 return false;
3389 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3390 glGenTextures(n, service_ids.get());
3391 for (GLsizei ii = 0; ii < n; ++ii) {
3392 CreateTexture(client_ids[ii], service_ids[ii]);
3394 return true;
3397 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id,
3398 GLsizei range) {
3399 GLuint last_client_id;
3400 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3401 return false;
3403 if (path_manager()->HasPathsInRange(first_client_id, last_client_id))
3404 return false;
3406 GLuint first_service_id = glGenPathsNV(range);
3407 if (first_service_id == 0) {
3408 // We have to fail the connection here, because client has already
3409 // succeeded in allocating the ids. This happens if we allocate
3410 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3411 // example).
3412 return false;
3414 // GenPathsNV does not wrap.
3415 DCHECK(first_service_id + range - 1 >= first_service_id);
3417 path_manager()->CreatePathRange(first_client_id, last_client_id,
3418 first_service_id);
3420 return true;
3423 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id,
3424 GLsizei range) {
3425 GLuint last_client_id;
3426 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3427 return false;
3429 path_manager()->RemovePaths(first_client_id, last_client_id);
3430 return true;
3433 void GLES2DecoderImpl::DeleteBuffersHelper(
3434 GLsizei n, const GLuint* client_ids) {
3435 for (GLsizei ii = 0; ii < n; ++ii) {
3436 Buffer* buffer = GetBuffer(client_ids[ii]);
3437 if (buffer && !buffer->IsDeleted()) {
3438 buffer->RemoveMappedRange();
3439 state_.RemoveBoundBuffer(buffer);
3440 RemoveBuffer(client_ids[ii]);
3445 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3446 GLsizei n, const GLuint* client_ids) {
3447 bool supports_separate_framebuffer_binds =
3448 features().chromium_framebuffer_multisample;
3450 for (GLsizei ii = 0; ii < n; ++ii) {
3451 Framebuffer* framebuffer =
3452 GetFramebuffer(client_ids[ii]);
3453 if (framebuffer && !framebuffer->IsDeleted()) {
3454 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3455 GLenum target = supports_separate_framebuffer_binds ?
3456 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3458 // Unbind attachments on FBO before deletion.
3459 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3460 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3462 glBindFramebufferEXT(target, GetBackbufferServiceId());
3463 framebuffer_state_.bound_draw_framebuffer = NULL;
3464 framebuffer_state_.clear_state_dirty = true;
3466 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3467 framebuffer_state_.bound_read_framebuffer = NULL;
3468 GLenum target = supports_separate_framebuffer_binds ?
3469 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3470 glBindFramebufferEXT(target, GetBackbufferServiceId());
3472 OnFboChanged();
3473 RemoveFramebuffer(client_ids[ii]);
3478 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3479 GLsizei n, const GLuint* client_ids) {
3480 bool supports_separate_framebuffer_binds =
3481 features().chromium_framebuffer_multisample;
3482 for (GLsizei ii = 0; ii < n; ++ii) {
3483 Renderbuffer* renderbuffer =
3484 GetRenderbuffer(client_ids[ii]);
3485 if (renderbuffer && !renderbuffer->IsDeleted()) {
3486 if (state_.bound_renderbuffer.get() == renderbuffer) {
3487 state_.bound_renderbuffer = NULL;
3489 // Unbind from current framebuffers.
3490 if (supports_separate_framebuffer_binds) {
3491 if (framebuffer_state_.bound_read_framebuffer.get()) {
3492 framebuffer_state_.bound_read_framebuffer
3493 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3495 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3496 framebuffer_state_.bound_draw_framebuffer
3497 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3499 } else {
3500 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3501 framebuffer_state_.bound_draw_framebuffer
3502 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3505 framebuffer_state_.clear_state_dirty = true;
3506 RemoveRenderbuffer(client_ids[ii]);
3511 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3512 GLsizei n,
3513 const GLuint* client_ids) {
3514 for (GLsizei ii = 0; ii < n; ++ii) {
3515 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3516 if (valuebuffer) {
3517 if (state_.bound_valuebuffer.get() == valuebuffer) {
3518 state_.bound_valuebuffer = NULL;
3520 RemoveValuebuffer(client_ids[ii]);
3525 void GLES2DecoderImpl::DeleteTexturesHelper(
3526 GLsizei n, const GLuint* client_ids) {
3527 bool supports_separate_framebuffer_binds =
3528 features().chromium_framebuffer_multisample;
3529 for (GLsizei ii = 0; ii < n; ++ii) {
3530 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3531 if (texture_ref) {
3532 Texture* texture = texture_ref->texture();
3533 if (texture->IsAttachedToFramebuffer()) {
3534 framebuffer_state_.clear_state_dirty = true;
3536 // Unbind texture_ref from texture_ref units.
3537 state_.UnbindTexture(texture_ref);
3539 // Unbind from current framebuffers.
3540 if (supports_separate_framebuffer_binds) {
3541 if (framebuffer_state_.bound_read_framebuffer.get()) {
3542 framebuffer_state_.bound_read_framebuffer
3543 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3545 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3546 framebuffer_state_.bound_draw_framebuffer
3547 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3549 } else {
3550 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3551 framebuffer_state_.bound_draw_framebuffer
3552 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3555 #if defined(OS_MACOSX)
3556 GLuint service_id = texture->service_id();
3557 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3558 ReleaseIOSurfaceForTexture(service_id);
3560 #endif
3561 RemoveTexture(client_ids[ii]);
3566 // } // anonymous namespace
3568 bool GLES2DecoderImpl::MakeCurrent() {
3569 if (!context_.get())
3570 return false;
3572 if (WasContextLost()) {
3573 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3574 return false;
3577 if (!context_->MakeCurrent(surface_.get())) {
3578 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3579 MarkContextLost(error::kMakeCurrentFailed);
3580 group_->LoseContexts(error::kUnknown);
3581 return false;
3584 if (CheckResetStatus()) {
3585 LOG(ERROR)
3586 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3587 group_->LoseContexts(error::kUnknown);
3588 return false;
3591 ProcessFinishedAsyncTransfers();
3593 // Rebind the FBO if it was unbound by the context.
3594 if (workarounds().unbind_fbo_on_context_switch)
3595 RestoreFramebufferBindings();
3597 framebuffer_state_.clear_state_dirty = true;
3599 return true;
3602 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3603 ProcessPendingReadPixels(false);
3604 if (engine() && query_manager_.get())
3605 query_manager_->ProcessPendingTransferQueries();
3608 static void RebindCurrentFramebuffer(
3609 GLenum target,
3610 Framebuffer* framebuffer,
3611 GLuint back_buffer_service_id) {
3612 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3614 if (framebuffer_id == 0) {
3615 framebuffer_id = back_buffer_service_id;
3618 glBindFramebufferEXT(target, framebuffer_id);
3621 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3622 framebuffer_state_.clear_state_dirty = true;
3624 if (!features().chromium_framebuffer_multisample) {
3625 RebindCurrentFramebuffer(
3626 GL_FRAMEBUFFER,
3627 framebuffer_state_.bound_draw_framebuffer.get(),
3628 GetBackbufferServiceId());
3629 } else {
3630 RebindCurrentFramebuffer(
3631 GL_READ_FRAMEBUFFER_EXT,
3632 framebuffer_state_.bound_read_framebuffer.get(),
3633 GetBackbufferServiceId());
3634 RebindCurrentFramebuffer(
3635 GL_DRAW_FRAMEBUFFER_EXT,
3636 framebuffer_state_.bound_draw_framebuffer.get(),
3637 GetBackbufferServiceId());
3639 OnFboChanged();
3642 bool GLES2DecoderImpl::CheckFramebufferValid(
3643 Framebuffer* framebuffer,
3644 GLenum target, const char* func_name) {
3645 if (!framebuffer) {
3646 if (surfaceless_)
3647 return false;
3648 if (backbuffer_needs_clear_bits_) {
3649 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3650 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3651 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3652 glClearStencil(0);
3653 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3654 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3655 glClearDepth(1.0f);
3656 state_.SetDeviceDepthMask(GL_TRUE);
3657 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3658 bool reset_draw_buffer = false;
3659 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3660 back_buffer_draw_buffer_ == GL_NONE) {
3661 reset_draw_buffer = true;
3662 GLenum buf = GL_BACK;
3663 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3664 buf = GL_COLOR_ATTACHMENT0;
3665 glDrawBuffersARB(1, &buf);
3667 glClear(backbuffer_needs_clear_bits_);
3668 if (reset_draw_buffer) {
3669 GLenum buf = GL_NONE;
3670 glDrawBuffersARB(1, &buf);
3672 backbuffer_needs_clear_bits_ = 0;
3673 RestoreClearState();
3675 return true;
3678 if (framebuffer_manager()->IsComplete(framebuffer)) {
3679 return true;
3682 GLenum completeness = framebuffer->IsPossiblyComplete();
3683 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3684 LOCAL_SET_GL_ERROR(
3685 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3686 return false;
3689 // Are all the attachments cleared?
3690 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3691 texture_manager()->HaveUnclearedMips()) {
3692 if (!framebuffer->IsCleared()) {
3693 // Can we clear them?
3694 if (framebuffer->GetStatus(texture_manager(), target) !=
3695 GL_FRAMEBUFFER_COMPLETE) {
3696 LOCAL_SET_GL_ERROR(
3697 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3698 "framebuffer incomplete (clear)");
3699 return false;
3701 ClearUnclearedAttachments(target, framebuffer);
3705 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3706 if (framebuffer->GetStatus(texture_manager(), target) !=
3707 GL_FRAMEBUFFER_COMPLETE) {
3708 LOCAL_SET_GL_ERROR(
3709 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3710 "framebuffer incomplete (check)");
3711 return false;
3713 framebuffer_manager()->MarkAsComplete(framebuffer);
3716 // NOTE: At this point we don't know if the framebuffer is complete but
3717 // we DO know that everything that needs to be cleared has been cleared.
3718 return true;
3721 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3722 if (!features().chromium_framebuffer_multisample) {
3723 bool valid = CheckFramebufferValid(
3724 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3725 func_name);
3727 if (valid)
3728 OnUseFramebuffer();
3730 return valid;
3732 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3733 GL_DRAW_FRAMEBUFFER_EXT,
3734 func_name) &&
3735 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3736 GL_READ_FRAMEBUFFER_EXT,
3737 func_name);
3740 bool GLES2DecoderImpl::CheckBoundDrawFramebufferValid(const char* func_name) {
3741 Framebuffer* framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
3742 if (!framebuffer) {
3743 // Assume the default back buffer is always complete.
3744 return true;
3746 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3747 if (framebuffer->GetStatus(texture_manager(), GL_DRAW_FRAMEBUFFER) !=
3748 GL_FRAMEBUFFER_COMPLETE) {
3749 LOCAL_SET_GL_ERROR(
3750 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3751 "framebuffer incomplete (check)");
3752 return false;
3754 framebuffer_manager()->MarkAsComplete(framebuffer);
3756 return true;
3759 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3760 const char* func_name) {
3761 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3762 framebuffer_state_.bound_read_framebuffer.get() :
3763 framebuffer_state_.bound_draw_framebuffer.get();
3764 if (!framebuffer)
3765 return true;
3766 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3767 LOCAL_SET_GL_ERROR(
3768 GL_INVALID_OPERATION, func_name, "no color image attached");
3769 return false;
3771 return true;
3774 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3775 TextureRef* texture, GLint level) {
3776 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3777 framebuffer_state_.bound_read_framebuffer.get() :
3778 framebuffer_state_.bound_draw_framebuffer.get();
3779 if (!framebuffer)
3780 return false;
3781 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3782 GL_COLOR_ATTACHMENT0);
3783 if (!attachment)
3784 return false;
3785 return attachment->FormsFeedbackLoop(texture, level);
3788 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3789 Framebuffer* framebuffer =
3790 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3791 if (framebuffer != NULL) {
3792 const Framebuffer::Attachment* attachment =
3793 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3794 if (attachment) {
3795 return gfx::Size(attachment->width(), attachment->height());
3797 return gfx::Size(0, 0);
3798 } else if (offscreen_target_frame_buffer_.get()) {
3799 return offscreen_size_;
3800 } else {
3801 return surface_->GetSize();
3805 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3806 Framebuffer* framebuffer =
3807 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3808 if (framebuffer) {
3809 return framebuffer->GetReadBufferTextureType();
3810 } else { // Back buffer.
3811 if (back_buffer_read_buffer_ == GL_NONE)
3812 return 0;
3813 return GL_UNSIGNED_BYTE;
3817 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3818 Framebuffer* framebuffer =
3819 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3820 if (framebuffer) {
3821 return framebuffer->GetReadBufferInternalFormat();
3822 } else { // Back buffer.
3823 if (back_buffer_read_buffer_ == GL_NONE)
3824 return 0;
3825 if (offscreen_target_frame_buffer_.get()) {
3826 return offscreen_target_color_format_;
3828 return back_buffer_color_format_;
3832 GLenum GLES2DecoderImpl::GetBoundColorDrawBufferInternalFormat(
3833 GLint drawbuffer_i) {
3834 DCHECK(drawbuffer_i >= 0 &&
3835 drawbuffer_i < static_cast<GLint>(group_->max_draw_buffers()));
3836 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3837 if (!framebuffer) {
3838 return 0;
3840 GLenum drawbuffer = static_cast<GLenum>(GL_DRAW_BUFFER0 + drawbuffer_i);
3841 if (framebuffer->GetDrawBuffer(drawbuffer) == GL_NONE) {
3842 return 0;
3844 GLenum attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + drawbuffer_i);
3845 const Framebuffer::Attachment* buffer =
3846 framebuffer->GetAttachment(attachment);
3847 if (!buffer) {
3848 return 0;
3850 return buffer->internal_format();
3853 void GLES2DecoderImpl::MarkDrawBufferAsCleared(
3854 GLenum buffer, GLint drawbuffer_i) {
3855 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3856 if (!framebuffer)
3857 return;
3858 GLenum attachment = 0;
3859 switch (buffer) {
3860 case GL_COLOR:
3861 DCHECK(drawbuffer_i >= 0 &&
3862 drawbuffer_i < static_cast<GLint>(group_->max_draw_buffers()));
3863 attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + drawbuffer_i);
3864 break;
3865 case GL_DEPTH:
3866 attachment = GL_DEPTH;
3867 break;
3868 case GL_STENCIL:
3869 attachment = GL_STENCIL;
3870 break;
3871 default:
3872 // Caller is responsible for breaking GL_DEPTH_STENCIL into GL_DEPTH and
3873 // GL_STENCIL.
3874 NOTREACHED();
3876 framebuffer->MarkAttachmentAsCleared(
3877 renderbuffer_manager(), texture_manager(), attachment, true);
3880 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3881 if (!offscreen_saved_color_texture_info_.get())
3882 return;
3883 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3884 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3885 texture_manager()->SetLevelInfo(
3886 offscreen_saved_color_texture_info_.get(), GL_TEXTURE_2D,
3887 0, // level
3888 GL_RGBA, offscreen_size_.width(), offscreen_size_.height(),
3889 1, // depth
3890 0, // border
3891 GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(offscreen_size_));
3892 texture_manager()->SetParameteri(
3893 "UpdateParentTextureInfo",
3894 GetErrorState(),
3895 offscreen_saved_color_texture_info_.get(),
3896 GL_TEXTURE_MAG_FILTER,
3897 GL_LINEAR);
3898 texture_manager()->SetParameteri(
3899 "UpdateParentTextureInfo",
3900 GetErrorState(),
3901 offscreen_saved_color_texture_info_.get(),
3902 GL_TEXTURE_MIN_FILTER,
3903 GL_LINEAR);
3904 texture_manager()->SetParameteri(
3905 "UpdateParentTextureInfo",
3906 GetErrorState(),
3907 offscreen_saved_color_texture_info_.get(),
3908 GL_TEXTURE_WRAP_S,
3909 GL_CLAMP_TO_EDGE);
3910 texture_manager()->SetParameteri(
3911 "UpdateParentTextureInfo",
3912 GetErrorState(),
3913 offscreen_saved_color_texture_info_.get(),
3914 GL_TEXTURE_WRAP_T,
3915 GL_CLAMP_TO_EDGE);
3916 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3917 &state_, target);
3918 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3921 void GLES2DecoderImpl::SetResizeCallback(
3922 const base::Callback<void(gfx::Size, float)>& callback) {
3923 resize_callback_ = callback;
3926 Logger* GLES2DecoderImpl::GetLogger() {
3927 return &logger_;
3930 void GLES2DecoderImpl::BeginDecoding() {
3931 gpu_tracer_->BeginDecoding();
3932 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3933 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_;
3934 query_manager_->ProcessFrameBeginUpdates();
3937 void GLES2DecoderImpl::EndDecoding() {
3938 gpu_tracer_->EndDecoding();
3941 ErrorState* GLES2DecoderImpl::GetErrorState() {
3942 return state_.GetErrorState();
3945 void GLES2DecoderImpl::SetShaderCacheCallback(
3946 const ShaderCacheCallback& callback) {
3947 shader_cache_callback_ = callback;
3950 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3951 const WaitSyncPointCallback& callback) {
3952 wait_sync_point_callback_ = callback;
3955 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3956 uint32* service_texture_id) {
3957 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3958 if (texture_ref) {
3959 *service_texture_id = texture_ref->service_id();
3960 return true;
3962 return false;
3965 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3966 return texture_state_.texture_upload_count;
3969 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3970 return texture_state_.total_texture_upload_time;
3973 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3974 return total_processing_commands_time_;
3977 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3978 total_processing_commands_time_ += time;
3981 void GLES2DecoderImpl::Destroy(bool have_context) {
3982 if (!initialized())
3983 return;
3985 DCHECK(!have_context || context_->IsCurrent(NULL));
3987 // Unbind everything.
3988 state_.vertex_attrib_manager = NULL;
3989 state_.default_vertex_attrib_manager = NULL;
3990 state_.texture_units.clear();
3991 state_.bound_array_buffer = NULL;
3992 state_.bound_copy_read_buffer = NULL;
3993 state_.bound_copy_write_buffer = NULL;
3994 state_.bound_pixel_pack_buffer = NULL;
3995 state_.bound_pixel_unpack_buffer = NULL;
3996 state_.bound_transform_feedback_buffer = NULL;
3997 state_.bound_uniform_buffer = NULL;
3998 framebuffer_state_.bound_read_framebuffer = NULL;
3999 framebuffer_state_.bound_draw_framebuffer = NULL;
4000 state_.bound_renderbuffer = NULL;
4001 state_.bound_valuebuffer = NULL;
4003 if (offscreen_saved_color_texture_info_.get()) {
4004 DCHECK(offscreen_target_color_texture_);
4005 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
4006 offscreen_saved_color_texture_->id());
4007 offscreen_saved_color_texture_->Invalidate();
4008 offscreen_saved_color_texture_info_ = NULL;
4010 if (have_context) {
4011 if (copy_texture_CHROMIUM_.get()) {
4012 copy_texture_CHROMIUM_->Destroy();
4013 copy_texture_CHROMIUM_.reset();
4016 clear_framebuffer_blit_.reset();
4018 if (state_.current_program.get()) {
4019 program_manager()->UnuseProgram(shader_manager(),
4020 state_.current_program.get());
4023 if (attrib_0_buffer_id_) {
4024 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
4026 if (fixed_attrib_buffer_id_) {
4027 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
4030 if (validation_texture_) {
4031 glDeleteTextures(1, &validation_texture_);
4032 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
4033 glDeleteFramebuffersEXT(1, &validation_fbo_);
4036 if (offscreen_target_frame_buffer_.get())
4037 offscreen_target_frame_buffer_->Destroy();
4038 if (offscreen_target_color_texture_.get())
4039 offscreen_target_color_texture_->Destroy();
4040 if (offscreen_target_color_render_buffer_.get())
4041 offscreen_target_color_render_buffer_->Destroy();
4042 if (offscreen_target_depth_render_buffer_.get())
4043 offscreen_target_depth_render_buffer_->Destroy();
4044 if (offscreen_target_stencil_render_buffer_.get())
4045 offscreen_target_stencil_render_buffer_->Destroy();
4046 if (offscreen_saved_frame_buffer_.get())
4047 offscreen_saved_frame_buffer_->Destroy();
4048 if (offscreen_saved_color_texture_.get())
4049 offscreen_saved_color_texture_->Destroy();
4050 if (offscreen_resolved_frame_buffer_.get())
4051 offscreen_resolved_frame_buffer_->Destroy();
4052 if (offscreen_resolved_color_texture_.get())
4053 offscreen_resolved_color_texture_->Destroy();
4054 } else {
4055 if (offscreen_target_frame_buffer_.get())
4056 offscreen_target_frame_buffer_->Invalidate();
4057 if (offscreen_target_color_texture_.get())
4058 offscreen_target_color_texture_->Invalidate();
4059 if (offscreen_target_color_render_buffer_.get())
4060 offscreen_target_color_render_buffer_->Invalidate();
4061 if (offscreen_target_depth_render_buffer_.get())
4062 offscreen_target_depth_render_buffer_->Invalidate();
4063 if (offscreen_target_stencil_render_buffer_.get())
4064 offscreen_target_stencil_render_buffer_->Invalidate();
4065 if (offscreen_saved_frame_buffer_.get())
4066 offscreen_saved_frame_buffer_->Invalidate();
4067 if (offscreen_saved_color_texture_.get())
4068 offscreen_saved_color_texture_->Invalidate();
4069 if (offscreen_resolved_frame_buffer_.get())
4070 offscreen_resolved_frame_buffer_->Invalidate();
4071 if (offscreen_resolved_color_texture_.get())
4072 offscreen_resolved_color_texture_->Invalidate();
4075 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4076 // Otherwise, we can leak objects. http://crbug.com/258772.
4077 // state_.current_program must be reset before group_ is reset because
4078 // the later deletes the ProgramManager object that referred by
4079 // state_.current_program object.
4080 state_.current_program = NULL;
4082 copy_texture_CHROMIUM_.reset();
4083 clear_framebuffer_blit_.reset();
4085 if (query_manager_.get()) {
4086 query_manager_->Destroy(have_context);
4087 query_manager_.reset();
4090 if (vertex_array_manager_ .get()) {
4091 vertex_array_manager_->Destroy(have_context);
4092 vertex_array_manager_.reset();
4095 if (image_manager_.get()) {
4096 image_manager_->Destroy(have_context);
4097 image_manager_.reset();
4100 offscreen_target_frame_buffer_.reset();
4101 offscreen_target_color_texture_.reset();
4102 offscreen_target_color_render_buffer_.reset();
4103 offscreen_target_depth_render_buffer_.reset();
4104 offscreen_target_stencil_render_buffer_.reset();
4105 offscreen_saved_frame_buffer_.reset();
4106 offscreen_saved_color_texture_.reset();
4107 offscreen_resolved_frame_buffer_.reset();
4108 offscreen_resolved_color_texture_.reset();
4110 // Need to release these before releasing |group_| which may own the
4111 // ShaderTranslatorCache.
4112 fragment_translator_ = NULL;
4113 vertex_translator_ = NULL;
4115 // Destroy the GPU Tracer which may own some in process GPU Timings.
4116 if (gpu_tracer_) {
4117 gpu_tracer_->Destroy(have_context);
4118 gpu_tracer_.reset();
4121 if (group_.get()) {
4122 framebuffer_manager()->RemoveObserver(this);
4123 group_->Destroy(this, have_context);
4124 group_ = NULL;
4127 if (context_.get()) {
4128 context_->ReleaseCurrent(NULL);
4129 context_ = NULL;
4132 #if defined(OS_MACOSX)
4133 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
4134 it != texture_to_io_surface_map_.end(); ++it) {
4135 CFRelease(it->second);
4137 texture_to_io_surface_map_.clear();
4138 #endif
4141 void GLES2DecoderImpl::SetSurface(
4142 const scoped_refptr<gfx::GLSurface>& surface) {
4143 DCHECK(context_->IsCurrent(NULL));
4144 DCHECK(surface_.get());
4145 surface_ = surface;
4146 RestoreCurrentFramebufferBindings();
4149 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
4150 if (!offscreen_saved_color_texture_.get()) {
4151 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
4152 return;
4154 if (!offscreen_saved_color_texture_info_.get()) {
4155 GLuint service_id = offscreen_saved_color_texture_->id();
4156 offscreen_saved_color_texture_info_ = TextureRef::Create(
4157 texture_manager(), 0, service_id);
4158 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
4159 GL_TEXTURE_2D);
4160 UpdateParentTextureInfo();
4162 mailbox_manager()->ProduceTexture(
4163 mailbox, offscreen_saved_color_texture_info_->texture());
4166 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
4167 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4168 if (!is_offscreen) {
4169 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4170 << " with an onscreen framebuffer.";
4171 return false;
4174 if (offscreen_size_ == size)
4175 return true;
4177 offscreen_size_ = size;
4178 int w = offscreen_size_.width();
4179 int h = offscreen_size_.height();
4180 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
4181 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4182 << "to allocate storage due to excessive dimensions.";
4183 return false;
4186 // Reallocate the offscreen target buffers.
4187 DCHECK(offscreen_target_color_format_);
4188 if (IsOffscreenBufferMultisampled()) {
4189 if (!offscreen_target_color_render_buffer_->AllocateStorage(
4190 feature_info_.get(),
4191 offscreen_size_,
4192 offscreen_target_color_format_,
4193 offscreen_target_samples_)) {
4194 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4195 << "to allocate storage for offscreen target color buffer.";
4196 return false;
4198 } else {
4199 if (!offscreen_target_color_texture_->AllocateStorage(
4200 offscreen_size_, offscreen_target_color_format_, false)) {
4201 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4202 << "to allocate storage for offscreen target color texture.";
4203 return false;
4206 if (offscreen_target_depth_format_ &&
4207 !offscreen_target_depth_render_buffer_->AllocateStorage(
4208 feature_info_.get(),
4209 offscreen_size_,
4210 offscreen_target_depth_format_,
4211 offscreen_target_samples_)) {
4212 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4213 << "to allocate storage for offscreen target depth buffer.";
4214 return false;
4216 if (offscreen_target_stencil_format_ &&
4217 !offscreen_target_stencil_render_buffer_->AllocateStorage(
4218 feature_info_.get(),
4219 offscreen_size_,
4220 offscreen_target_stencil_format_,
4221 offscreen_target_samples_)) {
4222 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4223 << "to allocate storage for offscreen target stencil buffer.";
4224 return false;
4227 // Attach the offscreen target buffers to the target frame buffer.
4228 if (IsOffscreenBufferMultisampled()) {
4229 offscreen_target_frame_buffer_->AttachRenderBuffer(
4230 GL_COLOR_ATTACHMENT0,
4231 offscreen_target_color_render_buffer_.get());
4232 } else {
4233 offscreen_target_frame_buffer_->AttachRenderTexture(
4234 offscreen_target_color_texture_.get());
4236 if (offscreen_target_depth_format_) {
4237 offscreen_target_frame_buffer_->AttachRenderBuffer(
4238 GL_DEPTH_ATTACHMENT,
4239 offscreen_target_depth_render_buffer_.get());
4241 const bool packed_depth_stencil =
4242 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4243 if (packed_depth_stencil) {
4244 offscreen_target_frame_buffer_->AttachRenderBuffer(
4245 GL_STENCIL_ATTACHMENT,
4246 offscreen_target_depth_render_buffer_.get());
4247 } else if (offscreen_target_stencil_format_) {
4248 offscreen_target_frame_buffer_->AttachRenderBuffer(
4249 GL_STENCIL_ATTACHMENT,
4250 offscreen_target_stencil_render_buffer_.get());
4253 if (offscreen_target_frame_buffer_->CheckStatus() !=
4254 GL_FRAMEBUFFER_COMPLETE) {
4255 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4256 << "because offscreen FBO was incomplete.";
4257 return false;
4260 // Clear the target frame buffer.
4262 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4263 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f);
4264 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4265 glClearStencil(0);
4266 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4267 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4268 glClearDepth(0);
4269 state_.SetDeviceDepthMask(GL_TRUE);
4270 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4271 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4272 RestoreClearState();
4275 // Destroy the offscreen resolved framebuffers.
4276 if (offscreen_resolved_frame_buffer_.get())
4277 offscreen_resolved_frame_buffer_->Destroy();
4278 if (offscreen_resolved_color_texture_.get())
4279 offscreen_resolved_color_texture_->Destroy();
4280 offscreen_resolved_color_texture_.reset();
4281 offscreen_resolved_frame_buffer_.reset();
4283 return true;
4286 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4287 const void* cmd_data) {
4288 const gles2::cmds::ResizeCHROMIUM& c =
4289 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4290 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4291 return error::kDeferCommandUntilLater;
4293 GLuint width = static_cast<GLuint>(c.width);
4294 GLuint height = static_cast<GLuint>(c.height);
4295 GLfloat scale_factor = c.scale_factor;
4296 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4298 width = std::max(1U, width);
4299 height = std::max(1U, height);
4301 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4302 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4303 // Make sure that we are done drawing to the back buffer before resizing.
4304 glFinish();
4305 #endif
4306 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4307 if (is_offscreen) {
4308 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4309 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4310 << "ResizeOffscreenFrameBuffer failed.";
4311 return error::kLostContext;
4315 if (!resize_callback_.is_null()) {
4316 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4317 DCHECK(context_->IsCurrent(surface_.get()));
4318 if (!context_->IsCurrent(surface_.get())) {
4319 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4320 << "current after resize callback.";
4321 return error::kLostContext;
4325 return error::kNoError;
4328 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4329 if (command_id > kStartPoint && command_id < kNumCommands) {
4330 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4332 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4335 // Decode a command, and call the corresponding GL functions.
4336 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4337 // of commands at once, and is now only used for tests that need to track
4338 // individual commands.
4339 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4340 unsigned int arg_count,
4341 const void* cmd_data) {
4342 return DoCommands(1, cmd_data, arg_count + 1, 0);
4345 // Decode multiple commands, and call the corresponding GL functions.
4346 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4347 // changed by a (malicious) client at any time, so if validation has to happen,
4348 // it should operate on a copy of them.
4349 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4350 // interest of performance in this critical execution loop.
4351 template <bool DebugImpl>
4352 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4353 const void* buffer,
4354 int num_entries,
4355 int* entries_processed) {
4356 commands_to_process_ = num_commands;
4357 error::Error result = error::kNoError;
4358 const CommandBufferEntry* cmd_data =
4359 static_cast<const CommandBufferEntry*>(buffer);
4360 int process_pos = 0;
4361 unsigned int command = 0;
4363 while (process_pos < num_entries && result == error::kNoError &&
4364 commands_to_process_--) {
4365 const unsigned int size = cmd_data->value_header.size;
4366 command = cmd_data->value_header.command;
4368 if (size == 0) {
4369 result = error::kInvalidSize;
4370 break;
4373 if (static_cast<int>(size) + process_pos > num_entries) {
4374 result = error::kOutOfBounds;
4375 break;
4378 if (DebugImpl && log_commands()) {
4379 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4380 << "cmd: " << GetCommandName(command);
4383 const unsigned int arg_count = size - 1;
4384 unsigned int command_index = command - kStartPoint - 1;
4385 if (command_index < arraysize(command_info)) {
4386 const CommandInfo& info = command_info[command_index];
4387 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4388 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4389 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4390 bool doing_gpu_trace = false;
4391 if (DebugImpl && gpu_trace_commands_) {
4392 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4393 doing_gpu_trace = true;
4394 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4395 GetCommandName(command),
4396 kTraceDecoder);
4400 uint32 immediate_data_size = (arg_count - info_arg_count) *
4401 sizeof(CommandBufferEntry); // NOLINT
4403 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4405 if (DebugImpl && doing_gpu_trace)
4406 gpu_tracer_->End(kTraceDecoder);
4408 if (DebugImpl && debug()) {
4409 GLenum error;
4410 while ((error = glGetError()) != GL_NO_ERROR) {
4411 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4412 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4413 << " : " << GetCommandName(command);
4414 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4417 } else {
4418 result = error::kInvalidArguments;
4420 } else {
4421 result = DoCommonCommand(command, arg_count, cmd_data);
4424 if (result == error::kNoError &&
4425 current_decoder_error_ != error::kNoError) {
4426 result = current_decoder_error_;
4427 current_decoder_error_ = error::kNoError;
4430 if (result != error::kDeferCommandUntilLater) {
4431 process_pos += size;
4432 cmd_data += size;
4436 if (entries_processed)
4437 *entries_processed = process_pos;
4439 if (error::IsError(result)) {
4440 LOG(ERROR) << "Error: " << result << " for Command "
4441 << GetCommandName(command);
4444 return result;
4447 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4448 const void* buffer,
4449 int num_entries,
4450 int* entries_processed) {
4451 if (gpu_debug_commands_) {
4452 return DoCommandsImpl<true>(
4453 num_commands, buffer, num_entries, entries_processed);
4454 } else {
4455 return DoCommandsImpl<false>(
4456 num_commands, buffer, num_entries, entries_processed);
4460 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4461 buffer_manager()->RemoveBuffer(client_id);
4464 void GLES2DecoderImpl::DoFinish() {
4465 glFinish();
4466 ProcessPendingReadPixels(true);
4467 ProcessPendingQueries(true);
4470 void GLES2DecoderImpl::DoFlush() {
4471 glFlush();
4472 ProcessPendingQueries(false);
4475 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4476 GLuint texture_index = texture_unit - GL_TEXTURE0;
4477 if (texture_index >= state_.texture_units.size()) {
4478 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4479 "glActiveTexture", texture_unit, "texture_unit");
4480 return;
4482 state_.active_texture_unit = texture_index;
4483 glActiveTexture(texture_unit);
4486 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4487 Buffer* buffer = NULL;
4488 GLuint service_id = 0;
4489 if (client_id != 0) {
4490 buffer = GetBuffer(client_id);
4491 if (!buffer) {
4492 if (!group_->bind_generates_resource()) {
4493 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4494 "glBindBuffer",
4495 "id not generated by glGenBuffers");
4496 return;
4499 // It's a new id so make a buffer buffer for it.
4500 glGenBuffersARB(1, &service_id);
4501 CreateBuffer(client_id, service_id);
4502 buffer = GetBuffer(client_id);
4505 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4506 if (buffer) {
4507 if (!buffer_manager()->SetTarget(buffer, target)) {
4508 LOCAL_SET_GL_ERROR(
4509 GL_INVALID_OPERATION,
4510 "glBindBuffer", "buffer bound to more than 1 target");
4511 return;
4513 service_id = buffer->service_id();
4515 state_.SetBoundBuffer(target, buffer);
4516 glBindBuffer(target, service_id);
4519 void GLES2DecoderImpl::DoBindBufferBase(GLenum target, GLuint index,
4520 GLuint client_id) {
4521 Buffer* buffer = NULL;
4522 GLuint service_id = 0;
4523 if (client_id != 0) {
4524 buffer = GetBuffer(client_id);
4525 if (!buffer) {
4526 if (!group_->bind_generates_resource()) {
4527 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4528 "glBindBufferBase",
4529 "id not generated by glGenBuffers");
4530 return;
4533 // It's a new id so make a buffer for it.
4534 glGenBuffersARB(1, &service_id);
4535 CreateBuffer(client_id, service_id);
4536 buffer = GetBuffer(client_id);
4539 LogClientServiceForInfo(buffer, client_id, "glBindBufferBase");
4540 if (buffer) {
4541 // TODO(kbr): track indexed bound buffers.
4542 service_id = buffer->service_id();
4544 glBindBufferBase(target, index, service_id);
4547 void GLES2DecoderImpl::DoBindBufferRange(GLenum target, GLuint index,
4548 GLuint client_id,
4549 GLintptr offset,
4550 GLsizeiptr size) {
4551 Buffer* buffer = NULL;
4552 GLuint service_id = 0;
4553 if (client_id != 0) {
4554 buffer = GetBuffer(client_id);
4555 if (!buffer) {
4556 if (!group_->bind_generates_resource()) {
4557 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4558 "glBindBufferRange",
4559 "id not generated by glGenBuffers");
4560 return;
4563 // It's a new id so make a buffer for it.
4564 glGenBuffersARB(1, &service_id);
4565 CreateBuffer(client_id, service_id);
4566 buffer = GetBuffer(client_id);
4569 LogClientServiceForInfo(buffer, client_id, "glBindBufferRange");
4570 if (buffer) {
4571 // TODO(kbr): track indexed bound buffers.
4572 service_id = buffer->service_id();
4574 glBindBufferRange(target, index, service_id, offset, size);
4577 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4578 Framebuffer* framebuffer =
4579 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4580 if (framebuffer)
4581 return framebuffer->HasAlphaMRT();
4582 return BackBufferHasAlpha();
4585 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4586 Framebuffer* framebuffer =
4587 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4588 if (framebuffer) {
4589 return framebuffer->HasDepthAttachment();
4591 if (offscreen_target_frame_buffer_.get()) {
4592 return offscreen_target_depth_format_ != 0;
4594 return back_buffer_has_depth_;
4597 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4598 Framebuffer* framebuffer =
4599 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4600 if (framebuffer) {
4601 return framebuffer->HasStencilAttachment();
4603 if (offscreen_target_frame_buffer_.get()) {
4604 return offscreen_target_stencil_format_ != 0 ||
4605 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4607 return back_buffer_has_stencil_;
4610 void GLES2DecoderImpl::ApplyDirtyState() {
4611 if (framebuffer_state_.clear_state_dirty) {
4612 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha();
4613 state_.SetDeviceColorMask(state_.color_mask_red,
4614 state_.color_mask_green,
4615 state_.color_mask_blue,
4616 state_.color_mask_alpha && have_alpha);
4618 bool have_depth = BoundFramebufferHasDepthAttachment();
4619 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4621 bool have_stencil = BoundFramebufferHasStencilAttachment();
4622 state_.SetDeviceStencilMaskSeparate(
4623 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4624 state_.SetDeviceStencilMaskSeparate(
4625 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4627 state_.SetDeviceCapabilityState(
4628 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4629 state_.SetDeviceCapabilityState(
4630 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4631 framebuffer_state_.clear_state_dirty = false;
4635 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4636 return (offscreen_target_frame_buffer_.get())
4637 ? offscreen_target_frame_buffer_->id()
4638 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4641 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4642 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4643 "context", logger_.GetLogPrefix());
4644 // Restore the Framebuffer first because of bugs in Intel drivers.
4645 // Intel drivers incorrectly clip the viewport settings to
4646 // the size of the current framebuffer object.
4647 RestoreFramebufferBindings();
4648 state_.RestoreState(prev_state);
4651 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4652 GLuint service_id =
4653 framebuffer_state_.bound_draw_framebuffer.get()
4654 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4655 : GetBackbufferServiceId();
4656 if (!features().chromium_framebuffer_multisample) {
4657 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4658 } else {
4659 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4660 service_id = framebuffer_state_.bound_read_framebuffer.get()
4661 ? framebuffer_state_.bound_read_framebuffer->service_id()
4662 : GetBackbufferServiceId();
4663 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4665 OnFboChanged();
4668 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4669 state_.RestoreRenderbufferBindings();
4672 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4673 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4674 if (texture) {
4675 GLenum target = texture->target();
4676 glBindTexture(target, service_id);
4677 glTexParameteri(
4678 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4679 glTexParameteri(
4680 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4681 glTexParameteri(
4682 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4683 glTexParameteri(
4684 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4685 RestoreTextureUnitBindings(state_.active_texture_unit);
4689 void GLES2DecoderImpl::ClearAllAttributes() const {
4690 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4691 // other VAOs.
4692 if (feature_info_->feature_flags().native_vertex_array_object)
4693 glBindVertexArrayOES(0);
4695 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4696 if (i != 0) // Never disable attribute 0
4697 glDisableVertexAttribArray(i);
4698 if (features().angle_instanced_arrays)
4699 glVertexAttribDivisorANGLE(i, 0);
4703 void GLES2DecoderImpl::RestoreAllAttributes() const {
4704 state_.RestoreVertexAttribs();
4707 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4708 state_.SetIgnoreCachedStateForTest(ignore);
4711 void GLES2DecoderImpl::OnFboChanged() const {
4712 if (workarounds().restore_scissor_on_fbo_change)
4713 state_.fbo_binding_for_scissor_workaround_dirty = true;
4715 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4716 GLint bound_fbo_unsigned = -1;
4717 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4718 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4719 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4720 surface_->NotifyWasBound();
4724 // Called after the FBO is checked for completeness.
4725 void GLES2DecoderImpl::OnUseFramebuffer() const {
4726 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4727 state_.fbo_binding_for_scissor_workaround_dirty = false;
4728 // The driver forgets the correct scissor when modifying the FBO binding.
4729 glScissor(state_.scissor_x,
4730 state_.scissor_y,
4731 state_.scissor_width,
4732 state_.scissor_height);
4734 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4735 // it's unclear how this bug works.
4736 glFlush();
4740 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4741 Framebuffer* framebuffer = NULL;
4742 GLuint service_id = 0;
4743 if (client_id != 0) {
4744 framebuffer = GetFramebuffer(client_id);
4745 if (!framebuffer) {
4746 if (!group_->bind_generates_resource()) {
4747 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4748 "glBindFramebuffer",
4749 "id not generated by glGenFramebuffers");
4750 return;
4753 // It's a new id so make a framebuffer framebuffer for it.
4754 glGenFramebuffersEXT(1, &service_id);
4755 CreateFramebuffer(client_id, service_id);
4756 framebuffer = GetFramebuffer(client_id);
4757 } else {
4758 service_id = framebuffer->service_id();
4760 framebuffer->MarkAsValid();
4762 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4764 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4765 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4768 // vmiura: This looks like dup code
4769 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4770 framebuffer_state_.bound_read_framebuffer = framebuffer;
4773 framebuffer_state_.clear_state_dirty = true;
4775 // If we are rendering to the backbuffer get the FBO id for any simulated
4776 // backbuffer.
4777 if (framebuffer == NULL) {
4778 service_id = GetBackbufferServiceId();
4781 glBindFramebufferEXT(target, service_id);
4782 OnFboChanged();
4785 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4786 Renderbuffer* renderbuffer = NULL;
4787 GLuint service_id = 0;
4788 if (client_id != 0) {
4789 renderbuffer = GetRenderbuffer(client_id);
4790 if (!renderbuffer) {
4791 if (!group_->bind_generates_resource()) {
4792 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4793 "glBindRenderbuffer",
4794 "id not generated by glGenRenderbuffers");
4795 return;
4798 // It's a new id so make a renderbuffer for it.
4799 glGenRenderbuffersEXT(1, &service_id);
4800 CreateRenderbuffer(client_id, service_id);
4801 renderbuffer = GetRenderbuffer(client_id);
4802 } else {
4803 service_id = renderbuffer->service_id();
4805 renderbuffer->MarkAsValid();
4807 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4808 state_.bound_renderbuffer = renderbuffer;
4809 state_.bound_renderbuffer_valid = true;
4810 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4813 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4814 TextureRef* texture_ref = NULL;
4815 GLuint service_id = 0;
4816 if (client_id != 0) {
4817 texture_ref = GetTexture(client_id);
4818 if (!texture_ref) {
4819 if (!group_->bind_generates_resource()) {
4820 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4821 "glBindTexture",
4822 "id not generated by glGenTextures");
4823 return;
4826 // It's a new id so make a texture texture for it.
4827 glGenTextures(1, &service_id);
4828 DCHECK_NE(0u, service_id);
4829 CreateTexture(client_id, service_id);
4830 texture_ref = GetTexture(client_id);
4832 } else {
4833 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4836 // Check the texture exists
4837 if (texture_ref) {
4838 Texture* texture = texture_ref->texture();
4839 // Check that we are not trying to bind it to a different target.
4840 if (texture->target() != 0 && texture->target() != target) {
4841 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4842 "glBindTexture",
4843 "texture bound to more than 1 target.");
4844 return;
4846 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4847 if (texture->target() == 0) {
4848 texture_manager()->SetTarget(texture_ref, target);
4850 glBindTexture(target, texture->service_id());
4851 } else {
4852 glBindTexture(target, 0);
4855 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4856 unit.bind_target = target;
4857 switch (target) {
4858 case GL_TEXTURE_2D:
4859 unit.bound_texture_2d = texture_ref;
4860 break;
4861 case GL_TEXTURE_CUBE_MAP:
4862 unit.bound_texture_cube_map = texture_ref;
4863 break;
4864 case GL_TEXTURE_EXTERNAL_OES:
4865 unit.bound_texture_external_oes = texture_ref;
4866 break;
4867 case GL_TEXTURE_RECTANGLE_ARB:
4868 unit.bound_texture_rectangle_arb = texture_ref;
4869 break;
4870 case GL_TEXTURE_3D:
4871 unit.bound_texture_3d = texture_ref;
4872 break;
4873 case GL_TEXTURE_2D_ARRAY:
4874 unit.bound_texture_2d_array = texture_ref;
4875 break;
4876 default:
4877 NOTREACHED(); // Validation should prevent us getting here.
4878 break;
4882 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4883 if (state_.vertex_attrib_manager->Enable(index, false)) {
4884 if (index != 0 ||
4885 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4886 glDisableVertexAttribArray(index);
4888 } else {
4889 LOCAL_SET_GL_ERROR(
4890 GL_INVALID_VALUE,
4891 "glDisableVertexAttribArray", "index out of range");
4895 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4896 GLsizei numAttachments,
4897 const GLenum* attachments) {
4898 if (workarounds().disable_discard_framebuffer)
4899 return;
4901 Framebuffer* framebuffer =
4902 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4904 // Validates the attachments. If one of them fails
4905 // the whole command fails.
4906 for (GLsizei i = 0; i < numAttachments; ++i) {
4907 if ((framebuffer &&
4908 !validators_->attachment.IsValid(attachments[i])) ||
4909 (!framebuffer &&
4910 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4911 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4912 "glDiscardFramebufferEXT", attachments[i], "attachments");
4913 return;
4917 // Marks each one of them as not cleared
4918 for (GLsizei i = 0; i < numAttachments; ++i) {
4919 if (framebuffer) {
4920 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4921 texture_manager(),
4922 attachments[i],
4923 false);
4924 } else {
4925 switch (attachments[i]) {
4926 case GL_COLOR_EXT:
4927 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4928 break;
4929 case GL_DEPTH_EXT:
4930 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4931 case GL_STENCIL_EXT:
4932 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4933 break;
4934 default:
4935 NOTREACHED();
4936 break;
4941 // If the default framebuffer is bound but we are still rendering to an
4942 // FBO, translate attachment names that refer to default framebuffer
4943 // channels to corresponding framebuffer attachments.
4944 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4945 for (GLsizei i = 0; i < numAttachments; ++i) {
4946 GLenum attachment = attachments[i];
4947 if (!framebuffer && GetBackbufferServiceId()) {
4948 switch (attachment) {
4949 case GL_COLOR_EXT:
4950 attachment = GL_COLOR_ATTACHMENT0;
4951 break;
4952 case GL_DEPTH_EXT:
4953 attachment = GL_DEPTH_ATTACHMENT;
4954 break;
4955 case GL_STENCIL_EXT:
4956 attachment = GL_STENCIL_ATTACHMENT;
4957 break;
4958 default:
4959 NOTREACHED();
4960 return;
4963 translated_attachments[i] = attachment;
4966 ScopedRenderTo do_render(framebuffer);
4967 if (feature_info_->gl_version_info().is_es3) {
4968 glInvalidateFramebuffer(
4969 target, numAttachments, translated_attachments.get());
4970 } else {
4971 glDiscardFramebufferEXT(
4972 target, numAttachments, translated_attachments.get());
4976 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4977 if (state_.vertex_attrib_manager->Enable(index, true)) {
4978 glEnableVertexAttribArray(index);
4979 } else {
4980 LOCAL_SET_GL_ERROR(
4981 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4985 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4986 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4987 &state_, target);
4988 if (!texture_ref ||
4989 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4990 LOCAL_SET_GL_ERROR(
4991 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4992 return;
4995 if (target == GL_TEXTURE_CUBE_MAP) {
4996 for (int i = 0; i < 6; ++i) {
4997 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4998 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4999 LOCAL_SET_GL_ERROR(
5000 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
5001 return;
5004 } else {
5005 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
5006 LOCAL_SET_GL_ERROR(
5007 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
5008 return;
5012 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
5013 // Workaround for Mac driver bug. In the large scheme of things setting
5014 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
5015 // hit so there's probably no need to make this conditional. The bug appears
5016 // to be that if the filtering mode is set to something that doesn't require
5017 // mipmaps for rendering, or is never set to something other than the default,
5018 // then glGenerateMipmap misbehaves.
5019 if (workarounds().set_texture_filter_before_generating_mipmap) {
5020 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
5022 glGenerateMipmapEXT(target);
5023 if (workarounds().set_texture_filter_before_generating_mipmap) {
5024 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
5025 texture_ref->texture()->min_filter());
5027 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
5028 if (error == GL_NO_ERROR) {
5029 texture_manager()->MarkMipmapsGenerated(texture_ref);
5033 bool GLES2DecoderImpl::GetHelper(
5034 GLenum pname, GLint* params, GLsizei* num_written) {
5035 DCHECK(num_written);
5036 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
5037 switch (pname) {
5038 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
5039 *num_written = 1;
5040 // Return the GL implementation's preferred format and (see below type)
5041 // if we have the GL extension that exposes this. This allows the GPU
5042 // client to use the implementation's preferred format for glReadPixels
5043 // for optimisation.
5045 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
5046 // case when requested on integer/floating point buffers but which is
5047 // acceptable on GLES2 and with the GL_OES_read_format extension.
5049 // Therefore if an error occurs we swallow the error and use the
5050 // internal implementation.
5051 if (params) {
5052 if (context_->HasExtension("GL_OES_read_format")) {
5053 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
5054 GetErrorState());
5055 glGetIntegerv(pname, params);
5056 if (glGetError() == GL_NO_ERROR)
5057 return true;
5059 *params = GLES2Util::GetGLReadPixelsImplementationFormat(
5060 GetBoundReadFrameBufferInternalFormat());
5062 return true;
5063 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
5064 *num_written = 1;
5065 if (params) {
5066 if (context_->HasExtension("GL_OES_read_format")) {
5067 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
5068 GetErrorState());
5069 glGetIntegerv(pname, params);
5070 if (glGetError() == GL_NO_ERROR)
5071 return true;
5073 *params = GLES2Util::GetGLReadPixelsImplementationType(
5074 GetBoundReadFrameBufferInternalFormat(),
5075 GetBoundReadFrameBufferTextureType());
5077 return true;
5078 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
5079 *num_written = 1;
5080 if (params) {
5081 *params = group_->max_fragment_uniform_vectors();
5083 return true;
5084 case GL_MAX_VARYING_VECTORS:
5085 *num_written = 1;
5086 if (params) {
5087 *params = group_->max_varying_vectors();
5089 return true;
5090 case GL_MAX_VERTEX_UNIFORM_VECTORS:
5091 *num_written = 1;
5092 if (params) {
5093 *params = group_->max_vertex_uniform_vectors();
5095 return true;
5098 if (unsafe_es3_apis_enabled()) {
5099 switch (pname) {
5100 case GL_MAX_VARYING_COMPONENTS: {
5101 if (feature_info_->gl_version_info().is_es) {
5102 // We can just delegate this query to the driver.
5103 return false;
5106 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5107 // OpenGL core profile, so for simplicity, just compute it
5108 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5109 // configurations.
5110 GLint max_varying_vectors = 0;
5111 glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors);
5112 *num_written = 1;
5113 if (params) {
5114 *params = max_varying_vectors * 4;
5116 return true;
5118 case GL_READ_BUFFER:
5119 *num_written = 1;
5120 if (params) {
5121 Framebuffer* framebuffer =
5122 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
5123 GLenum read_buffer;
5124 if (framebuffer) {
5125 read_buffer = framebuffer->read_buffer();
5126 } else {
5127 read_buffer = back_buffer_read_buffer_;
5129 *params = static_cast<GLint>(read_buffer);
5131 return true;
5134 switch (pname) {
5135 case GL_MAX_VIEWPORT_DIMS:
5136 if (offscreen_target_frame_buffer_.get()) {
5137 *num_written = 2;
5138 if (params) {
5139 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5140 params[1] = renderbuffer_manager()->max_renderbuffer_size();
5142 return true;
5144 return false;
5145 case GL_MAX_SAMPLES:
5146 *num_written = 1;
5147 if (params) {
5148 params[0] = renderbuffer_manager()->max_samples();
5150 return true;
5151 case GL_MAX_RENDERBUFFER_SIZE:
5152 *num_written = 1;
5153 if (params) {
5154 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5156 return true;
5157 case GL_MAX_TEXTURE_SIZE:
5158 *num_written = 1;
5159 if (params) {
5160 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
5162 return true;
5163 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
5164 *num_written = 1;
5165 if (params) {
5166 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
5168 return true;
5169 case GL_MAX_COLOR_ATTACHMENTS_EXT:
5170 *num_written = 1;
5171 if (params) {
5172 params[0] = group_->max_color_attachments();
5174 return true;
5175 case GL_MAX_DRAW_BUFFERS_ARB:
5176 *num_written = 1;
5177 if (params) {
5178 params[0] = group_->max_draw_buffers();
5180 return true;
5181 case GL_ALPHA_BITS:
5182 *num_written = 1;
5183 if (params) {
5184 GLint v = 0;
5185 Framebuffer* framebuffer =
5186 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5187 if (framebuffer) {
5188 if (framebuffer->HasAlphaMRT() &&
5189 framebuffer->HasSameInternalFormatsMRT()) {
5190 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5191 glGetFramebufferAttachmentParameterivEXT(
5192 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5193 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
5194 } else {
5195 glGetIntegerv(GL_ALPHA_BITS, &v);
5198 } else {
5199 v = (BackBufferHasAlpha() ? 8 : 0);
5201 params[0] = v;
5203 return true;
5204 case GL_DEPTH_BITS:
5205 *num_written = 1;
5206 if (params) {
5207 GLint v = 0;
5208 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5209 Framebuffer* framebuffer =
5210 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5211 if (framebuffer) {
5212 glGetFramebufferAttachmentParameterivEXT(
5213 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
5214 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
5215 } else {
5216 v = (back_buffer_has_depth_ ? 24 : 0);
5218 } else {
5219 glGetIntegerv(GL_DEPTH_BITS, &v);
5221 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
5223 return true;
5224 case GL_RED_BITS:
5225 case GL_GREEN_BITS:
5226 case GL_BLUE_BITS:
5227 *num_written = 1;
5228 if (params) {
5229 GLint v = 0;
5230 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5231 Framebuffer* framebuffer =
5232 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5233 if (framebuffer) {
5234 GLenum framebuffer_enum = 0;
5235 switch (pname) {
5236 case GL_RED_BITS:
5237 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
5238 break;
5239 case GL_GREEN_BITS:
5240 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
5241 break;
5242 case GL_BLUE_BITS:
5243 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
5244 break;
5246 glGetFramebufferAttachmentParameterivEXT(
5247 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
5248 } else {
5249 v = 8;
5251 } else {
5252 glGetIntegerv(pname, &v);
5254 params[0] = v;
5256 return true;
5257 case GL_STENCIL_BITS:
5258 *num_written = 1;
5259 if (params) {
5260 GLint v = 0;
5261 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5262 Framebuffer* framebuffer =
5263 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5264 if (framebuffer) {
5265 glGetFramebufferAttachmentParameterivEXT(
5266 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
5267 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
5268 } else {
5269 v = (back_buffer_has_stencil_ ? 8 : 0);
5271 } else {
5272 glGetIntegerv(GL_STENCIL_BITS, &v);
5274 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
5276 return true;
5277 case GL_COMPRESSED_TEXTURE_FORMATS:
5278 *num_written = validators_->compressed_texture_format.GetValues().size();
5279 if (params) {
5280 for (GLint ii = 0; ii < *num_written; ++ii) {
5281 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
5284 return true;
5285 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
5286 *num_written = 1;
5287 if (params) {
5288 *params = validators_->compressed_texture_format.GetValues().size();
5290 return true;
5291 case GL_NUM_SHADER_BINARY_FORMATS:
5292 *num_written = 1;
5293 if (params) {
5294 *params = validators_->shader_binary_format.GetValues().size();
5296 return true;
5297 case GL_SHADER_BINARY_FORMATS:
5298 *num_written = validators_->shader_binary_format.GetValues().size();
5299 if (params) {
5300 for (GLint ii = 0; ii < *num_written; ++ii) {
5301 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5304 return true;
5305 case GL_SHADER_COMPILER:
5306 *num_written = 1;
5307 if (params) {
5308 *params = GL_TRUE;
5310 return true;
5311 case GL_ARRAY_BUFFER_BINDING:
5312 *num_written = 1;
5313 if (params) {
5314 *params = GetClientId(
5315 buffer_manager(), state_.bound_array_buffer.get());
5317 return true;
5318 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5319 *num_written = 1;
5320 if (params) {
5321 *params = GetClientId(
5322 buffer_manager(),
5323 state_.vertex_attrib_manager->element_array_buffer());
5325 return true;
5326 case GL_COPY_READ_BUFFER_BINDING:
5327 *num_written = 1;
5328 if (params) {
5329 *params = GetClientId(
5330 buffer_manager(), state_.bound_copy_read_buffer.get());
5332 return true;
5333 case GL_COPY_WRITE_BUFFER_BINDING:
5334 *num_written = 1;
5335 if (params) {
5336 *params = GetClientId(
5337 buffer_manager(), state_.bound_copy_write_buffer.get());
5339 return true;
5340 case GL_PIXEL_PACK_BUFFER_BINDING:
5341 *num_written = 1;
5342 if (params) {
5343 *params = GetClientId(
5344 buffer_manager(), state_.bound_pixel_pack_buffer.get());
5346 return true;
5347 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5348 *num_written = 1;
5349 if (params) {
5350 *params = GetClientId(
5351 buffer_manager(), state_.bound_pixel_unpack_buffer.get());
5353 return true;
5354 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5355 *num_written = 1;
5356 if (params) {
5357 *params = GetClientId(
5358 buffer_manager(), state_.bound_transform_feedback_buffer.get());
5360 return true;
5361 case GL_UNIFORM_BUFFER_BINDING:
5362 *num_written = 1;
5363 if (params) {
5364 *params = GetClientId(
5365 buffer_manager(), state_.bound_uniform_buffer.get());
5367 return true;
5368 case GL_FRAMEBUFFER_BINDING:
5369 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5370 *num_written = 1;
5371 if (params) {
5372 *params = GetClientId(
5373 framebuffer_manager(),
5374 GetFramebufferInfoForTarget(GL_FRAMEBUFFER));
5376 return true;
5377 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5378 *num_written = 1;
5379 if (params) {
5380 *params = GetClientId(
5381 framebuffer_manager(),
5382 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT));
5384 return true;
5385 case GL_RENDERBUFFER_BINDING:
5386 *num_written = 1;
5387 if (params) {
5388 Renderbuffer* renderbuffer =
5389 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5390 if (renderbuffer) {
5391 *params = renderbuffer->client_id();
5392 } else {
5393 *params = 0;
5396 return true;
5397 case GL_CURRENT_PROGRAM:
5398 *num_written = 1;
5399 if (params) {
5400 *params = GetClientId(program_manager(), state_.current_program.get());
5402 return true;
5403 case GL_VERTEX_ARRAY_BINDING_OES:
5404 *num_written = 1;
5405 if (params) {
5406 if (state_.vertex_attrib_manager.get() !=
5407 state_.default_vertex_attrib_manager.get()) {
5408 GLuint client_id = 0;
5409 vertex_array_manager_->GetClientId(
5410 state_.vertex_attrib_manager->service_id(), &client_id);
5411 *params = client_id;
5412 } else {
5413 *params = 0;
5416 return true;
5417 case GL_TEXTURE_BINDING_2D:
5418 *num_written = 1;
5419 if (params) {
5420 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5421 if (unit.bound_texture_2d.get()) {
5422 *params = unit.bound_texture_2d->client_id();
5423 } else {
5424 *params = 0;
5427 return true;
5428 case GL_TEXTURE_BINDING_CUBE_MAP:
5429 *num_written = 1;
5430 if (params) {
5431 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5432 if (unit.bound_texture_cube_map.get()) {
5433 *params = unit.bound_texture_cube_map->client_id();
5434 } else {
5435 *params = 0;
5438 return true;
5439 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5440 *num_written = 1;
5441 if (params) {
5442 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5443 if (unit.bound_texture_external_oes.get()) {
5444 *params = unit.bound_texture_external_oes->client_id();
5445 } else {
5446 *params = 0;
5449 return true;
5450 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5451 *num_written = 1;
5452 if (params) {
5453 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5454 if (unit.bound_texture_rectangle_arb.get()) {
5455 *params = unit.bound_texture_rectangle_arb->client_id();
5456 } else {
5457 *params = 0;
5460 return true;
5461 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5462 *num_written = 1;
5463 if (params) {
5464 params[0] = group_->bind_generates_resource() ? 1 : 0;
5466 return true;
5467 default:
5468 if (pname >= GL_DRAW_BUFFER0_ARB &&
5469 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5470 *num_written = 1;
5471 if (params) {
5472 Framebuffer* framebuffer =
5473 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5474 if (framebuffer) {
5475 params[0] = framebuffer->GetDrawBuffer(pname);
5476 } else { // backbuffer
5477 if (pname == GL_DRAW_BUFFER0_ARB)
5478 params[0] = back_buffer_draw_buffer_;
5479 else
5480 params[0] = GL_NONE;
5483 return true;
5485 *num_written = util_.GLGetNumValuesReturned(pname);
5486 return false;
5490 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5491 GLenum pname, GLsizei* num_values) {
5492 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5493 return true;
5495 return GetHelper(pname, NULL, num_values);
5498 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5499 if (GL_MAX_SAMPLES == pname &&
5500 features().use_img_for_multisampled_render_to_texture) {
5501 return GL_MAX_SAMPLES_IMG;
5503 return pname;
5506 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5507 DCHECK(params);
5508 GLsizei num_written = 0;
5509 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5510 scoped_ptr<GLint[]> values(new GLint[num_written]);
5511 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5512 GetHelper(pname, values.get(), &num_written);
5514 for (GLsizei ii = 0; ii < num_written; ++ii) {
5515 params[ii] = static_cast<GLboolean>(values[ii]);
5517 } else {
5518 pname = AdjustGetPname(pname);
5519 glGetBooleanv(pname, params);
5523 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5524 DCHECK(params);
5525 GLsizei num_written = 0;
5526 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5527 if (GetHelper(pname, NULL, &num_written)) {
5528 scoped_ptr<GLint[]> values(new GLint[num_written]);
5529 GetHelper(pname, values.get(), &num_written);
5530 for (GLsizei ii = 0; ii < num_written; ++ii) {
5531 params[ii] = static_cast<GLfloat>(values[ii]);
5533 } else {
5534 pname = AdjustGetPname(pname);
5535 glGetFloatv(pname, params);
5540 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5541 DCHECK(params);
5542 if (unsafe_es3_apis_enabled()) {
5543 switch (pname) {
5544 case GL_MAX_ELEMENT_INDEX: {
5545 if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
5546 feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
5547 glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
5548 } else {
5549 // Assume that desktop GL implementations can generally support
5550 // 32-bit indices.
5551 if (params) {
5552 *params = std::numeric_limits<unsigned int>::max();
5555 return;
5559 pname = AdjustGetPname(pname);
5560 glGetInteger64v(pname, params);
5563 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5564 DCHECK(params);
5565 GLsizei num_written;
5566 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5567 !GetHelper(pname, params, &num_written)) {
5568 pname = AdjustGetPname(pname);
5569 glGetIntegerv(pname, params);
5573 void GLES2DecoderImpl::DoGetProgramiv(
5574 GLuint program_id, GLenum pname, GLint* params) {
5575 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5576 if (!program) {
5577 return;
5579 program->GetProgramiv(pname, params);
5582 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5583 GLenum target, GLenum pname, GLint64* params) {
5584 // Just delegate it. Some validation is actually done before this.
5585 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5586 &state_, target, pname, params);
5589 void GLES2DecoderImpl::DoGetBufferParameteriv(
5590 GLenum target, GLenum pname, GLint* params) {
5591 // Just delegate it. Some validation is actually done before this.
5592 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5593 &state_, target, pname, params);
5596 void GLES2DecoderImpl::DoBindAttribLocation(
5597 GLuint program_id, GLuint index, const char* name) {
5598 if (!StringIsValidForGLES(name)) {
5599 LOCAL_SET_GL_ERROR(
5600 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5601 return;
5603 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5604 LOCAL_SET_GL_ERROR(
5605 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5606 return;
5608 if (index >= group_->max_vertex_attribs()) {
5609 LOCAL_SET_GL_ERROR(
5610 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5611 return;
5613 Program* program = GetProgramInfoNotShader(
5614 program_id, "glBindAttribLocation");
5615 if (!program) {
5616 return;
5618 // At this point, the program's shaders may not be translated yet,
5619 // therefore, we may not find the hashed attribute name.
5620 // glBindAttribLocation call with original name is useless.
5621 // So instead, we should simply cache the binding, and then call
5622 // Program::ExecuteBindAttribLocationCalls() right before link.
5623 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5624 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5625 glBindAttribLocation(program->service_id(), index, name);
5628 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5629 uint32 immediate_data_size,
5630 const void* cmd_data) {
5631 const gles2::cmds::BindAttribLocationBucket& c =
5632 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5633 GLuint program = static_cast<GLuint>(c.program);
5634 GLuint index = static_cast<GLuint>(c.index);
5635 Bucket* bucket = GetBucket(c.name_bucket_id);
5636 if (!bucket || bucket->size() == 0) {
5637 return error::kInvalidArguments;
5639 std::string name_str;
5640 if (!bucket->GetAsString(&name_str)) {
5641 return error::kInvalidArguments;
5643 DoBindAttribLocation(program, index, name_str.c_str());
5644 return error::kNoError;
5647 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5648 GLuint program_id, GLint location, const char* name) {
5649 if (!StringIsValidForGLES(name)) {
5650 LOCAL_SET_GL_ERROR(
5651 GL_INVALID_VALUE,
5652 "glBindUniformLocationCHROMIUM", "Invalid character");
5653 return;
5655 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5656 LOCAL_SET_GL_ERROR(
5657 GL_INVALID_OPERATION,
5658 "glBindUniformLocationCHROMIUM", "reserved prefix");
5659 return;
5661 if (location < 0 || static_cast<uint32>(location) >=
5662 (group_->max_fragment_uniform_vectors() +
5663 group_->max_vertex_uniform_vectors()) * 4) {
5664 LOCAL_SET_GL_ERROR(
5665 GL_INVALID_VALUE,
5666 "glBindUniformLocationCHROMIUM", "location out of range");
5667 return;
5669 Program* program = GetProgramInfoNotShader(
5670 program_id, "glBindUniformLocationCHROMIUM");
5671 if (!program) {
5672 return;
5674 if (!program->SetUniformLocationBinding(name, location)) {
5675 LOCAL_SET_GL_ERROR(
5676 GL_INVALID_VALUE,
5677 "glBindUniformLocationCHROMIUM", "location out of range");
5681 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5682 uint32 immediate_data_size,
5683 const void* cmd_data) {
5684 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5685 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5686 cmd_data);
5687 GLuint program = static_cast<GLuint>(c.program);
5688 GLint location = static_cast<GLint>(c.location);
5689 Bucket* bucket = GetBucket(c.name_bucket_id);
5690 if (!bucket || bucket->size() == 0) {
5691 return error::kInvalidArguments;
5693 std::string name_str;
5694 if (!bucket->GetAsString(&name_str)) {
5695 return error::kInvalidArguments;
5697 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5698 return error::kNoError;
5701 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5702 const void* cmd_data) {
5703 const gles2::cmds::DeleteShader& c =
5704 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5705 GLuint client_id = c.shader;
5706 if (client_id) {
5707 Shader* shader = GetShader(client_id);
5708 if (shader) {
5709 if (!shader->IsDeleted()) {
5710 shader_manager()->Delete(shader);
5712 } else {
5713 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5716 return error::kNoError;
5719 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5720 const void* cmd_data) {
5721 const gles2::cmds::DeleteProgram& c =
5722 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5723 GLuint client_id = c.program;
5724 if (client_id) {
5725 Program* program = GetProgram(client_id);
5726 if (program) {
5727 if (!program->IsDeleted()) {
5728 program_manager()->MarkAsDeleted(shader_manager(), program);
5730 } else {
5731 LOCAL_SET_GL_ERROR(
5732 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5735 return error::kNoError;
5738 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5739 DCHECK(!ShouldDeferDraws());
5740 if (CheckBoundFramebuffersValid("glClear")) {
5741 ApplyDirtyState();
5742 // TODO(zmo): Filter out INTEGER/SIGNED INTEGER images to avoid
5743 // undefined results.
5744 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5745 if (workarounds().gl_clear_broken) {
5746 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5747 GetErrorState());
5748 if (!BoundFramebufferHasDepthAttachment())
5749 mask &= ~GL_DEPTH_BUFFER_BIT;
5750 if (!BoundFramebufferHasStencilAttachment())
5751 mask &= ~GL_STENCIL_BUFFER_BIT;
5752 clear_framebuffer_blit_->ClearFramebuffer(
5753 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5754 state_.color_clear_green, state_.color_clear_blue,
5755 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5756 return error::kNoError;
5758 glClear(mask);
5760 return error::kNoError;
5763 void GLES2DecoderImpl::DoClearBufferiv(
5764 GLenum buffer, GLint drawbuffer, const GLint* value) {
5765 if (!CheckBoundDrawFramebufferValid("glClearBufferiv"))
5766 return;
5767 ApplyDirtyState();
5769 switch (buffer) {
5770 case GL_COLOR:
5771 case GL_STENCIL:
5772 break;
5773 default:
5774 LOCAL_SET_GL_ERROR(
5775 GL_INVALID_ENUM, "glClearBufferiv", "invalid buffer");
5776 return;
5778 GLenum attachment = 0;
5779 if (buffer == GL_COLOR) {
5780 if (drawbuffer < 0 ||
5781 drawbuffer >= static_cast<GLint>(group_->max_draw_buffers())) {
5782 LOCAL_SET_GL_ERROR(
5783 GL_INVALID_VALUE, "glClearBufferiv", "invalid drawBuffer");
5784 return;
5786 GLenum internal_format =
5787 GetBoundColorDrawBufferInternalFormat(drawbuffer);
5788 if (!GLES2Util::IsSignedIntegerFormat(internal_format)) {
5789 // To avoid undefined results, return without calling the gl function.
5790 return;
5792 attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + drawbuffer);
5793 } else {
5794 DCHECK(buffer == GL_STENCIL);
5795 if (drawbuffer != 0) {
5796 LOCAL_SET_GL_ERROR(
5797 GL_INVALID_VALUE, "glClearBufferiv", "invalid drawBuffer");
5798 return;
5800 if (!BoundFramebufferHasStencilAttachment()) {
5801 return;
5803 attachment = GL_STENCIL_ATTACHMENT;
5805 MarkDrawBufferAsCleared(buffer, drawbuffer);
5807 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get(),
5808 attachment);
5809 glClearBufferiv(buffer, drawbuffer, value);
5813 void GLES2DecoderImpl::DoClearBufferuiv(
5814 GLenum buffer, GLint drawbuffer, const GLuint* value) {
5815 if (!CheckBoundDrawFramebufferValid("glClearBufferuiv"))
5816 return;
5817 ApplyDirtyState();
5819 switch (buffer) {
5820 case GL_COLOR:
5821 break;
5822 default:
5823 LOCAL_SET_GL_ERROR(
5824 GL_INVALID_ENUM, "glClearBufferuiv", "invalid buffer");
5825 return;
5827 if (drawbuffer < 0 ||
5828 drawbuffer >= static_cast<GLint>(group_->max_draw_buffers())) {
5829 LOCAL_SET_GL_ERROR(
5830 GL_INVALID_VALUE, "glClearBufferuiv", "invalid drawBuffer");
5831 return;
5833 GLenum internal_format =
5834 GetBoundColorDrawBufferInternalFormat(drawbuffer);
5835 if (!GLES2Util::IsUnsignedIntegerFormat(internal_format)) {
5836 // To avoid undefined results, return without calling the gl function.
5837 return;
5839 MarkDrawBufferAsCleared(buffer, drawbuffer);
5840 GLenum attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + drawbuffer);
5842 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get(),
5843 attachment);
5844 glClearBufferuiv(buffer, drawbuffer, value);
5848 void GLES2DecoderImpl::DoClearBufferfv(
5849 GLenum buffer, GLint drawbuffer, const GLfloat* value) {
5850 if (!CheckBoundDrawFramebufferValid("glClearBufferfv"))
5851 return;
5852 ApplyDirtyState();
5854 switch (buffer) {
5855 case GL_COLOR:
5856 case GL_DEPTH:
5857 break;
5858 default:
5859 LOCAL_SET_GL_ERROR(
5860 GL_INVALID_ENUM, "glClearBufferfv", "invalid buffer");
5861 return;
5863 GLenum attachment = 0;
5864 if (buffer == GL_COLOR) {
5865 if (drawbuffer < 0 ||
5866 drawbuffer >= static_cast<GLint>(group_->max_draw_buffers())) {
5867 LOCAL_SET_GL_ERROR(
5868 GL_INVALID_VALUE, "glClearBufferfv", "invalid drawBuffer");
5869 return;
5871 GLenum internal_format =
5872 GetBoundColorDrawBufferInternalFormat(drawbuffer);
5873 if (GLES2Util::IsIntegerFormat(internal_format)) {
5874 // To avoid undefined results, return without calling the gl function.
5875 return;
5877 attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + drawbuffer);
5878 } else {
5879 DCHECK(buffer == GL_DEPTH);
5880 if (drawbuffer != 0) {
5881 LOCAL_SET_GL_ERROR(
5882 GL_INVALID_VALUE, "glClearBufferfv", "invalid drawBuffer");
5883 return;
5885 if (!BoundFramebufferHasDepthAttachment()) {
5886 return;
5888 attachment = GL_DEPTH_ATTACHMENT;
5890 MarkDrawBufferAsCleared(buffer, drawbuffer);
5892 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get(),
5893 attachment);
5894 glClearBufferfv(buffer, drawbuffer, value);
5898 void GLES2DecoderImpl::DoClearBufferfi(
5899 GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
5900 if (!CheckBoundDrawFramebufferValid("glClearBufferfi"))
5901 return;
5902 ApplyDirtyState();
5904 switch (buffer) {
5905 case GL_DEPTH_STENCIL:
5906 break;
5907 default:
5908 LOCAL_SET_GL_ERROR(
5909 GL_INVALID_ENUM, "glClearBufferfi", "invalid buffer");
5910 return;
5912 if (drawbuffer != 0) {
5913 LOCAL_SET_GL_ERROR(
5914 GL_INVALID_VALUE, "glClearBufferfi", "invalid drawBuffer");
5915 return;
5917 if (!BoundFramebufferHasDepthAttachment() &&
5918 !BoundFramebufferHasStencilAttachment()) {
5919 return;
5921 MarkDrawBufferAsCleared(GL_DEPTH, drawbuffer);
5922 MarkDrawBufferAsCleared(GL_STENCIL, drawbuffer);
5924 ScopedRenderTo do_render_depth(
5925 framebuffer_state_.bound_draw_framebuffer.get(),
5926 GL_DEPTH_ATTACHMENT);
5927 ScopedRenderTo do_render_stencil(
5928 framebuffer_state_.bound_draw_framebuffer.get(),
5929 GL_STENCIL_ATTACHMENT);
5930 glClearBufferfi(buffer, drawbuffer, depth, stencil);
5934 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5935 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5936 GLuint client_renderbuffer_id) {
5937 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5938 if (!framebuffer) {
5939 LOCAL_SET_GL_ERROR(
5940 GL_INVALID_OPERATION,
5941 "glFramebufferRenderbuffer", "no framebuffer bound");
5942 return;
5944 GLuint service_id = 0;
5945 Renderbuffer* renderbuffer = NULL;
5946 if (client_renderbuffer_id) {
5947 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5948 if (!renderbuffer) {
5949 LOCAL_SET_GL_ERROR(
5950 GL_INVALID_OPERATION,
5951 "glFramebufferRenderbuffer", "unknown renderbuffer");
5952 return;
5954 service_id = renderbuffer->service_id();
5956 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5957 glFramebufferRenderbufferEXT(
5958 target, attachment, renderbuffertarget, service_id);
5959 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5960 if (error == GL_NO_ERROR) {
5961 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5963 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5964 framebuffer_state_.clear_state_dirty = true;
5966 OnFboChanged();
5969 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5970 if (SetCapabilityState(cap, false)) {
5971 glDisable(cap);
5975 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5976 if (SetCapabilityState(cap, true)) {
5977 glEnable(cap);
5981 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5982 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5983 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5984 glDepthRange(znear, zfar);
5987 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5988 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5989 state_.sample_coverage_invert = (invert != 0);
5990 glSampleCoverage(state_.sample_coverage_value, invert);
5993 // Assumes framebuffer is complete.
5994 void GLES2DecoderImpl::ClearUnclearedAttachments(
5995 GLenum target, Framebuffer* framebuffer) {
5996 if (target == GL_READ_FRAMEBUFFER_EXT) {
5997 // bind this to the DRAW point, clear then bind back to READ
5998 // TODO(gman): I don't think there is any guarantee that an FBO that
5999 // is complete on the READ attachment will be complete as a DRAW
6000 // attachment.
6001 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
6002 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
6004 GLbitfield clear_bits = 0;
6005 if (framebuffer->HasUnclearedColorAttachments()) {
6006 // We should always use alpha == 0 here, because 1) some draw buffers may
6007 // have alpha and some may not; 2) we won't have the same situation as the
6008 // back buffer where alpha channel exists but is not requested.
6009 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6010 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6011 clear_bits |= GL_COLOR_BUFFER_BIT;
6012 if (feature_info_->feature_flags().ext_draw_buffers ||
6013 feature_info_->IsES3Enabled()) {
6014 framebuffer->PrepareDrawBuffersForClear();
6018 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
6019 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
6020 glClearStencil(0);
6021 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
6022 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
6023 clear_bits |= GL_STENCIL_BUFFER_BIT;
6026 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
6027 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
6028 glClearDepth(1.0f);
6029 state_.SetDeviceDepthMask(GL_TRUE);
6030 clear_bits |= GL_DEPTH_BUFFER_BIT;
6033 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6034 glClear(clear_bits);
6036 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
6037 (feature_info_->feature_flags().ext_draw_buffers ||
6038 feature_info_->IsES3Enabled())) {
6039 framebuffer->RestoreDrawBuffersAfterClear();
6042 if (feature_info_->IsES3Enabled()) {
6043 // TODO(zmo): track more state to know whether there are any integer
6044 // buffers attached to the current framebuffer.
6045 framebuffer->ClearIntegerBuffers();
6048 framebuffer_manager()->MarkAttachmentsAsCleared(
6049 framebuffer, renderbuffer_manager(), texture_manager());
6051 RestoreClearState();
6053 if (target == GL_READ_FRAMEBUFFER_EXT) {
6054 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
6055 Framebuffer* draw_framebuffer =
6056 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
6057 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
6058 GetBackbufferServiceId();
6059 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
6063 void GLES2DecoderImpl::RestoreClearState() {
6064 framebuffer_state_.clear_state_dirty = true;
6065 glClearColor(
6066 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
6067 state_.color_clear_alpha);
6068 glClearStencil(state_.stencil_clear);
6069 glClearDepth(state_.depth_clear);
6070 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
6071 state_.enable_flags.scissor_test);
6072 glScissor(state_.scissor_x, state_.scissor_y, state_.scissor_width,
6073 state_.scissor_height);
6076 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
6077 Framebuffer* framebuffer =
6078 GetFramebufferInfoForTarget(target);
6079 if (!framebuffer) {
6080 return GL_FRAMEBUFFER_COMPLETE;
6082 GLenum completeness = framebuffer->IsPossiblyComplete();
6083 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
6084 return completeness;
6086 return framebuffer->GetStatus(texture_manager(), target);
6089 void GLES2DecoderImpl::DoFramebufferTexture2D(
6090 GLenum target, GLenum attachment, GLenum textarget,
6091 GLuint client_texture_id, GLint level) {
6092 DoFramebufferTexture2DCommon(
6093 "glFramebufferTexture2D", target, attachment,
6094 textarget, client_texture_id, level, 0);
6097 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
6098 GLenum target, GLenum attachment, GLenum textarget,
6099 GLuint client_texture_id, GLint level, GLsizei samples) {
6100 DoFramebufferTexture2DCommon(
6101 "glFramebufferTexture2DMultisample", target, attachment,
6102 textarget, client_texture_id, level, samples);
6105 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
6106 const char* name, GLenum target, GLenum attachment, GLenum textarget,
6107 GLuint client_texture_id, GLint level, GLsizei samples) {
6108 if (samples > renderbuffer_manager()->max_samples()) {
6109 LOCAL_SET_GL_ERROR(
6110 GL_INVALID_VALUE,
6111 "glFramebufferTexture2DMultisample", "samples too large");
6112 return;
6114 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
6115 if (!framebuffer) {
6116 LOCAL_SET_GL_ERROR(
6117 GL_INVALID_OPERATION,
6118 name, "no framebuffer bound.");
6119 return;
6121 GLuint service_id = 0;
6122 TextureRef* texture_ref = NULL;
6123 if (client_texture_id) {
6124 texture_ref = GetTexture(client_texture_id);
6125 if (!texture_ref) {
6126 LOCAL_SET_GL_ERROR(
6127 GL_INVALID_OPERATION,
6128 name, "unknown texture_ref");
6129 return;
6131 service_id = texture_ref->service_id();
6134 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
6135 LOCAL_SET_GL_ERROR(
6136 GL_INVALID_VALUE,
6137 name, "level out of range");
6138 return;
6141 if (texture_ref)
6142 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
6144 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
6145 if (0 == samples) {
6146 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
6147 } else {
6148 if (features().use_img_for_multisampled_render_to_texture) {
6149 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
6150 service_id, level, samples);
6151 } else {
6152 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
6153 service_id, level, samples);
6156 GLenum error = LOCAL_PEEK_GL_ERROR(name);
6157 if (error == GL_NO_ERROR) {
6158 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
6159 samples);
6161 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
6162 framebuffer_state_.clear_state_dirty = true;
6165 if (texture_ref)
6166 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
6168 OnFboChanged();
6171 void GLES2DecoderImpl::DoFramebufferTextureLayer(
6172 GLenum target, GLenum attachment, GLuint client_texture_id,
6173 GLint level, GLint layer) {
6174 // TODO(zmo): Unsafe ES3 API, missing states update.
6175 GLuint service_id = 0;
6176 TextureRef* texture_ref = NULL;
6177 if (client_texture_id) {
6178 texture_ref = GetTexture(client_texture_id);
6179 if (!texture_ref) {
6180 LOCAL_SET_GL_ERROR(
6181 GL_INVALID_OPERATION,
6182 "glFramebufferTextureLayer", "unknown texture_ref");
6183 return;
6185 service_id = texture_ref->service_id();
6187 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
6190 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
6191 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
6192 const char kFunctionName[] = "glGetFramebufferAttachmentParameteriv";
6193 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
6194 if (!framebuffer) {
6195 if (!unsafe_es3_apis_enabled()) {
6196 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
6197 "no framebuffer bound");
6198 return;
6200 if (!validators_->backbuffer_attachment.IsValid(attachment)) {
6201 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
6202 "invalid attachment for backbuffer");
6203 return;
6205 switch (pname) {
6206 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
6207 *params = static_cast<GLint>(GL_FRAMEBUFFER_DEFAULT);
6208 return;
6209 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
6210 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
6211 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
6212 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
6213 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
6214 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
6215 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
6216 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
6217 // Delegate to underlying driver.
6218 break;
6219 default:
6220 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName,
6221 "invalid pname for backbuffer");
6222 return;
6224 if (GetBackbufferServiceId() != 0) { // Emulated backbuffer.
6225 switch (attachment) {
6226 case GL_BACK:
6227 attachment = GL_COLOR_ATTACHMENT0;
6228 break;
6229 case GL_DEPTH:
6230 attachment = GL_DEPTH_ATTACHMENT;
6231 break;
6232 case GL_STENCIL:
6233 attachment = GL_STENCIL_ATTACHMENT;
6234 break;
6235 default:
6236 NOTREACHED();
6237 break;
6241 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
6242 features().use_img_for_multisampled_render_to_texture) {
6243 pname = GL_TEXTURE_SAMPLES_IMG;
6245 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
6246 DCHECK(framebuffer);
6247 // If we query from the driver, it will be service ID; however, we need to
6248 // return the client ID here.
6249 const Framebuffer::Attachment* attachment_object =
6250 framebuffer->GetAttachment(attachment);
6251 *params = attachment_object ? attachment_object->object_name() : 0;
6252 return;
6255 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
6256 // We didn't perform a full error check before gl call.
6257 LOCAL_PEEK_GL_ERROR(kFunctionName);
6260 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
6261 GLenum target, GLenum pname, GLint* params) {
6262 Renderbuffer* renderbuffer =
6263 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6264 if (!renderbuffer) {
6265 LOCAL_SET_GL_ERROR(
6266 GL_INVALID_OPERATION,
6267 "glGetRenderbufferParameteriv", "no renderbuffer bound");
6268 return;
6271 EnsureRenderbufferBound();
6272 switch (pname) {
6273 case GL_RENDERBUFFER_INTERNAL_FORMAT:
6274 *params = renderbuffer->internal_format();
6275 break;
6276 case GL_RENDERBUFFER_WIDTH:
6277 *params = renderbuffer->width();
6278 break;
6279 case GL_RENDERBUFFER_HEIGHT:
6280 *params = renderbuffer->height();
6281 break;
6282 case GL_RENDERBUFFER_SAMPLES_EXT:
6283 if (features().use_img_for_multisampled_render_to_texture) {
6284 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
6285 params);
6286 } else {
6287 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
6288 params);
6290 default:
6291 glGetRenderbufferParameterivEXT(target, pname, params);
6292 break;
6296 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
6297 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
6298 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6299 GLbitfield mask, GLenum filter) {
6300 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
6302 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
6303 return;
6306 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6307 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6308 BlitFramebufferHelper(
6309 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6310 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
6311 state_.enable_flags.scissor_test);
6314 void GLES2DecoderImpl::EnsureRenderbufferBound() {
6315 if (!state_.bound_renderbuffer_valid) {
6316 state_.bound_renderbuffer_valid = true;
6317 glBindRenderbufferEXT(GL_RENDERBUFFER,
6318 state_.bound_renderbuffer.get()
6319 ? state_.bound_renderbuffer->service_id()
6320 : 0);
6324 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6325 const FeatureInfo* feature_info,
6326 GLenum target,
6327 GLsizei samples,
6328 GLenum internal_format,
6329 GLsizei width,
6330 GLsizei height) {
6331 // TODO(sievers): This could be resolved at the GL binding level, but the
6332 // binding process is currently a bit too 'brute force'.
6333 if (feature_info->gl_version_info().is_angle) {
6334 glRenderbufferStorageMultisampleANGLE(
6335 target, samples, internal_format, width, height);
6336 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
6337 glRenderbufferStorageMultisample(
6338 target, samples, internal_format, width, height);
6339 } else {
6340 glRenderbufferStorageMultisampleEXT(
6341 target, samples, internal_format, width, height);
6345 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
6346 GLint srcY0,
6347 GLint srcX1,
6348 GLint srcY1,
6349 GLint dstX0,
6350 GLint dstY0,
6351 GLint dstX1,
6352 GLint dstY1,
6353 GLbitfield mask,
6354 GLenum filter) {
6355 // TODO(sievers): This could be resolved at the GL binding level, but the
6356 // binding process is currently a bit too 'brute force'.
6357 if (feature_info_->gl_version_info().is_angle) {
6358 glBlitFramebufferANGLE(
6359 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6360 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
6361 glBlitFramebuffer(
6362 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6363 } else {
6364 glBlitFramebufferEXT(
6365 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6369 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6370 GLsizei samples,
6371 GLenum internalformat,
6372 GLsizei width,
6373 GLsizei height) {
6374 if (samples > renderbuffer_manager()->max_samples()) {
6375 LOCAL_SET_GL_ERROR(
6376 GL_INVALID_VALUE,
6377 "glRenderbufferStorageMultisample", "samples too large");
6378 return false;
6381 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6382 height > renderbuffer_manager()->max_renderbuffer_size()) {
6383 LOCAL_SET_GL_ERROR(
6384 GL_INVALID_VALUE,
6385 "glRenderbufferStorageMultisample", "dimensions too large");
6386 return false;
6389 uint32 estimated_size = 0;
6390 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6391 width, height, samples, internalformat, &estimated_size)) {
6392 LOCAL_SET_GL_ERROR(
6393 GL_OUT_OF_MEMORY,
6394 "glRenderbufferStorageMultisample", "dimensions too large");
6395 return false;
6398 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6399 LOCAL_SET_GL_ERROR(
6400 GL_OUT_OF_MEMORY,
6401 "glRenderbufferStorageMultisample", "out of memory");
6402 return false;
6405 return true;
6408 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6409 GLenum target, GLsizei samples, GLenum internalformat,
6410 GLsizei width, GLsizei height) {
6411 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6412 if (!renderbuffer) {
6413 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6414 "glRenderbufferStorageMultisampleCHROMIUM",
6415 "no renderbuffer bound");
6416 return;
6419 if (!ValidateRenderbufferStorageMultisample(
6420 samples, internalformat, width, height)) {
6421 return;
6424 EnsureRenderbufferBound();
6425 GLenum impl_format =
6426 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6427 internalformat);
6428 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6429 "glRenderbufferStorageMultisampleCHROMIUM");
6430 RenderbufferStorageMultisampleHelper(
6431 feature_info_.get(), target, samples, impl_format, width, height);
6432 GLenum error =
6433 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6434 if (error == GL_NO_ERROR) {
6435 if (workarounds().validate_multisample_buffer_allocation) {
6436 if (!VerifyMultisampleRenderbufferIntegrity(
6437 renderbuffer->service_id(), impl_format)) {
6438 LOCAL_SET_GL_ERROR(
6439 GL_OUT_OF_MEMORY,
6440 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6441 return;
6445 // TODO(gman): If renderbuffers tracked which framebuffers they were
6446 // attached to we could just mark those framebuffers as not complete.
6447 framebuffer_manager()->IncFramebufferStateChangeCount();
6448 renderbuffer_manager()->SetInfo(
6449 renderbuffer, samples, internalformat, width, height);
6453 // This is the handler for multisampled_render_to_texture extensions.
6454 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6455 GLenum target, GLsizei samples, GLenum internalformat,
6456 GLsizei width, GLsizei height) {
6457 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6458 if (!renderbuffer) {
6459 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6460 "glRenderbufferStorageMultisampleEXT",
6461 "no renderbuffer bound");
6462 return;
6465 if (!ValidateRenderbufferStorageMultisample(
6466 samples, internalformat, width, height)) {
6467 return;
6470 EnsureRenderbufferBound();
6471 GLenum impl_format =
6472 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6473 internalformat);
6474 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6475 if (features().use_img_for_multisampled_render_to_texture) {
6476 glRenderbufferStorageMultisampleIMG(
6477 target, samples, impl_format, width, height);
6478 } else {
6479 glRenderbufferStorageMultisampleEXT(
6480 target, samples, impl_format, width, height);
6482 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6483 if (error == GL_NO_ERROR) {
6484 // TODO(gman): If renderbuffers tracked which framebuffers they were
6485 // attached to we could just mark those framebuffers as not complete.
6486 framebuffer_manager()->IncFramebufferStateChangeCount();
6487 renderbuffer_manager()->SetInfo(
6488 renderbuffer, samples, internalformat, width, height);
6492 // This function validates the allocation of a multisampled renderbuffer
6493 // by clearing it to a key color, blitting the contents to a texture, and
6494 // reading back the color to ensure it matches the key.
6495 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6496 GLuint renderbuffer, GLenum format) {
6498 // Only validate color buffers.
6499 // These formats have been selected because they are very common or are known
6500 // to be used by the WebGL backbuffer. If problems are observed with other
6501 // color formats they can be added here.
6502 switch (format) {
6503 case GL_RGB:
6504 case GL_RGB8:
6505 case GL_RGBA:
6506 case GL_RGBA8:
6507 break;
6508 default:
6509 return true;
6512 GLint draw_framebuffer, read_framebuffer;
6514 // Cache framebuffer and texture bindings.
6515 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
6516 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
6518 if (!validation_texture_) {
6519 GLint bound_texture;
6520 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
6522 // Create additional resources needed for the verification.
6523 glGenTextures(1, &validation_texture_);
6524 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
6525 glGenFramebuffersEXT(1, &validation_fbo_);
6527 // Texture only needs to be 1x1.
6528 glBindTexture(GL_TEXTURE_2D, validation_texture_);
6529 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6530 // multisample will fail if the color format of the source and destination
6531 // do not match. Here, we assume that the source is GL_RGBA, and make the
6532 // destination GL_RGBA. http://crbug.com/484203
6533 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
6534 GL_UNSIGNED_BYTE, NULL);
6536 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6537 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6538 GL_TEXTURE_2D, validation_texture_, 0);
6540 glBindTexture(GL_TEXTURE_2D, bound_texture);
6543 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6544 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6545 GL_RENDERBUFFER, renderbuffer);
6547 // Cache current state and reset it to the values we require.
6548 GLboolean scissor_enabled = false;
6549 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6550 if (scissor_enabled)
6551 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6553 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6554 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6555 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6557 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6558 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6559 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6561 // Clear the buffer to the desired key color.
6562 glClear(GL_COLOR_BUFFER_BIT);
6564 // Blit from the multisample buffer to a standard texture.
6565 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6566 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6568 BlitFramebufferHelper(
6569 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6571 // Read a pixel from the buffer.
6572 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6574 unsigned char pixel[3] = {0, 0, 0};
6575 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6577 // Detach the renderbuffer.
6578 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6579 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6580 GL_RENDERBUFFER, 0);
6582 // Restore cached state.
6583 if (scissor_enabled)
6584 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6586 state_.SetDeviceColorMask(
6587 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6588 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6589 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6590 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6592 // Return true if the pixel matched the desired key color.
6593 return (pixel[0] == 0xFF &&
6594 pixel[1] == 0x00 &&
6595 pixel[2] == 0xFF);
6598 void GLES2DecoderImpl::DoRenderbufferStorage(
6599 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6600 Renderbuffer* renderbuffer =
6601 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6602 if (!renderbuffer) {
6603 LOCAL_SET_GL_ERROR(
6604 GL_INVALID_OPERATION,
6605 "glRenderbufferStorage", "no renderbuffer bound");
6606 return;
6609 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6610 height > renderbuffer_manager()->max_renderbuffer_size()) {
6611 LOCAL_SET_GL_ERROR(
6612 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6613 return;
6616 uint32 estimated_size = 0;
6617 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6618 width, height, 1, internalformat, &estimated_size)) {
6619 LOCAL_SET_GL_ERROR(
6620 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6621 return;
6624 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6625 LOCAL_SET_GL_ERROR(
6626 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6627 return;
6630 EnsureRenderbufferBound();
6631 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6632 glRenderbufferStorageEXT(
6633 target,
6634 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6635 internalformat),
6636 width,
6637 height);
6638 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6639 if (error == GL_NO_ERROR) {
6640 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6641 // we could just mark those framebuffers as not complete.
6642 framebuffer_manager()->IncFramebufferStateChangeCount();
6643 renderbuffer_manager()->SetInfo(
6644 renderbuffer, 1, internalformat, width, height);
6648 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6649 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6650 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6651 Program* program = GetProgramInfoNotShader(
6652 program_id, "glLinkProgram");
6653 if (!program) {
6654 return;
6657 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6658 if (program->Link(shader_manager(),
6659 workarounds().count_all_in_varyings_packing ?
6660 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6661 shader_cache_callback_)) {
6662 if (program == state_.current_program.get()) {
6663 if (workarounds().use_current_program_after_successful_link)
6664 glUseProgram(program->service_id());
6665 if (workarounds().clear_uniforms_before_first_program_use)
6666 program_manager()->ClearUniforms(program);
6670 // LinkProgram can be very slow. Exit command processing to allow for
6671 // context preemption and GPU watchdog checks.
6672 ExitCommandProcessingEarly();
6675 void GLES2DecoderImpl::DoReadBuffer(GLenum src) {
6676 switch (src) {
6677 case GL_NONE:
6678 case GL_BACK:
6679 break;
6680 default:
6682 GLenum upper_limit = static_cast<GLenum>(
6683 group_->max_color_attachments() + GL_COLOR_ATTACHMENT0);
6684 if (src < GL_COLOR_ATTACHMENT0 || src >= upper_limit) {
6685 LOCAL_SET_GL_ERROR(
6686 GL_INVALID_ENUM, "glReadBuffer", "invalid enum for src");
6687 return;
6690 break;
6693 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
6694 if (framebuffer) {
6695 if (src == GL_BACK) {
6696 LOCAL_SET_GL_ERROR(
6697 GL_INVALID_ENUM, "glReadBuffer",
6698 "invalid src for a named framebuffer");
6699 return;
6701 framebuffer->set_read_buffer(src);
6702 } else {
6703 if (src != GL_NONE && src != GL_BACK) {
6704 LOCAL_SET_GL_ERROR(
6705 GL_INVALID_ENUM, "glReadBuffer",
6706 "invalid src for the default framebuffer");
6707 return;
6709 back_buffer_read_buffer_ = src;
6710 if (GetBackbufferServiceId() && src == GL_BACK)
6711 src = GL_COLOR_ATTACHMENT0;
6713 glReadBuffer(src);
6716 void GLES2DecoderImpl::DoSamplerParameterfv(
6717 GLuint sampler, GLenum pname, const GLfloat* params) {
6718 DCHECK(params);
6719 glSamplerParameterf(sampler, pname, params[0]);
6722 void GLES2DecoderImpl::DoSamplerParameteriv(
6723 GLuint sampler, GLenum pname, const GLint* params) {
6724 DCHECK(params);
6725 glSamplerParameteri(sampler, pname, params[0]);
6728 void GLES2DecoderImpl::DoTexParameterf(
6729 GLenum target, GLenum pname, GLfloat param) {
6730 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6731 &state_, target);
6732 if (!texture) {
6733 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6734 return;
6737 texture_manager()->SetParameterf(
6738 "glTexParameterf", GetErrorState(), texture, pname, param);
6741 void GLES2DecoderImpl::DoTexParameteri(
6742 GLenum target, GLenum pname, GLint param) {
6743 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6744 &state_, target);
6745 if (!texture) {
6746 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6747 return;
6750 texture_manager()->SetParameteri(
6751 "glTexParameteri", GetErrorState(), texture, pname, param);
6754 void GLES2DecoderImpl::DoTexParameterfv(
6755 GLenum target, GLenum pname, const GLfloat* params) {
6756 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6757 &state_, target);
6758 if (!texture) {
6759 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6760 return;
6763 texture_manager()->SetParameterf(
6764 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6767 void GLES2DecoderImpl::DoTexParameteriv(
6768 GLenum target, GLenum pname, const GLint* params) {
6769 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6770 &state_, target);
6771 if (!texture) {
6772 LOCAL_SET_GL_ERROR(
6773 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6774 return;
6777 texture_manager()->SetParameteri(
6778 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6781 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6782 if (!state_.bound_valuebuffer.get()) {
6783 // There is no valuebuffer bound
6784 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6785 "no valuebuffer in use");
6786 return false;
6788 return true;
6791 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6792 GLenum subscription,
6793 const char* function_name) {
6794 if (!CheckCurrentValuebuffer(function_name)) {
6795 return false;
6797 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6798 // The valuebuffer is not subscribed to the target
6799 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6800 "valuebuffer is not subscribed");
6801 return false;
6803 return true;
6806 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6807 GLenum subscription,
6808 const char* function_name) {
6809 if (!CheckCurrentProgramForUniform(location, function_name)) {
6810 return false;
6812 GLint real_location = -1;
6813 GLint array_index = -1;
6814 const Program::UniformInfo* info =
6815 state_.current_program->GetUniformInfoByFakeLocation(
6816 location, &real_location, &array_index);
6817 if (!info) {
6818 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6819 return false;
6821 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6822 info->accepts_api_type) == 0) {
6823 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6824 "wrong type for subscription");
6825 return false;
6827 return true;
6830 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6831 if (!state_.current_program.get()) {
6832 // The program does not exist.
6833 LOCAL_SET_GL_ERROR(
6834 GL_INVALID_OPERATION, function_name, "no program in use");
6835 return false;
6837 if (!state_.current_program->InUse()) {
6838 LOCAL_SET_GL_ERROR(
6839 GL_INVALID_OPERATION, function_name, "program not linked");
6840 return false;
6842 return true;
6845 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6846 GLint location, const char* function_name) {
6847 if (!CheckCurrentProgram(function_name)) {
6848 return false;
6850 return location != -1;
6853 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6854 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6855 if (!framebuffer)
6856 return false;
6857 const Framebuffer::Attachment* attachment =
6858 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6859 if (!attachment)
6860 return false;
6862 DCHECK(state_.current_program.get());
6863 const Program::SamplerIndices& sampler_indices =
6864 state_.current_program->sampler_indices();
6865 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6866 const Program::UniformInfo* uniform_info =
6867 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6868 DCHECK(uniform_info);
6869 if (uniform_info->type != GL_SAMPLER_2D)
6870 continue;
6871 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6872 GLuint texture_unit_index = uniform_info->texture_units[jj];
6873 if (texture_unit_index >= state_.texture_units.size())
6874 continue;
6875 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6876 TextureRef* texture_ref =
6877 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6878 if (attachment->IsTexture(texture_ref))
6879 return true;
6882 return false;
6885 bool GLES2DecoderImpl::CheckUniformForApiType(
6886 const Program::UniformInfo* info,
6887 const char* function_name,
6888 Program::UniformApiType api_type) {
6889 DCHECK(info);
6890 if ((api_type & info->accepts_api_type) == 0) {
6891 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6892 "wrong uniform function for type");
6893 return false;
6895 return true;
6898 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6899 GLint fake_location,
6900 const char* function_name,
6901 Program::UniformApiType api_type,
6902 GLint* real_location,
6903 GLenum* type,
6904 GLsizei* count) {
6905 DCHECK(type);
6906 DCHECK(count);
6907 DCHECK(real_location);
6909 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6910 return false;
6912 GLint array_index = -1;
6913 const Program::UniformInfo* info =
6914 state_.current_program->GetUniformInfoByFakeLocation(
6915 fake_location, real_location, &array_index);
6916 if (!info) {
6917 LOCAL_SET_GL_ERROR(
6918 GL_INVALID_OPERATION, function_name, "unknown location");
6919 return false;
6921 if (!CheckUniformForApiType(info, function_name, api_type)) {
6922 return false;
6924 if (*count > 1 && !info->is_array) {
6925 LOCAL_SET_GL_ERROR(
6926 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6927 return false;
6929 *count = std::min(info->size - array_index, *count);
6930 if (*count <= 0) {
6931 return false;
6933 *type = info->type;
6934 return true;
6937 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6938 GLenum type = 0;
6939 GLsizei count = 1;
6940 GLint real_location = -1;
6941 if (!PrepForSetUniformByLocation(fake_location,
6942 "glUniform1i",
6943 Program::kUniform1i,
6944 &real_location,
6945 &type,
6946 &count)) {
6947 return;
6949 if (!state_.current_program->SetSamplers(
6950 state_.texture_units.size(), fake_location, 1, &v0)) {
6951 LOCAL_SET_GL_ERROR(
6952 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6953 return;
6955 glUniform1i(real_location, v0);
6958 void GLES2DecoderImpl::DoUniform1iv(
6959 GLint fake_location, GLsizei count, const GLint *value) {
6960 GLenum type = 0;
6961 GLint real_location = -1;
6962 if (!PrepForSetUniformByLocation(fake_location,
6963 "glUniform1iv",
6964 Program::kUniform1i,
6965 &real_location,
6966 &type,
6967 &count)) {
6968 return;
6970 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6971 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6972 if (!state_.current_program->SetSamplers(
6973 state_.texture_units.size(), fake_location, count, value)) {
6974 LOCAL_SET_GL_ERROR(
6975 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6976 return;
6979 glUniform1iv(real_location, count, value);
6982 void GLES2DecoderImpl::DoUniform1uiv(
6983 GLint fake_location, GLsizei count, const GLuint *value) {
6984 GLenum type = 0;
6985 GLint real_location = -1;
6986 if (!PrepForSetUniformByLocation(fake_location,
6987 "glUniform1uiv",
6988 Program::kUniform1ui,
6989 &real_location,
6990 &type,
6991 &count)) {
6992 return;
6994 glUniform1uiv(real_location, count, value);
6997 void GLES2DecoderImpl::DoUniform1fv(
6998 GLint fake_location, GLsizei count, const GLfloat* value) {
6999 GLenum type = 0;
7000 GLint real_location = -1;
7001 if (!PrepForSetUniformByLocation(fake_location,
7002 "glUniform1fv",
7003 Program::kUniform1f,
7004 &real_location,
7005 &type,
7006 &count)) {
7007 return;
7009 if (type == GL_BOOL) {
7010 scoped_ptr<GLint[]> temp(new GLint[count]);
7011 for (GLsizei ii = 0; ii < count; ++ii) {
7012 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
7014 DoUniform1iv(real_location, count, temp.get());
7015 } else {
7016 glUniform1fv(real_location, count, value);
7020 void GLES2DecoderImpl::DoUniform2fv(
7021 GLint fake_location, GLsizei count, const GLfloat* value) {
7022 GLenum type = 0;
7023 GLint real_location = -1;
7024 if (!PrepForSetUniformByLocation(fake_location,
7025 "glUniform2fv",
7026 Program::kUniform2f,
7027 &real_location,
7028 &type,
7029 &count)) {
7030 return;
7032 if (type == GL_BOOL_VEC2) {
7033 GLsizei num_values = count * 2;
7034 scoped_ptr<GLint[]> temp(new GLint[num_values]);
7035 for (GLsizei ii = 0; ii < num_values; ++ii) {
7036 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
7038 glUniform2iv(real_location, count, temp.get());
7039 } else {
7040 glUniform2fv(real_location, count, value);
7044 void GLES2DecoderImpl::DoUniform3fv(
7045 GLint fake_location, GLsizei count, const GLfloat* value) {
7046 GLenum type = 0;
7047 GLint real_location = -1;
7048 if (!PrepForSetUniformByLocation(fake_location,
7049 "glUniform3fv",
7050 Program::kUniform3f,
7051 &real_location,
7052 &type,
7053 &count)) {
7054 return;
7056 if (type == GL_BOOL_VEC3) {
7057 GLsizei num_values = count * 3;
7058 scoped_ptr<GLint[]> temp(new GLint[num_values]);
7059 for (GLsizei ii = 0; ii < num_values; ++ii) {
7060 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
7062 glUniform3iv(real_location, count, temp.get());
7063 } else {
7064 glUniform3fv(real_location, count, value);
7068 void GLES2DecoderImpl::DoUniform4fv(
7069 GLint fake_location, GLsizei count, const GLfloat* value) {
7070 GLenum type = 0;
7071 GLint real_location = -1;
7072 if (!PrepForSetUniformByLocation(fake_location,
7073 "glUniform4fv",
7074 Program::kUniform4f,
7075 &real_location,
7076 &type,
7077 &count)) {
7078 return;
7080 if (type == GL_BOOL_VEC4) {
7081 GLsizei num_values = count * 4;
7082 scoped_ptr<GLint[]> temp(new GLint[num_values]);
7083 for (GLsizei ii = 0; ii < num_values; ++ii) {
7084 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
7086 glUniform4iv(real_location, count, temp.get());
7087 } else {
7088 glUniform4fv(real_location, count, value);
7092 void GLES2DecoderImpl::DoUniform2iv(
7093 GLint fake_location, GLsizei count, const GLint* value) {
7094 GLenum type = 0;
7095 GLint real_location = -1;
7096 if (!PrepForSetUniformByLocation(fake_location,
7097 "glUniform2iv",
7098 Program::kUniform2i,
7099 &real_location,
7100 &type,
7101 &count)) {
7102 return;
7104 glUniform2iv(real_location, count, value);
7107 void GLES2DecoderImpl::DoUniform2uiv(
7108 GLint fake_location, GLsizei count, const GLuint* value) {
7109 GLenum type = 0;
7110 GLint real_location = -1;
7111 if (!PrepForSetUniformByLocation(fake_location,
7112 "glUniform2uiv",
7113 Program::kUniform2ui,
7114 &real_location,
7115 &type,
7116 &count)) {
7117 return;
7119 glUniform2uiv(real_location, count, value);
7122 void GLES2DecoderImpl::DoUniform3iv(
7123 GLint fake_location, GLsizei count, const GLint* value) {
7124 GLenum type = 0;
7125 GLint real_location = -1;
7126 if (!PrepForSetUniformByLocation(fake_location,
7127 "glUniform3iv",
7128 Program::kUniform3i,
7129 &real_location,
7130 &type,
7131 &count)) {
7132 return;
7134 glUniform3iv(real_location, count, value);
7137 void GLES2DecoderImpl::DoUniform3uiv(
7138 GLint fake_location, GLsizei count, const GLuint* value) {
7139 GLenum type = 0;
7140 GLint real_location = -1;
7141 if (!PrepForSetUniformByLocation(fake_location,
7142 "glUniform3uiv",
7143 Program::kUniform3ui,
7144 &real_location,
7145 &type,
7146 &count)) {
7147 return;
7149 glUniform3uiv(real_location, count, value);
7152 void GLES2DecoderImpl::DoUniform4iv(
7153 GLint fake_location, GLsizei count, const GLint* value) {
7154 GLenum type = 0;
7155 GLint real_location = -1;
7156 if (!PrepForSetUniformByLocation(fake_location,
7157 "glUniform4iv",
7158 Program::kUniform4i,
7159 &real_location,
7160 &type,
7161 &count)) {
7162 return;
7164 glUniform4iv(real_location, count, value);
7167 void GLES2DecoderImpl::DoUniform4uiv(
7168 GLint fake_location, GLsizei count, const GLuint* value) {
7169 GLenum type = 0;
7170 GLint real_location = -1;
7171 if (!PrepForSetUniformByLocation(fake_location,
7172 "glUniform4uiv",
7173 Program::kUniform4ui,
7174 &real_location,
7175 &type,
7176 &count)) {
7177 return;
7179 glUniform4uiv(real_location, count, value);
7182 void GLES2DecoderImpl::DoUniformMatrix2fv(
7183 GLint fake_location, GLsizei count, GLboolean transpose,
7184 const GLfloat* value) {
7185 GLenum type = 0;
7186 GLint real_location = -1;
7187 if (!PrepForSetUniformByLocation(fake_location,
7188 "glUniformMatrix2fv",
7189 Program::kUniformMatrix2f,
7190 &real_location,
7191 &type,
7192 &count)) {
7193 return;
7195 glUniformMatrix2fv(real_location, count, transpose, value);
7198 void GLES2DecoderImpl::DoUniformMatrix3fv(
7199 GLint fake_location, GLsizei count, GLboolean transpose,
7200 const GLfloat* value) {
7201 GLenum type = 0;
7202 GLint real_location = -1;
7203 if (!PrepForSetUniformByLocation(fake_location,
7204 "glUniformMatrix3fv",
7205 Program::kUniformMatrix3f,
7206 &real_location,
7207 &type,
7208 &count)) {
7209 return;
7211 glUniformMatrix3fv(real_location, count, transpose, value);
7214 void GLES2DecoderImpl::DoUniformMatrix4fv(
7215 GLint fake_location, GLsizei count, GLboolean transpose,
7216 const GLfloat* value) {
7217 GLenum type = 0;
7218 GLint real_location = -1;
7219 if (!PrepForSetUniformByLocation(fake_location,
7220 "glUniformMatrix4fv",
7221 Program::kUniformMatrix4f,
7222 &real_location,
7223 &type,
7224 &count)) {
7225 return;
7227 glUniformMatrix4fv(real_location, count, transpose, value);
7230 void GLES2DecoderImpl::DoUniformMatrix2x3fv(
7231 GLint fake_location, GLsizei count, GLboolean transpose,
7232 const GLfloat* value) {
7233 GLenum type = 0;
7234 GLint real_location = -1;
7235 if (!PrepForSetUniformByLocation(fake_location,
7236 "glUniformMatrix2x3fv",
7237 Program::kUniformMatrix2x3f,
7238 &real_location,
7239 &type,
7240 &count)) {
7241 return;
7243 glUniformMatrix2x3fv(real_location, count, transpose, value);
7246 void GLES2DecoderImpl::DoUniformMatrix2x4fv(
7247 GLint fake_location, GLsizei count, GLboolean transpose,
7248 const GLfloat* value) {
7249 GLenum type = 0;
7250 GLint real_location = -1;
7251 if (!PrepForSetUniformByLocation(fake_location,
7252 "glUniformMatrix2x4fv",
7253 Program::kUniformMatrix2x4f,
7254 &real_location,
7255 &type,
7256 &count)) {
7257 return;
7259 glUniformMatrix2x4fv(real_location, count, transpose, value);
7262 void GLES2DecoderImpl::DoUniformMatrix3x2fv(
7263 GLint fake_location, GLsizei count, GLboolean transpose,
7264 const GLfloat* value) {
7265 GLenum type = 0;
7266 GLint real_location = -1;
7267 if (!PrepForSetUniformByLocation(fake_location,
7268 "glUniformMatrix3x2fv",
7269 Program::kUniformMatrix3x2f,
7270 &real_location,
7271 &type,
7272 &count)) {
7273 return;
7275 glUniformMatrix3x2fv(real_location, count, transpose, value);
7278 void GLES2DecoderImpl::DoUniformMatrix3x4fv(
7279 GLint fake_location, GLsizei count, GLboolean transpose,
7280 const GLfloat* value) {
7281 GLenum type = 0;
7282 GLint real_location = -1;
7283 if (!PrepForSetUniformByLocation(fake_location,
7284 "glUniformMatrix3x4fv",
7285 Program::kUniformMatrix3x4f,
7286 &real_location,
7287 &type,
7288 &count)) {
7289 return;
7291 glUniformMatrix3x4fv(real_location, count, transpose, value);
7294 void GLES2DecoderImpl::DoUniformMatrix4x2fv(
7295 GLint fake_location, GLsizei count, GLboolean transpose,
7296 const GLfloat* value) {
7297 GLenum type = 0;
7298 GLint real_location = -1;
7299 if (!PrepForSetUniformByLocation(fake_location,
7300 "glUniformMatrix4x2fv",
7301 Program::kUniformMatrix4x2f,
7302 &real_location,
7303 &type,
7304 &count)) {
7305 return;
7307 glUniformMatrix4x2fv(real_location, count, transpose, value);
7310 void GLES2DecoderImpl::DoUniformMatrix4x3fv(
7311 GLint fake_location, GLsizei count, GLboolean transpose,
7312 const GLfloat* value) {
7313 GLenum type = 0;
7314 GLint real_location = -1;
7315 if (!PrepForSetUniformByLocation(fake_location,
7316 "glUniformMatrix4x3fv",
7317 Program::kUniformMatrix4x3f,
7318 &real_location,
7319 &type,
7320 &count)) {
7321 return;
7323 glUniformMatrix4x3fv(real_location, count, transpose, value);
7326 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
7327 GLuint service_id = 0;
7328 Program* program = NULL;
7329 if (program_id) {
7330 program = GetProgramInfoNotShader(program_id, "glUseProgram");
7331 if (!program) {
7332 return;
7334 if (!program->IsValid()) {
7335 // Program was not linked successfully. (ie, glLinkProgram)
7336 LOCAL_SET_GL_ERROR(
7337 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
7338 return;
7340 service_id = program->service_id();
7342 if (state_.current_program.get()) {
7343 program_manager()->UnuseProgram(shader_manager(),
7344 state_.current_program.get());
7346 state_.current_program = program;
7347 LogClientServiceMapping("glUseProgram", program_id, service_id);
7348 glUseProgram(service_id);
7349 if (state_.current_program.get()) {
7350 program_manager()->UseProgram(state_.current_program.get());
7351 if (workarounds().clear_uniforms_before_first_program_use)
7352 program_manager()->ClearUniforms(program);
7356 void GLES2DecoderImpl::RenderWarning(
7357 const char* filename, int line, const std::string& msg) {
7358 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
7361 void GLES2DecoderImpl::PerformanceWarning(
7362 const char* filename, int line, const std::string& msg) {
7363 logger_.LogMessage(filename, line,
7364 std::string("PERFORMANCE WARNING: ") + msg);
7367 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
7368 Texture* texture, GLenum textarget) {
7369 // Image is already in use if texture is attached to a framebuffer.
7370 if (texture && !texture->IsAttachedToFramebuffer()) {
7371 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
7372 if (image) {
7373 ScopedGLErrorSuppressor suppressor(
7374 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
7375 GetErrorState());
7376 glBindTexture(textarget, texture->service_id());
7377 image->WillUseTexImage();
7378 RestoreCurrentTextureBindings(&state_, textarget);
7383 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
7384 Texture* texture, GLenum textarget) {
7385 // Image is still in use if texture is attached to a framebuffer.
7386 if (texture && !texture->IsAttachedToFramebuffer()) {
7387 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
7388 if (image) {
7389 ScopedGLErrorSuppressor suppressor(
7390 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
7391 GetErrorState());
7392 glBindTexture(textarget, texture->service_id());
7393 image->DidUseTexImage();
7394 RestoreCurrentTextureBindings(&state_, textarget);
7399 bool GLES2DecoderImpl::PrepareTexturesForRender() {
7400 DCHECK(state_.current_program.get());
7401 if (!texture_manager()->HaveUnrenderableTextures() &&
7402 !texture_manager()->HaveImages()) {
7403 return true;
7405 bool textures_set = false;
7406 const Program::SamplerIndices& sampler_indices =
7407 state_.current_program->sampler_indices();
7408 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7409 const Program::UniformInfo* uniform_info =
7410 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7411 DCHECK(uniform_info);
7412 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7413 GLuint texture_unit_index = uniform_info->texture_units[jj];
7414 if (texture_unit_index < state_.texture_units.size()) {
7415 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7416 TextureRef* texture_ref =
7417 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7418 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
7419 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
7420 textures_set = true;
7421 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7422 glBindTexture(
7423 textarget,
7424 texture_manager()->black_texture_id(uniform_info->type));
7425 if (!texture_ref) {
7426 LOCAL_RENDER_WARNING(
7427 std::string("there is no texture bound to the unit ") +
7428 base::UintToString(texture_unit_index));
7429 } else {
7430 LOCAL_RENDER_WARNING(
7431 std::string("texture bound to texture unit ") +
7432 base::UintToString(texture_unit_index) +
7433 " is not renderable. It maybe non-power-of-2 and have"
7434 " incompatible texture filtering.");
7436 continue;
7439 if (textarget != GL_TEXTURE_CUBE_MAP) {
7440 Texture* texture = texture_ref->texture();
7441 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
7442 if (image && !texture->IsAttachedToFramebuffer()) {
7443 ScopedGLErrorSuppressor suppressor(
7444 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
7445 textures_set = true;
7446 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7447 image->WillUseTexImage();
7448 continue;
7452 // else: should this be an error?
7455 return !textures_set;
7458 void GLES2DecoderImpl::RestoreStateForTextures() {
7459 DCHECK(state_.current_program.get());
7460 const Program::SamplerIndices& sampler_indices =
7461 state_.current_program->sampler_indices();
7462 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7463 const Program::UniformInfo* uniform_info =
7464 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7465 DCHECK(uniform_info);
7466 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7467 GLuint texture_unit_index = uniform_info->texture_units[jj];
7468 if (texture_unit_index < state_.texture_units.size()) {
7469 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7470 TextureRef* texture_ref =
7471 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7472 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
7473 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7474 // Get the texture_ref info that was previously bound here.
7475 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
7476 ? texture_unit.bound_texture_2d.get()
7477 : texture_unit.bound_texture_cube_map.get();
7478 glBindTexture(texture_unit.bind_target,
7479 texture_ref ? texture_ref->service_id() : 0);
7480 continue;
7483 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
7484 Texture* texture = texture_ref->texture();
7485 gfx::GLImage* image =
7486 texture->GetLevelImage(texture_unit.bind_target, 0);
7487 if (image && !texture->IsAttachedToFramebuffer()) {
7488 ScopedGLErrorSuppressor suppressor(
7489 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7490 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7491 image->DidUseTexImage();
7492 continue;
7498 // Set the active texture back to whatever the user had it as.
7499 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
7502 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7503 // Only check if there are some uncleared textures.
7504 if (!texture_manager()->HaveUnsafeTextures()) {
7505 return true;
7508 // 1: Check all textures we are about to render with.
7509 if (state_.current_program.get()) {
7510 const Program::SamplerIndices& sampler_indices =
7511 state_.current_program->sampler_indices();
7512 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7513 const Program::UniformInfo* uniform_info =
7514 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7515 DCHECK(uniform_info);
7516 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7517 GLuint texture_unit_index = uniform_info->texture_units[jj];
7518 if (texture_unit_index < state_.texture_units.size()) {
7519 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7520 TextureRef* texture_ref =
7521 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7522 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
7523 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
7524 return false;
7531 return true;
7534 bool GLES2DecoderImpl::IsDrawValid(
7535 const char* function_name, GLuint max_vertex_accessed, bool instanced,
7536 GLsizei primcount) {
7537 DCHECK(instanced || primcount == 1);
7539 // NOTE: We specifically do not check current_program->IsValid() because
7540 // it could never be invalid since glUseProgram would have failed. While
7541 // glLinkProgram could later mark the program as invalid the previous
7542 // valid program will still function if it is still the current program.
7543 if (!state_.current_program.get()) {
7544 // The program does not exist.
7545 // But GL says no ERROR.
7546 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7547 return false;
7550 if (CheckDrawingFeedbackLoops()) {
7551 LOCAL_SET_GL_ERROR(
7552 GL_INVALID_OPERATION, function_name,
7553 "Source and destination textures of the draw are the same.");
7554 return false;
7557 return state_.vertex_attrib_manager
7558 ->ValidateBindings(function_name,
7559 this,
7560 feature_info_.get(),
7561 state_.current_program.get(),
7562 max_vertex_accessed,
7563 instanced,
7564 primcount);
7567 bool GLES2DecoderImpl::SimulateAttrib0(
7568 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
7569 DCHECK(simulated);
7570 *simulated = false;
7572 if (feature_info_->gl_version_info().BehavesLikeGLES())
7573 return true;
7575 const VertexAttrib* attrib =
7576 state_.vertex_attrib_manager->GetVertexAttrib(0);
7577 // If it's enabled or it's not used then we don't need to do anything.
7578 bool attrib_0_used =
7579 state_.current_program->GetAttribInfoByLocation(0) != NULL;
7580 if (attrib->enabled() && attrib_0_used) {
7581 return true;
7584 // Make a buffer with a single repeated vec4 value enough to
7585 // simulate the constant value that is supposed to be here.
7586 // This is required to emulate GLES2 on GL.
7587 GLuint num_vertices = max_vertex_accessed + 1;
7588 uint32 size_needed = 0;
7590 if (num_vertices == 0 ||
7591 !SafeMultiplyUint32(num_vertices, sizeof(Vec4f), &size_needed) ||
7592 size_needed > 0x7FFFFFFFU) {
7593 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7594 return false;
7597 LOCAL_PERFORMANCE_WARNING(
7598 "Attribute 0 is disabled. This has signficant performance penalty");
7600 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7601 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
7603 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
7604 if (new_buffer) {
7605 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7606 GLenum error = glGetError();
7607 if (error != GL_NO_ERROR) {
7608 LOCAL_SET_GL_ERROR(
7609 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7610 return false;
7614 const Vec4& value = state_.attrib_values[0];
7615 if (new_buffer ||
7616 (attrib_0_used &&
7617 (!attrib_0_buffer_matches_value_ || !value.Equal(attrib_0_value_)))){
7618 // TODO(zmo): This is not 100% correct because we might lose data when
7619 // casting to float type, but it is a corner case and once we migrate to
7620 // core profiles on desktop GL, it is no longer relevant.
7621 Vec4f fvalue(value);
7622 std::vector<Vec4f> temp(num_vertices, fvalue);
7623 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
7624 attrib_0_buffer_matches_value_ = true;
7625 attrib_0_value_ = value;
7626 attrib_0_size_ = size_needed;
7629 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
7631 if (attrib->divisor())
7632 glVertexAttribDivisorANGLE(0, 0);
7634 *simulated = true;
7635 return true;
7638 void GLES2DecoderImpl::RestoreStateForAttrib(
7639 GLuint attrib_index, bool restore_array_binding) {
7640 const VertexAttrib* attrib =
7641 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
7642 if (restore_array_binding) {
7643 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
7644 Buffer* buffer = attrib->buffer();
7645 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
7646 glVertexAttribPointer(
7647 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
7648 attrib->gl_stride(), ptr);
7650 if (attrib->divisor())
7651 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
7652 glBindBuffer(
7653 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
7654 state_.bound_array_buffer->service_id() : 0);
7656 // Never touch vertex attribute 0's state (in particular, never
7657 // disable it) when running on desktop GL because it will never be
7658 // re-enabled.
7659 if (attrib_index != 0 ||
7660 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
7661 if (attrib->enabled()) {
7662 glEnableVertexAttribArray(attrib_index);
7663 } else {
7664 glDisableVertexAttribArray(attrib_index);
7669 bool GLES2DecoderImpl::SimulateFixedAttribs(
7670 const char* function_name,
7671 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
7672 DCHECK(simulated);
7673 *simulated = false;
7674 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
7675 return true;
7677 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
7678 return true;
7681 LOCAL_PERFORMANCE_WARNING(
7682 "GL_FIXED attributes have a signficant performance penalty");
7684 // NOTE: we could be smart and try to check if a buffer is used
7685 // twice in 2 different attribs, find the overlapping parts and therefore
7686 // duplicate the minimum amount of data but this whole code path is not meant
7687 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7688 // tests so we just add to the buffer attrib used.
7690 GLuint elements_needed = 0;
7691 const VertexAttribManager::VertexAttribList& enabled_attribs =
7692 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
7693 for (VertexAttribManager::VertexAttribList::const_iterator it =
7694 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7695 const VertexAttrib* attrib = *it;
7696 const Program::VertexAttrib* attrib_info =
7697 state_.current_program->GetAttribInfoByLocation(attrib->index());
7698 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7699 max_vertex_accessed);
7700 GLuint num_vertices = max_accessed + 1;
7701 if (num_vertices == 0) {
7702 LOCAL_SET_GL_ERROR(
7703 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7704 return false;
7706 if (attrib_info &&
7707 attrib->CanAccess(max_accessed) &&
7708 attrib->type() == GL_FIXED) {
7709 uint32 elements_used = 0;
7710 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
7711 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
7712 LOCAL_SET_GL_ERROR(
7713 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7714 return false;
7719 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
7720 uint32 size_needed = 0;
7721 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
7722 size_needed > 0x7FFFFFFFU) {
7723 LOCAL_SET_GL_ERROR(
7724 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7725 return false;
7728 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7730 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
7731 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
7732 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7733 GLenum error = glGetError();
7734 if (error != GL_NO_ERROR) {
7735 LOCAL_SET_GL_ERROR(
7736 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7737 return false;
7741 // Copy the elements and convert to float
7742 GLintptr offset = 0;
7743 for (VertexAttribManager::VertexAttribList::const_iterator it =
7744 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7745 const VertexAttrib* attrib = *it;
7746 const Program::VertexAttrib* attrib_info =
7747 state_.current_program->GetAttribInfoByLocation(attrib->index());
7748 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7749 max_vertex_accessed);
7750 GLuint num_vertices = max_accessed + 1;
7751 if (num_vertices == 0) {
7752 LOCAL_SET_GL_ERROR(
7753 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7754 return false;
7756 if (attrib_info &&
7757 attrib->CanAccess(max_accessed) &&
7758 attrib->type() == GL_FIXED) {
7759 int num_elements = attrib->size() * num_vertices;
7760 const int src_size = num_elements * sizeof(int32);
7761 const int dst_size = num_elements * sizeof(float);
7762 scoped_ptr<float[]> data(new float[num_elements]);
7763 const int32* src = reinterpret_cast<const int32 *>(
7764 attrib->buffer()->GetRange(attrib->offset(), src_size));
7765 const int32* end = src + num_elements;
7766 float* dst = data.get();
7767 while (src != end) {
7768 *dst++ = static_cast<float>(*src++) / 65536.0f;
7770 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7771 glVertexAttribPointer(
7772 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7773 reinterpret_cast<GLvoid*>(offset));
7774 offset += dst_size;
7777 *simulated = true;
7778 return true;
7781 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7782 // There's no need to call glVertexAttribPointer because we shadow all the
7783 // settings and passing GL_FIXED to it will not work.
7784 glBindBuffer(
7785 GL_ARRAY_BUFFER,
7786 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7787 : 0);
7790 error::Error GLES2DecoderImpl::DoDrawArrays(
7791 const char* function_name,
7792 bool instanced,
7793 GLenum mode,
7794 GLint first,
7795 GLsizei count,
7796 GLsizei primcount) {
7797 error::Error error = WillAccessBoundFramebufferForDraw();
7798 if (error != error::kNoError)
7799 return error;
7800 if (!validators_->draw_mode.IsValid(mode)) {
7801 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7802 return error::kNoError;
7804 if (count < 0) {
7805 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7806 return error::kNoError;
7808 if (primcount < 0) {
7809 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7810 return error::kNoError;
7812 if (!CheckBoundFramebuffersValid(function_name)) {
7813 return error::kNoError;
7815 // We have to check this here because the prototype for glDrawArrays
7816 // is GLint not GLsizei.
7817 if (first < 0) {
7818 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7819 return error::kNoError;
7822 if (count == 0 || primcount == 0) {
7823 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7824 return error::kNoError;
7827 GLuint max_vertex_accessed = first + count - 1;
7828 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7829 if (!ClearUnclearedTextures()) {
7830 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7831 return error::kNoError;
7833 bool simulated_attrib_0 = false;
7834 if (!SimulateAttrib0(
7835 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7836 return error::kNoError;
7838 bool simulated_fixed_attribs = false;
7839 if (SimulateFixedAttribs(
7840 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7841 primcount)) {
7842 bool textures_set = !PrepareTexturesForRender();
7843 ApplyDirtyState();
7844 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7845 if (!instanced) {
7846 glDrawArrays(mode, first, count);
7847 } else {
7848 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7850 if (textures_set) {
7851 RestoreStateForTextures();
7853 if (simulated_fixed_attribs) {
7854 RestoreStateForSimulatedFixedAttribs();
7857 if (simulated_attrib_0) {
7858 // We don't have to restore attrib 0 generic data at the end of this
7859 // function even if it is simulated. This is because we will simulate
7860 // it in each draw call, and attrib 0 generic data queries use cached
7861 // values instead of passing down to the underlying driver.
7862 RestoreStateForAttrib(0, false);
7865 return error::kNoError;
7868 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7869 const void* cmd_data) {
7870 // TODO(zmo): crbug.com/481184
7871 // On Desktop GL with versions lower than 4.3, we need to emulate
7872 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7873 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7874 return DoDrawArrays("glDrawArrays",
7875 false,
7876 static_cast<GLenum>(c.mode),
7877 static_cast<GLint>(c.first),
7878 static_cast<GLsizei>(c.count),
7882 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7883 uint32 immediate_data_size,
7884 const void* cmd_data) {
7885 const gles2::cmds::DrawArraysInstancedANGLE& c =
7886 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7887 if (!features().angle_instanced_arrays) {
7888 LOCAL_SET_GL_ERROR(
7889 GL_INVALID_OPERATION,
7890 "glDrawArraysInstancedANGLE", "function not available");
7891 return error::kNoError;
7893 return DoDrawArrays("glDrawArraysIntancedANGLE",
7894 true,
7895 static_cast<GLenum>(c.mode),
7896 static_cast<GLint>(c.first),
7897 static_cast<GLsizei>(c.count),
7898 static_cast<GLsizei>(c.primcount));
7901 error::Error GLES2DecoderImpl::DoDrawElements(
7902 const char* function_name,
7903 bool instanced,
7904 GLenum mode,
7905 GLsizei count,
7906 GLenum type,
7907 int32 offset,
7908 GLsizei primcount) {
7909 error::Error error = WillAccessBoundFramebufferForDraw();
7910 if (error != error::kNoError)
7911 return error;
7912 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7913 LOCAL_SET_GL_ERROR(
7914 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7915 return error::kNoError;
7918 if (count < 0) {
7919 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7920 return error::kNoError;
7922 if (offset < 0) {
7923 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7924 return error::kNoError;
7926 if (!validators_->draw_mode.IsValid(mode)) {
7927 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7928 return error::kNoError;
7930 if (!validators_->index_type.IsValid(type)) {
7931 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7932 return error::kNoError;
7934 if (primcount < 0) {
7935 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7936 return error::kNoError;
7939 if (!CheckBoundFramebuffersValid(function_name)) {
7940 return error::kNoError;
7943 if (count == 0 || primcount == 0) {
7944 return error::kNoError;
7947 GLuint max_vertex_accessed;
7948 Buffer* element_array_buffer =
7949 state_.vertex_attrib_manager->element_array_buffer();
7951 if (!element_array_buffer->GetMaxValueForRange(
7952 offset, count, type, &max_vertex_accessed)) {
7953 LOCAL_SET_GL_ERROR(
7954 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7955 return error::kNoError;
7958 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7959 if (!ClearUnclearedTextures()) {
7960 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7961 return error::kNoError;
7963 bool simulated_attrib_0 = false;
7964 if (!SimulateAttrib0(
7965 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7966 return error::kNoError;
7968 bool simulated_fixed_attribs = false;
7969 if (SimulateFixedAttribs(
7970 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7971 primcount)) {
7972 bool textures_set = !PrepareTexturesForRender();
7973 ApplyDirtyState();
7974 // TODO(gman): Refactor to hide these details in BufferManager or
7975 // VertexAttribManager.
7976 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7977 bool used_client_side_array = false;
7978 if (element_array_buffer->IsClientSideArray()) {
7979 used_client_side_array = true;
7980 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7981 indices = element_array_buffer->GetRange(offset, 0);
7984 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7985 if (!instanced) {
7986 glDrawElements(mode, count, type, indices);
7987 } else {
7988 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7991 if (used_client_side_array) {
7992 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7993 element_array_buffer->service_id());
7996 if (textures_set) {
7997 RestoreStateForTextures();
7999 if (simulated_fixed_attribs) {
8000 RestoreStateForSimulatedFixedAttribs();
8003 if (simulated_attrib_0) {
8004 // We don't have to restore attrib 0 generic data at the end of this
8005 // function even if it is simulated. This is because we will simulate
8006 // it in each draw call, and attrib 0 generic data queries use cached
8007 // values instead of passing down to the underlying driver.
8008 RestoreStateForAttrib(0, false);
8011 return error::kNoError;
8014 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
8015 const void* cmd_data) {
8016 // TODO(zmo): crbug.com/481184
8017 // On Desktop GL with versions lower than 4.3, we need to emulate
8018 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
8019 const gles2::cmds::DrawElements& c =
8020 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
8021 return DoDrawElements("glDrawElements",
8022 false,
8023 static_cast<GLenum>(c.mode),
8024 static_cast<GLsizei>(c.count),
8025 static_cast<GLenum>(c.type),
8026 static_cast<int32>(c.index_offset),
8030 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
8031 uint32 immediate_data_size,
8032 const void* cmd_data) {
8033 const gles2::cmds::DrawElementsInstancedANGLE& c =
8034 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
8035 if (!features().angle_instanced_arrays) {
8036 LOCAL_SET_GL_ERROR(
8037 GL_INVALID_OPERATION,
8038 "glDrawElementsInstancedANGLE", "function not available");
8039 return error::kNoError;
8041 return DoDrawElements("glDrawElementsInstancedANGLE",
8042 true,
8043 static_cast<GLenum>(c.mode),
8044 static_cast<GLsizei>(c.count),
8045 static_cast<GLenum>(c.type),
8046 static_cast<int32>(c.index_offset),
8047 static_cast<GLsizei>(c.primcount));
8050 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
8051 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
8052 GLuint max_vertex_accessed = 0;
8053 Buffer* buffer = GetBuffer(buffer_id);
8054 if (!buffer) {
8055 // TODO(gman): Should this be a GL error or a command buffer error?
8056 LOCAL_SET_GL_ERROR(
8057 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
8058 } else {
8059 if (!buffer->GetMaxValueForRange(
8060 offset, count, type, &max_vertex_accessed)) {
8061 // TODO(gman): Should this be a GL error or a command buffer error?
8062 LOCAL_SET_GL_ERROR(
8063 GL_INVALID_OPERATION,
8064 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
8067 return max_vertex_accessed;
8070 void GLES2DecoderImpl::DoShaderSource(
8071 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
8072 std::string str;
8073 for (GLsizei ii = 0; ii < count; ++ii) {
8074 if (length && length[ii] > 0)
8075 str.append(data[ii], length[ii]);
8076 else
8077 str.append(data[ii]);
8079 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
8080 if (!shader) {
8081 return;
8083 // Note: We don't actually call glShaderSource here. We wait until
8084 // we actually compile the shader.
8085 shader->set_source(str);
8088 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
8089 GLuint client_program_id, GLsizei count, const char* const* varyings,
8090 GLenum buffer_mode) {
8091 Program* program = GetProgramInfoNotShader(
8092 client_program_id, "glTransformFeedbackVaryings");
8093 if (!program) {
8094 return;
8096 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
8099 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
8100 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
8101 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
8102 if (!shader) {
8103 return;
8106 scoped_refptr<ShaderTranslatorInterface> translator;
8107 if (!feature_info_->disable_shader_translator()) {
8108 translator = shader->shader_type() == GL_VERTEX_SHADER ?
8109 vertex_translator_ : fragment_translator_;
8112 const Shader::TranslatedShaderSourceType source_type =
8113 feature_info_->feature_flags().angle_translated_shader_source ?
8114 Shader::kANGLE : Shader::kGL;
8115 shader->RequestCompile(translator, source_type);
8118 void GLES2DecoderImpl::DoGetShaderiv(
8119 GLuint shader_id, GLenum pname, GLint* params) {
8120 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
8121 if (!shader) {
8122 return;
8125 // Compile now for statuses that require it.
8126 switch (pname) {
8127 case GL_COMPILE_STATUS:
8128 case GL_INFO_LOG_LENGTH:
8129 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
8130 shader->DoCompile();
8131 break;
8133 default:
8134 break;
8137 switch (pname) {
8138 case GL_SHADER_SOURCE_LENGTH:
8139 *params = shader->source().size();
8140 if (*params)
8141 ++(*params);
8142 return;
8143 case GL_COMPILE_STATUS:
8144 *params = compile_shader_always_succeeds_ ? true : shader->valid();
8145 return;
8146 case GL_INFO_LOG_LENGTH:
8147 *params = shader->log_info().size();
8148 if (*params)
8149 ++(*params);
8150 return;
8151 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
8152 *params = shader->translated_source().size();
8153 if (*params)
8154 ++(*params);
8155 return;
8156 default:
8157 break;
8159 glGetShaderiv(shader->service_id(), pname, params);
8162 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
8163 const void* cmd_data) {
8164 const gles2::cmds::GetShaderSource& c =
8165 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
8166 GLuint shader_id = c.shader;
8167 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8168 Bucket* bucket = CreateBucket(bucket_id);
8169 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
8170 if (!shader || shader->source().empty()) {
8171 bucket->SetSize(0);
8172 return error::kNoError;
8174 bucket->SetFromString(shader->source().c_str());
8175 return error::kNoError;
8178 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
8179 uint32 immediate_data_size,
8180 const void* cmd_data) {
8181 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
8182 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
8183 cmd_data);
8184 GLuint shader_id = c.shader;
8185 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8186 Bucket* bucket = CreateBucket(bucket_id);
8187 Shader* shader = GetShaderInfoNotProgram(
8188 shader_id, "glGetTranslatedShaderSourceANGLE");
8189 if (!shader) {
8190 bucket->SetSize(0);
8191 return error::kNoError;
8194 // Make sure translator has been utilized in compile.
8195 shader->DoCompile();
8197 bucket->SetFromString(shader->translated_source().c_str());
8198 return error::kNoError;
8201 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
8202 uint32 immediate_data_size,
8203 const void* cmd_data) {
8204 const gles2::cmds::GetProgramInfoLog& c =
8205 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
8206 GLuint program_id = c.program;
8207 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8208 Bucket* bucket = CreateBucket(bucket_id);
8209 Program* program = GetProgramInfoNotShader(
8210 program_id, "glGetProgramInfoLog");
8211 if (!program || !program->log_info()) {
8212 bucket->SetFromString("");
8213 return error::kNoError;
8215 bucket->SetFromString(program->log_info()->c_str());
8216 return error::kNoError;
8219 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
8220 uint32 immediate_data_size,
8221 const void* cmd_data) {
8222 const gles2::cmds::GetShaderInfoLog& c =
8223 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
8224 GLuint shader_id = c.shader;
8225 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8226 Bucket* bucket = CreateBucket(bucket_id);
8227 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
8228 if (!shader) {
8229 bucket->SetFromString("");
8230 return error::kNoError;
8233 // Shader must be compiled in order to get the info log.
8234 shader->DoCompile();
8236 bucket->SetFromString(shader->log_info().c_str());
8237 return error::kNoError;
8240 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
8241 return state_.GetEnabled(cap);
8244 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
8245 const Buffer* buffer = GetBuffer(client_id);
8246 return buffer && buffer->IsValid() && !buffer->IsDeleted();
8249 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
8250 const Framebuffer* framebuffer =
8251 GetFramebuffer(client_id);
8252 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
8255 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
8256 // IsProgram is true for programs as soon as they are created, until they are
8257 // deleted and no longer in use.
8258 const Program* program = GetProgram(client_id);
8259 return program != NULL && !program->IsDeleted();
8262 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
8263 const Renderbuffer* renderbuffer =
8264 GetRenderbuffer(client_id);
8265 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
8268 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
8269 // IsShader is true for shaders as soon as they are created, until they
8270 // are deleted and not attached to any programs.
8271 const Shader* shader = GetShader(client_id);
8272 return shader != NULL && !shader->IsDeleted();
8275 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
8276 const TextureRef* texture_ref = GetTexture(client_id);
8277 return texture_ref && texture_ref->texture()->IsValid();
8280 void GLES2DecoderImpl::DoAttachShader(
8281 GLuint program_client_id, GLint shader_client_id) {
8282 Program* program = GetProgramInfoNotShader(
8283 program_client_id, "glAttachShader");
8284 if (!program) {
8285 return;
8287 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
8288 if (!shader) {
8289 return;
8291 if (!program->AttachShader(shader_manager(), shader)) {
8292 LOCAL_SET_GL_ERROR(
8293 GL_INVALID_OPERATION,
8294 "glAttachShader",
8295 "can not attach more than one shader of the same type.");
8296 return;
8298 glAttachShader(program->service_id(), shader->service_id());
8301 void GLES2DecoderImpl::DoDetachShader(
8302 GLuint program_client_id, GLint shader_client_id) {
8303 Program* program = GetProgramInfoNotShader(
8304 program_client_id, "glDetachShader");
8305 if (!program) {
8306 return;
8308 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
8309 if (!shader) {
8310 return;
8312 if (!program->DetachShader(shader_manager(), shader)) {
8313 LOCAL_SET_GL_ERROR(
8314 GL_INVALID_OPERATION,
8315 "glDetachShader", "shader not attached to program");
8316 return;
8318 glDetachShader(program->service_id(), shader->service_id());
8321 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
8322 Program* program = GetProgramInfoNotShader(
8323 program_client_id, "glValidateProgram");
8324 if (!program) {
8325 return;
8327 program->Validate();
8330 void GLES2DecoderImpl::GetVertexAttribHelper(
8331 const VertexAttrib* attrib, GLenum pname, GLint* params) {
8332 switch (pname) {
8333 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
8335 Buffer* buffer = attrib->buffer();
8336 if (buffer && !buffer->IsDeleted()) {
8337 GLuint client_id;
8338 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
8339 *params = client_id;
8341 break;
8343 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
8344 *params = attrib->enabled();
8345 break;
8346 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
8347 *params = attrib->size();
8348 break;
8349 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
8350 *params = attrib->gl_stride();
8351 break;
8352 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
8353 *params = attrib->type();
8354 break;
8355 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
8356 *params = attrib->normalized();
8357 break;
8358 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
8359 *params = attrib->divisor();
8360 break;
8361 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
8362 *params = attrib->integer();
8363 break;
8364 default:
8365 NOTREACHED();
8366 break;
8370 void GLES2DecoderImpl::DoGetTexParameterfv(
8371 GLenum target, GLenum pname, GLfloat* params) {
8372 InitTextureMaxAnisotropyIfNeeded(target, pname);
8373 glGetTexParameterfv(target, pname, params);
8376 void GLES2DecoderImpl::DoGetTexParameteriv(
8377 GLenum target, GLenum pname, GLint* params) {
8378 InitTextureMaxAnisotropyIfNeeded(target, pname);
8379 glGetTexParameteriv(target, pname, params);
8382 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
8383 GLenum target, GLenum pname) {
8384 if (!workarounds().init_texture_max_anisotropy)
8385 return;
8386 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
8387 !validators_->texture_parameter.IsValid(pname)) {
8388 return;
8391 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8392 &state_, target);
8393 if (!texture_ref) {
8394 LOCAL_SET_GL_ERROR(
8395 GL_INVALID_OPERATION,
8396 "glGetTexParamter{fi}v", "unknown texture for target");
8397 return;
8399 Texture* texture = texture_ref->texture();
8400 texture->InitTextureMaxAnisotropyIfNeeded(target);
8403 template <typename T>
8404 void GLES2DecoderImpl::DoGetVertexAttribImpl(
8405 GLuint index, GLenum pname, T* params) {
8406 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
8407 if (!attrib) {
8408 LOCAL_SET_GL_ERROR(
8409 GL_INVALID_VALUE, "glGetVertexAttrib", "index out of range");
8410 return;
8412 switch (pname) {
8413 case GL_CURRENT_VERTEX_ATTRIB:
8414 state_.attrib_values[index].GetValues(params);
8415 break;
8416 default: {
8417 GLint value = 0;
8418 GetVertexAttribHelper(attrib, pname, &value);
8419 *params = static_cast<T>(value);
8420 break;
8425 void GLES2DecoderImpl::DoGetVertexAttribfv(
8426 GLuint index, GLenum pname, GLfloat* params) {
8427 DoGetVertexAttribImpl<GLfloat>(index, pname, params);
8430 void GLES2DecoderImpl::DoGetVertexAttribiv(
8431 GLuint index, GLenum pname, GLint* params) {
8432 DoGetVertexAttribImpl<GLint>(index, pname, params);
8435 void GLES2DecoderImpl::DoGetVertexAttribIiv(
8436 GLuint index, GLenum pname, GLint* params) {
8437 DoGetVertexAttribImpl<GLint>(index, pname, params);
8440 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
8441 GLuint index, GLenum pname, GLuint* params) {
8442 DoGetVertexAttribImpl<GLuint>(index, pname, params);
8445 template <typename T>
8446 bool GLES2DecoderImpl::SetVertexAttribValue(
8447 const char* function_name, GLuint index, const T* value) {
8448 if (index >= state_.attrib_values.size()) {
8449 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
8450 return false;
8452 state_.attrib_values[index].SetValues(value);
8453 return true;
8456 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
8457 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
8458 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
8459 glVertexAttrib1f(index, v0);
8463 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
8464 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
8465 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
8466 glVertexAttrib2f(index, v0, v1);
8470 void GLES2DecoderImpl::DoVertexAttrib3f(
8471 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
8472 GLfloat v[4] = { v0, v1, v2, 1.0f, };
8473 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
8474 glVertexAttrib3f(index, v0, v1, v2);
8478 void GLES2DecoderImpl::DoVertexAttrib4f(
8479 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
8480 GLfloat v[4] = { v0, v1, v2, v3, };
8481 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
8482 glVertexAttrib4f(index, v0, v1, v2, v3);
8486 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
8487 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
8488 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
8489 glVertexAttrib1fv(index, v);
8493 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
8494 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
8495 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
8496 glVertexAttrib2fv(index, v);
8500 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
8501 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
8502 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
8503 glVertexAttrib3fv(index, v);
8507 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
8508 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
8509 glVertexAttrib4fv(index, v);
8513 void GLES2DecoderImpl::DoVertexAttribI4i(
8514 GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
8515 GLint v[4] = { v0, v1, v2, v3 };
8516 if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
8517 glVertexAttribI4i(index, v0, v1, v2, v3);
8521 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
8522 if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
8523 glVertexAttribI4iv(index, v);
8527 void GLES2DecoderImpl::DoVertexAttribI4ui(
8528 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
8529 GLuint v[4] = { v0, v1, v2, v3 };
8530 if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
8531 glVertexAttribI4ui(index, v0, v1, v2, v3);
8535 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
8536 if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
8537 glVertexAttribI4uiv(index, v);
8541 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
8542 uint32 immediate_data_size,
8543 const void* cmd_data) {
8544 if (!unsafe_es3_apis_enabled())
8545 return error::kUnknownCommand;
8546 const gles2::cmds::VertexAttribIPointer& c =
8547 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
8549 if (!state_.bound_array_buffer.get() ||
8550 state_.bound_array_buffer->IsDeleted()) {
8551 if (state_.vertex_attrib_manager.get() ==
8552 state_.default_vertex_attrib_manager.get()) {
8553 LOCAL_SET_GL_ERROR(
8554 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
8555 return error::kNoError;
8556 } else if (c.offset != 0) {
8557 LOCAL_SET_GL_ERROR(
8558 GL_INVALID_VALUE,
8559 "glVertexAttribIPointer", "client side arrays are not allowed");
8560 return error::kNoError;
8564 GLuint indx = c.indx;
8565 GLint size = c.size;
8566 GLenum type = c.type;
8567 GLsizei stride = c.stride;
8568 GLsizei offset = c.offset;
8569 const void* ptr = reinterpret_cast<const void*>(offset);
8570 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
8571 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
8572 return error::kNoError;
8574 if (!validators_->vertex_attrib_size.IsValid(size)) {
8575 LOCAL_SET_GL_ERROR(
8576 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8577 return error::kNoError;
8579 if (indx >= group_->max_vertex_attribs()) {
8580 LOCAL_SET_GL_ERROR(
8581 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
8582 return error::kNoError;
8584 if (stride < 0) {
8585 LOCAL_SET_GL_ERROR(
8586 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
8587 return error::kNoError;
8589 if (stride > 255) {
8590 LOCAL_SET_GL_ERROR(
8591 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
8592 return error::kNoError;
8594 if (offset < 0) {
8595 LOCAL_SET_GL_ERROR(
8596 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
8597 return error::kNoError;
8599 GLsizei component_size =
8600 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8601 // component_size must be a power of two to use & as optimized modulo.
8602 DCHECK(GLES2Util::IsPOT(component_size));
8603 if (offset & (component_size - 1)) {
8604 LOCAL_SET_GL_ERROR(
8605 GL_INVALID_OPERATION,
8606 "glVertexAttribIPointer", "offset not valid for type");
8607 return error::kNoError;
8609 if (stride & (component_size - 1)) {
8610 LOCAL_SET_GL_ERROR(
8611 GL_INVALID_OPERATION,
8612 "glVertexAttribIPointer", "stride not valid for type");
8613 return error::kNoError;
8615 state_.vertex_attrib_manager
8616 ->SetAttribInfo(indx,
8617 state_.bound_array_buffer.get(),
8618 size,
8619 type,
8620 GL_FALSE,
8621 stride,
8622 stride != 0 ? stride : component_size * size,
8623 offset,
8624 GL_TRUE);
8625 glVertexAttribIPointer(indx, size, type, stride, ptr);
8626 return error::kNoError;
8629 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
8630 uint32 immediate_data_size,
8631 const void* cmd_data) {
8632 const gles2::cmds::VertexAttribPointer& c =
8633 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
8635 if (!state_.bound_array_buffer.get() ||
8636 state_.bound_array_buffer->IsDeleted()) {
8637 if (state_.vertex_attrib_manager.get() ==
8638 state_.default_vertex_attrib_manager.get()) {
8639 LOCAL_SET_GL_ERROR(
8640 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
8641 return error::kNoError;
8642 } else if (c.offset != 0) {
8643 LOCAL_SET_GL_ERROR(
8644 GL_INVALID_VALUE,
8645 "glVertexAttribPointer", "client side arrays are not allowed");
8646 return error::kNoError;
8650 GLuint indx = c.indx;
8651 GLint size = c.size;
8652 GLenum type = c.type;
8653 GLboolean normalized = static_cast<GLboolean>(c.normalized);
8654 GLsizei stride = c.stride;
8655 GLsizei offset = c.offset;
8656 const void* ptr = reinterpret_cast<const void*>(offset);
8657 if (!validators_->vertex_attrib_type.IsValid(type)) {
8658 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
8659 return error::kNoError;
8661 if (!validators_->vertex_attrib_size.IsValid(size)) {
8662 LOCAL_SET_GL_ERROR(
8663 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8664 return error::kNoError;
8666 if (indx >= group_->max_vertex_attribs()) {
8667 LOCAL_SET_GL_ERROR(
8668 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
8669 return error::kNoError;
8671 if (stride < 0) {
8672 LOCAL_SET_GL_ERROR(
8673 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
8674 return error::kNoError;
8676 if (stride > 255) {
8677 LOCAL_SET_GL_ERROR(
8678 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
8679 return error::kNoError;
8681 if (offset < 0) {
8682 LOCAL_SET_GL_ERROR(
8683 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
8684 return error::kNoError;
8686 GLsizei component_size =
8687 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8688 // component_size must be a power of two to use & as optimized modulo.
8689 DCHECK(GLES2Util::IsPOT(component_size));
8690 if (offset & (component_size - 1)) {
8691 LOCAL_SET_GL_ERROR(
8692 GL_INVALID_OPERATION,
8693 "glVertexAttribPointer", "offset not valid for type");
8694 return error::kNoError;
8696 if (stride & (component_size - 1)) {
8697 LOCAL_SET_GL_ERROR(
8698 GL_INVALID_OPERATION,
8699 "glVertexAttribPointer", "stride not valid for type");
8700 return error::kNoError;
8702 state_.vertex_attrib_manager
8703 ->SetAttribInfo(indx,
8704 state_.bound_array_buffer.get(),
8705 size,
8706 type,
8707 normalized,
8708 stride,
8709 stride != 0 ? stride : component_size * size,
8710 offset,
8711 GL_FALSE);
8712 // We support GL_FIXED natively on EGL/GLES2 implementations
8713 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
8714 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
8716 return error::kNoError;
8719 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
8720 GLsizei height) {
8721 state_.viewport_x = x;
8722 state_.viewport_y = y;
8723 state_.viewport_width = std::min(width, viewport_max_width_);
8724 state_.viewport_height = std::min(height, viewport_max_height_);
8725 glViewport(x, y, width, height);
8728 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8729 uint32 immediate_data_size,
8730 const void* cmd_data) {
8731 const gles2::cmds::VertexAttribDivisorANGLE& c =
8732 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
8733 if (!features().angle_instanced_arrays) {
8734 LOCAL_SET_GL_ERROR(
8735 GL_INVALID_OPERATION,
8736 "glVertexAttribDivisorANGLE", "function not available");
8737 return error::kNoError;
8739 GLuint index = c.index;
8740 GLuint divisor = c.divisor;
8741 if (index >= group_->max_vertex_attribs()) {
8742 LOCAL_SET_GL_ERROR(
8743 GL_INVALID_VALUE,
8744 "glVertexAttribDivisorANGLE", "index out of range");
8745 return error::kNoError;
8748 state_.vertex_attrib_manager->SetDivisor(
8749 index,
8750 divisor);
8751 glVertexAttribDivisorANGLE(index, divisor);
8752 return error::kNoError;
8755 template <typename pixel_data_type>
8756 static void WriteAlphaData(
8757 void* pixels, uint32 row_count, uint32 channel_count,
8758 uint32 alpha_channel_index, uint32 unpadded_row_size,
8759 uint32 padded_row_size, pixel_data_type alpha_value) {
8760 DCHECK_GT(channel_count, 0U);
8761 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8762 uint32 unpadded_row_size_in_elements =
8763 unpadded_row_size / sizeof(pixel_data_type);
8764 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8765 uint32 padded_row_size_in_elements =
8766 padded_row_size / sizeof(pixel_data_type);
8767 pixel_data_type* dst =
8768 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8769 for (uint32 yy = 0; yy < row_count; ++yy) {
8770 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8771 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8772 *d = alpha_value;
8774 dst += padded_row_size_in_elements;
8778 void GLES2DecoderImpl::FinishReadPixels(
8779 const cmds::ReadPixels& c,
8780 GLuint buffer) {
8781 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8782 GLsizei width = c.width;
8783 GLsizei height = c.height;
8784 GLenum format = c.format;
8785 GLenum type = c.type;
8786 typedef cmds::ReadPixels::Result Result;
8787 uint32 pixels_size;
8788 Result* result = NULL;
8789 if (c.result_shm_id != 0) {
8790 result = GetSharedMemoryAs<Result*>(
8791 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8792 if (!result) {
8793 if (buffer != 0) {
8794 glDeleteBuffersARB(1, &buffer);
8796 return;
8799 GLES2Util::ComputeImageDataSizes(
8800 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8801 NULL, NULL);
8802 void* pixels = GetSharedMemoryAs<void*>(
8803 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8804 if (!pixels) {
8805 if (buffer != 0) {
8806 glDeleteBuffersARB(1, &buffer);
8808 return;
8811 if (buffer != 0) {
8812 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8813 void* data;
8814 if (features().map_buffer_range) {
8815 data = glMapBufferRange(
8816 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8817 } else {
8818 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8820 if (!data) {
8821 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8822 "Unable to map memory for readback.");
8823 return;
8825 memcpy(pixels, data, pixels_size);
8826 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8827 // have to restore the state.
8828 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8829 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8830 glDeleteBuffersARB(1, &buffer);
8833 if (result != NULL) {
8834 *result = true;
8837 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8838 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8839 if ((channels_exist & 0x0008) == 0 &&
8840 workarounds().clear_alpha_in_readpixels) {
8841 // Set the alpha to 255 because some drivers are buggy in this regard.
8842 uint32 temp_size;
8844 uint32 unpadded_row_size;
8845 uint32 padded_row_size;
8846 if (!GLES2Util::ComputeImageDataSizes(
8847 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8848 &unpadded_row_size, &padded_row_size)) {
8849 return;
8852 uint32 channel_count = 0;
8853 uint32 alpha_channel = 0;
8854 switch (format) {
8855 case GL_RGBA:
8856 case GL_BGRA_EXT:
8857 channel_count = 4;
8858 alpha_channel = 3;
8859 break;
8860 case GL_ALPHA:
8861 channel_count = 1;
8862 alpha_channel = 0;
8863 break;
8866 if (channel_count > 0) {
8867 switch (type) {
8868 case GL_UNSIGNED_BYTE:
8869 WriteAlphaData<uint8>(
8870 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8871 padded_row_size, 0xFF);
8872 break;
8873 case GL_FLOAT:
8874 WriteAlphaData<float>(
8875 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8876 padded_row_size, 1.0f);
8877 break;
8878 case GL_HALF_FLOAT:
8879 WriteAlphaData<uint16>(
8880 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8881 padded_row_size, 0x3C00);
8882 break;
8888 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8889 const void* cmd_data) {
8890 const gles2::cmds::ReadPixels& c =
8891 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8892 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8893 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8894 if (fbo_error != error::kNoError)
8895 return fbo_error;
8896 GLint x = c.x;
8897 GLint y = c.y;
8898 GLsizei width = c.width;
8899 GLsizei height = c.height;
8900 GLenum format = c.format;
8901 GLenum type = c.type;
8902 GLboolean async = static_cast<GLboolean>(c.async);
8903 if (width < 0 || height < 0) {
8904 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8905 return error::kNoError;
8907 typedef cmds::ReadPixels::Result Result;
8908 uint32 pixels_size;
8909 if (!GLES2Util::ComputeImageDataSizes(
8910 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8911 NULL, NULL)) {
8912 return error::kOutOfBounds;
8914 void* pixels = GetSharedMemoryAs<void*>(
8915 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8916 if (!pixels) {
8917 return error::kOutOfBounds;
8919 Result* result = NULL;
8920 if (c.result_shm_id != 0) {
8921 result = GetSharedMemoryAs<Result*>(
8922 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8923 if (!result) {
8924 return error::kOutOfBounds;
8928 if (!validators_->read_pixel_format.IsValid(format)) {
8929 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8930 return error::kNoError;
8932 if (!validators_->read_pixel_type.IsValid(type)) {
8933 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8934 return error::kNoError;
8937 GLenum src_internal_format = GetBoundReadFrameBufferInternalFormat();
8938 if (src_internal_format == 0) {
8939 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels",
8940 "no valid read buffer source");
8941 return error::kNoError;
8943 std::vector<GLenum> accepted_formats;
8944 std::vector<GLenum> accepted_types;
8945 switch (src_internal_format) {
8946 case GL_R8UI:
8947 case GL_R16UI:
8948 case GL_R32UI:
8949 case GL_RG8UI:
8950 case GL_RG16UI:
8951 case GL_RG32UI:
8952 // All the RGB_INTEGER formats are not renderable.
8953 case GL_RGBA8UI:
8954 case GL_RGB10_A2UI:
8955 case GL_RGBA16UI:
8956 case GL_RGBA32UI:
8957 accepted_formats.push_back(GL_RGBA_INTEGER);
8958 accepted_types.push_back(GL_UNSIGNED_INT);
8959 break;
8960 case GL_R8I:
8961 case GL_R16I:
8962 case GL_R32I:
8963 case GL_RG8I:
8964 case GL_RG16I:
8965 case GL_RG32I:
8966 case GL_RGBA8I:
8967 case GL_RGBA16I:
8968 case GL_RGBA32I:
8969 accepted_formats.push_back(GL_RGBA_INTEGER);
8970 accepted_types.push_back(GL_INT);
8971 break;
8972 case GL_RGB10_A2:
8973 accepted_formats.push_back(GL_RGBA);
8974 accepted_types.push_back(GL_UNSIGNED_BYTE);
8975 // Special case with an extra supported format/type.
8976 accepted_formats.push_back(GL_RGBA);
8977 accepted_types.push_back(GL_UNSIGNED_INT_2_10_10_10_REV);
8978 break;
8979 default:
8980 accepted_formats.push_back(GL_RGBA);
8982 GLenum src_type = GetBoundReadFrameBufferTextureType();
8983 switch (src_type) {
8984 case GL_HALF_FLOAT:
8985 case GL_HALF_FLOAT_OES:
8986 case GL_FLOAT:
8987 case GL_UNSIGNED_INT_10F_11F_11F_REV:
8988 if (!feature_info_->IsES3Enabled()) {
8989 accepted_types.push_back(GL_UNSIGNED_BYTE);
8990 } else {
8991 accepted_types.push_back(GL_FLOAT);
8993 break;
8994 default:
8995 accepted_types.push_back(GL_UNSIGNED_BYTE);
8996 break;
8999 break;
9001 if (!IsWebGLContext()) {
9002 accepted_formats.push_back(GL_BGRA_EXT);
9003 accepted_types.push_back(GL_UNSIGNED_BYTE);
9005 DCHECK_EQ(accepted_formats.size(), accepted_types.size());
9006 bool format_type_acceptable = false;
9007 for (size_t ii = 0; ii < accepted_formats.size(); ++ii) {
9008 if (format == accepted_formats[ii] && type == accepted_types[ii]) {
9009 format_type_acceptable = true;
9010 break;
9013 if (!format_type_acceptable) {
9014 // format and type are acceptable enums but not guaranteed to be supported
9015 // for this framebuffer. Have to ask gl if they are valid.
9016 GLint preferred_format = 0;
9017 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
9018 GLint preferred_type = 0;
9019 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
9020 if (format == static_cast<GLenum>(preferred_format) &&
9021 type == static_cast<GLenum>(preferred_type)) {
9022 format_type_acceptable = true;
9025 if (!format_type_acceptable) {
9026 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadPixels",
9027 "format and type incompatible with the current read framebuffer");
9028 return error::kNoError;
9030 if (width == 0 || height == 0) {
9031 return error::kNoError;
9034 // Get the size of the current fbo or backbuffer.
9035 gfx::Size max_size = GetBoundReadFrameBufferSize();
9037 int32 max_x;
9038 int32 max_y;
9039 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
9040 LOCAL_SET_GL_ERROR(
9041 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
9042 return error::kNoError;
9045 if (!CheckBoundFramebuffersValid("glReadPixels")) {
9046 return error::kNoError;
9049 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
9051 ScopedResolvedFrameBufferBinder binder(this, false, true);
9053 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
9054 // The user requested an out of range area. Get the results 1 line
9055 // at a time.
9056 uint32 temp_size;
9057 uint32 unpadded_row_size;
9058 uint32 padded_row_size;
9059 if (!GLES2Util::ComputeImageDataSizes(
9060 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
9061 &unpadded_row_size, &padded_row_size)) {
9062 LOCAL_SET_GL_ERROR(
9063 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
9064 return error::kNoError;
9067 GLint dest_x_offset = std::max(-x, 0);
9068 uint32 dest_row_offset;
9069 if (!GLES2Util::ComputeImageDataSizes(
9070 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
9071 &dest_row_offset, NULL, NULL)) {
9072 LOCAL_SET_GL_ERROR(
9073 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
9074 return error::kNoError;
9077 // Copy each row into the larger dest rect.
9078 int8* dst = static_cast<int8*>(pixels);
9079 GLint read_x = std::max(0, x);
9080 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
9081 GLint read_width = read_end_x - read_x;
9082 for (GLint yy = 0; yy < height; ++yy) {
9083 GLint ry = y + yy;
9085 // Clear the row.
9086 memset(dst, 0, unpadded_row_size);
9088 // If the row is in range, copy it.
9089 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
9090 glReadPixels(
9091 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
9093 dst += padded_row_size;
9095 } else {
9096 if (async && features().use_async_readpixels) {
9097 GLuint buffer = 0;
9098 glGenBuffersARB(1, &buffer);
9099 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
9100 // For ANGLE client version 2, GL_STREAM_READ is not available.
9101 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
9102 GL_STATIC_DRAW : GL_STREAM_READ;
9103 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
9104 GLenum error = glGetError();
9105 if (error == GL_NO_ERROR) {
9106 glReadPixels(x, y, width, height, format, type, 0);
9107 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
9108 new FenceCallback()));
9109 WaitForReadPixels(base::Bind(
9110 &GLES2DecoderImpl::FinishReadPixels,
9111 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
9112 <GLES2DecoderImpl>(this),
9113 c, buffer));
9114 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
9115 return error::kNoError;
9116 } else {
9117 // On error, unbind pack buffer and fall through to sync readpixels
9118 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
9119 glDeleteBuffersARB(1, &buffer);
9122 glReadPixels(x, y, width, height, format, type, pixels);
9124 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
9125 if (error == GL_NO_ERROR) {
9126 if (result != NULL) {
9127 *result = true;
9129 FinishReadPixels(c, 0);
9132 return error::kNoError;
9135 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
9136 const void* cmd_data) {
9137 const gles2::cmds::PixelStorei& c =
9138 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
9139 GLenum pname = c.pname;
9140 GLenum param = c.param;
9141 if (!validators_->pixel_store.IsValid(pname)) {
9142 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
9143 return error::kNoError;
9145 switch (pname) {
9146 case GL_PACK_ALIGNMENT:
9147 case GL_UNPACK_ALIGNMENT:
9148 if (!validators_->pixel_store_alignment.IsValid(param)) {
9149 LOCAL_SET_GL_ERROR(
9150 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
9151 return error::kNoError;
9153 break;
9154 default:
9155 break;
9157 glPixelStorei(pname, param);
9158 switch (pname) {
9159 case GL_PACK_ALIGNMENT:
9160 state_.pack_alignment = param;
9161 break;
9162 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
9163 state_.pack_reverse_row_order = (param != 0);
9164 break;
9165 case GL_UNPACK_ALIGNMENT:
9166 state_.unpack_alignment = param;
9167 break;
9168 default:
9169 // Validation should have prevented us from getting here.
9170 NOTREACHED();
9171 break;
9173 return error::kNoError;
9176 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
9177 uint32 immediate_data_size,
9178 const void* cmd_data) {
9179 const gles2::cmds::PostSubBufferCHROMIUM& c =
9180 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
9181 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
9183 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9185 if (!supports_post_sub_buffer_) {
9186 LOCAL_SET_GL_ERROR(
9187 GL_INVALID_OPERATION,
9188 "glPostSubBufferCHROMIUM", "command not supported by surface");
9189 return error::kNoError;
9191 bool is_tracing;
9192 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9193 &is_tracing);
9194 if (is_tracing) {
9195 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9196 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9197 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9198 is_offscreen ? offscreen_size_ : surface_->GetSize());
9200 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height) !=
9201 gfx::SwapResult::SWAP_FAILED) {
9202 return error::kNoError;
9203 } else {
9204 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
9205 return error::kLostContext;
9209 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
9210 uint32 immediate_data_size,
9211 const void* cmd_data) {
9212 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
9213 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
9214 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
9215 if (!ref) {
9216 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9217 "glScheduleOverlayPlaneCHROMIUM",
9218 "unknown texture");
9219 return error::kNoError;
9221 gfx::GLImage* image =
9222 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
9223 if (!image) {
9224 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9225 "glScheduleOverlayPlaneCHROMIUM",
9226 "unsupported texture format");
9227 return error::kNoError;
9229 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
9230 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
9231 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
9232 "glScheduleOverlayPlaneCHROMIUM",
9233 "invalid transform enum");
9234 return error::kNoError;
9236 if (!surface_->ScheduleOverlayPlane(
9237 c.plane_z_order,
9238 transform,
9239 image,
9240 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
9241 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
9242 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9243 "glScheduleOverlayPlaneCHROMIUM",
9244 "failed to schedule overlay");
9246 return error::kNoError;
9249 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
9250 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
9251 const std::string& name_str) {
9252 if (!StringIsValidForGLES(name_str.c_str())) {
9253 LOCAL_SET_GL_ERROR(
9254 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
9255 return error::kNoError;
9257 Program* program = GetProgramInfoNotShader(
9258 client_id, "glGetAttribLocation");
9259 if (!program) {
9260 return error::kNoError;
9262 if (!program->IsValid()) {
9263 LOCAL_SET_GL_ERROR(
9264 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
9265 return error::kNoError;
9267 GLint* location = GetSharedMemoryAs<GLint*>(
9268 location_shm_id, location_shm_offset, sizeof(GLint));
9269 if (!location) {
9270 return error::kOutOfBounds;
9272 // Require the client to init this incase the context is lost and we are no
9273 // longer executing commands.
9274 if (*location != -1) {
9275 return error::kGenericError;
9277 *location = program->GetAttribLocation(name_str);
9278 return error::kNoError;
9281 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
9282 uint32 immediate_data_size,
9283 const void* cmd_data) {
9284 const gles2::cmds::GetAttribLocation& c =
9285 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
9286 Bucket* bucket = GetBucket(c.name_bucket_id);
9287 if (!bucket) {
9288 return error::kInvalidArguments;
9290 std::string name_str;
9291 if (!bucket->GetAsString(&name_str)) {
9292 return error::kInvalidArguments;
9294 return GetAttribLocationHelper(
9295 c.program, c.location_shm_id, c.location_shm_offset, name_str);
9298 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
9299 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
9300 const std::string& name_str) {
9301 if (!StringIsValidForGLES(name_str.c_str())) {
9302 LOCAL_SET_GL_ERROR(
9303 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
9304 return error::kNoError;
9306 Program* program = GetProgramInfoNotShader(
9307 client_id, "glGetUniformLocation");
9308 if (!program) {
9309 return error::kNoError;
9311 if (!program->IsValid()) {
9312 LOCAL_SET_GL_ERROR(
9313 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
9314 return error::kNoError;
9316 GLint* location = GetSharedMemoryAs<GLint*>(
9317 location_shm_id, location_shm_offset, sizeof(GLint));
9318 if (!location) {
9319 return error::kOutOfBounds;
9321 // Require the client to init this incase the context is lost an we are no
9322 // longer executing commands.
9323 if (*location != -1) {
9324 return error::kGenericError;
9326 *location = program->GetUniformFakeLocation(name_str);
9327 return error::kNoError;
9330 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
9331 uint32 immediate_data_size,
9332 const void* cmd_data) {
9333 const gles2::cmds::GetUniformLocation& c =
9334 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
9335 Bucket* bucket = GetBucket(c.name_bucket_id);
9336 if (!bucket) {
9337 return error::kInvalidArguments;
9339 std::string name_str;
9340 if (!bucket->GetAsString(&name_str)) {
9341 return error::kInvalidArguments;
9343 return GetUniformLocationHelper(
9344 c.program, c.location_shm_id, c.location_shm_offset, name_str);
9347 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
9348 uint32 immediate_data_size,
9349 const void* cmd_data) {
9350 if (!unsafe_es3_apis_enabled())
9351 return error::kUnknownCommand;
9352 const gles2::cmds::GetUniformIndices& c =
9353 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
9354 Bucket* bucket = GetBucket(c.names_bucket_id);
9355 if (!bucket) {
9356 return error::kInvalidArguments;
9358 GLsizei count = 0;
9359 std::vector<char*> names;
9360 std::vector<GLint> len;
9361 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
9362 return error::kInvalidArguments;
9364 typedef cmds::GetUniformIndices::Result Result;
9365 Result* result = GetSharedMemoryAs<Result*>(
9366 c.indices_shm_id, c.indices_shm_offset,
9367 Result::ComputeSize(static_cast<size_t>(count)));
9368 GLuint* indices = result ? result->GetData() : NULL;
9369 if (indices == NULL) {
9370 return error::kOutOfBounds;
9372 // Check that the client initialized the result.
9373 if (result->size != 0) {
9374 return error::kInvalidArguments;
9376 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
9377 if (!program) {
9378 return error::kNoError;
9380 GLuint service_id = program->service_id();
9381 GLint link_status = GL_FALSE;
9382 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
9383 if (link_status != GL_TRUE) {
9384 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9385 "glGetUniformIndices", "program not linked");
9386 return error::kNoError;
9388 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
9389 glGetUniformIndices(service_id, count, &names[0], indices);
9390 GLenum error = glGetError();
9391 if (error == GL_NO_ERROR) {
9392 result->SetNumResults(count);
9393 } else {
9394 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
9396 return error::kNoError;
9399 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
9400 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
9401 const std::string& name_str) {
9402 GLint* location = GetSharedMemoryAs<GLint*>(
9403 location_shm_id, location_shm_offset, sizeof(GLint));
9404 if (!location) {
9405 return error::kOutOfBounds;
9407 // Require the client to init this incase the context is lost and we are no
9408 // longer executing commands.
9409 if (*location != -1) {
9410 return error::kGenericError;
9412 Program* program = GetProgramInfoNotShader(
9413 client_id, "glGetFragDataLocation");
9414 if (!program) {
9415 return error::kNoError;
9417 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
9418 return error::kNoError;
9421 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
9422 uint32 immediate_data_size,
9423 const void* cmd_data) {
9424 if (!unsafe_es3_apis_enabled())
9425 return error::kUnknownCommand;
9426 const gles2::cmds::GetFragDataLocation& c =
9427 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
9428 Bucket* bucket = GetBucket(c.name_bucket_id);
9429 if (!bucket) {
9430 return error::kInvalidArguments;
9432 std::string name_str;
9433 if (!bucket->GetAsString(&name_str)) {
9434 return error::kInvalidArguments;
9436 return GetFragDataLocationHelper(
9437 c.program, c.location_shm_id, c.location_shm_offset, name_str);
9440 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
9441 uint32 immediate_data_size, const void* cmd_data) {
9442 if (!unsafe_es3_apis_enabled())
9443 return error::kUnknownCommand;
9444 const gles2::cmds::GetUniformBlockIndex& c =
9445 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
9446 Bucket* bucket = GetBucket(c.name_bucket_id);
9447 if (!bucket) {
9448 return error::kInvalidArguments;
9450 std::string name_str;
9451 if (!bucket->GetAsString(&name_str)) {
9452 return error::kInvalidArguments;
9454 GLuint* index = GetSharedMemoryAs<GLuint*>(
9455 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
9456 if (!index) {
9457 return error::kOutOfBounds;
9459 // Require the client to init this in case the context is lost and we are no
9460 // longer executing commands.
9461 if (*index != GL_INVALID_INDEX) {
9462 return error::kGenericError;
9464 Program* program = GetProgramInfoNotShader(
9465 c.program, "glGetUniformBlockIndex");
9466 if (!program) {
9467 return error::kNoError;
9469 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
9470 return error::kNoError;
9473 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
9474 const void* cmd_data) {
9475 const gles2::cmds::GetString& c =
9476 *static_cast<const gles2::cmds::GetString*>(cmd_data);
9477 GLenum name = static_cast<GLenum>(c.name);
9478 if (!validators_->string_type.IsValid(name)) {
9479 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
9480 return error::kNoError;
9483 const char* str = nullptr;
9484 std::string extensions;
9485 switch (name) {
9486 case GL_VERSION:
9487 if (unsafe_es3_apis_enabled())
9488 str = "OpenGL ES 3.0 Chromium";
9489 else
9490 str = "OpenGL ES 2.0 Chromium";
9491 break;
9492 case GL_SHADING_LANGUAGE_VERSION:
9493 if (unsafe_es3_apis_enabled())
9494 str = "OpenGL ES GLSL ES 3.0 Chromium";
9495 else
9496 str = "OpenGL ES GLSL ES 1.0 Chromium";
9497 break;
9498 case GL_RENDERER:
9499 case GL_VENDOR:
9500 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9501 // They are used by WEBGL_debug_renderer_info.
9502 if (!IsWebGLContext())
9503 str = "Chromium";
9504 else
9505 str = reinterpret_cast<const char*>(glGetString(name));
9506 break;
9507 case GL_EXTENSIONS:
9509 // For WebGL contexts, strip out the OES derivatives and
9510 // EXT frag depth extensions if they have not been enabled.
9511 if (IsWebGLContext()) {
9512 extensions = feature_info_->extensions();
9513 if (!derivatives_explicitly_enabled_) {
9514 size_t offset = extensions.find(kOESDerivativeExtension);
9515 if (std::string::npos != offset) {
9516 extensions.replace(offset, arraysize(kOESDerivativeExtension),
9517 std::string());
9520 if (!frag_depth_explicitly_enabled_) {
9521 size_t offset = extensions.find(kEXTFragDepthExtension);
9522 if (std::string::npos != offset) {
9523 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
9524 std::string());
9527 if (!draw_buffers_explicitly_enabled_) {
9528 size_t offset = extensions.find(kEXTDrawBuffersExtension);
9529 if (std::string::npos != offset) {
9530 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
9531 std::string());
9534 if (!shader_texture_lod_explicitly_enabled_) {
9535 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
9536 if (std::string::npos != offset) {
9537 extensions.replace(offset,
9538 arraysize(kEXTShaderTextureLodExtension),
9539 std::string());
9542 } else {
9543 extensions = feature_info_->extensions().c_str();
9545 if (supports_post_sub_buffer_)
9546 extensions += " GL_CHROMIUM_post_sub_buffer";
9547 str = extensions.c_str();
9549 break;
9550 default:
9551 str = reinterpret_cast<const char*>(glGetString(name));
9552 break;
9554 Bucket* bucket = CreateBucket(c.bucket_id);
9555 bucket->SetFromString(str);
9556 return error::kNoError;
9559 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
9560 const void* cmd_data) {
9561 const gles2::cmds::BufferData& c =
9562 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
9563 GLenum target = static_cast<GLenum>(c.target);
9564 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
9565 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9566 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9567 GLenum usage = static_cast<GLenum>(c.usage);
9568 const void* data = NULL;
9569 if (data_shm_id != 0 || data_shm_offset != 0) {
9570 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
9571 if (!data) {
9572 return error::kOutOfBounds;
9575 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
9576 return error::kNoError;
9579 void GLES2DecoderImpl::DoBufferSubData(
9580 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
9581 // Just delegate it. Some validation is actually done before this.
9582 buffer_manager()->ValidateAndDoBufferSubData(
9583 &state_, target, offset, size, data);
9586 bool GLES2DecoderImpl::ClearLevel(Texture* texture,
9587 unsigned target,
9588 int level,
9589 unsigned format,
9590 unsigned type,
9591 int xoffset,
9592 int yoffset,
9593 int width,
9594 int height) {
9595 uint32 channels = GLES2Util::GetChannelsForFormat(format);
9596 if ((feature_info_->feature_flags().angle_depth_texture ||
9597 feature_info_->IsES3Enabled())
9598 && (channels & GLES2Util::kDepth) != 0) {
9599 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9600 // on depth formats.
9601 GLuint fb = 0;
9602 glGenFramebuffersEXT(1, &fb);
9603 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
9605 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
9606 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
9607 GL_DEPTH_ATTACHMENT;
9609 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
9610 texture->service_id(), level);
9611 // ANGLE promises a depth only attachment ok.
9612 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
9613 GL_FRAMEBUFFER_COMPLETE) {
9614 return false;
9616 glClearStencil(0);
9617 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
9618 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
9619 glClearDepth(1.0f);
9620 state_.SetDeviceDepthMask(GL_TRUE);
9621 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
9622 glScissor(xoffset, yoffset, width, height);
9623 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
9625 RestoreClearState();
9627 glDeleteFramebuffersEXT(1, &fb);
9628 Framebuffer* framebuffer =
9629 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
9630 GLuint fb_service_id =
9631 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
9632 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
9633 return true;
9636 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
9638 uint32 size;
9639 uint32 padded_row_size;
9640 if (!GLES2Util::ComputeImageDataSizes(
9641 width, height, 1, format, type, state_.unpack_alignment, &size,
9642 NULL, &padded_row_size)) {
9643 return false;
9646 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
9648 int tile_height;
9650 if (size > kMaxZeroSize) {
9651 if (kMaxZeroSize < padded_row_size) {
9652 // That'd be an awfully large texture.
9653 return false;
9655 // We should never have a large total size with a zero row size.
9656 DCHECK_GT(padded_row_size, 0U);
9657 tile_height = kMaxZeroSize / padded_row_size;
9658 if (!GLES2Util::ComputeImageDataSizes(
9659 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
9660 NULL, NULL)) {
9661 return false;
9663 } else {
9664 tile_height = height;
9667 // Assumes the size has already been checked.
9668 scoped_ptr<char[]> zero(new char[size]);
9669 memset(zero.get(), 0, size);
9670 glBindTexture(texture->target(), texture->service_id());
9672 GLint y = 0;
9673 while (y < height) {
9674 GLint h = y + tile_height > height ? height - y : tile_height;
9675 glTexSubImage2D(target, level, xoffset, yoffset + y, width, h, format, type,
9676 zero.get());
9677 y += tile_height;
9679 TextureRef* bound_texture =
9680 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
9681 glBindTexture(texture->target(),
9682 bound_texture ? bound_texture->service_id() : 0);
9683 return true;
9686 namespace {
9688 const int kASTCBlockSize = 16;
9689 const int kS3TCBlockWidth = 4;
9690 const int kS3TCBlockHeight = 4;
9691 const int kS3TCDXT1BlockSize = 8;
9692 const int kS3TCDXT3AndDXT5BlockSize = 16;
9693 const int kEACAndETC2BlockSize = 4;
9695 typedef struct {
9696 int blockWidth;
9697 int blockHeight;
9698 } ASTCBlockArray;
9700 const ASTCBlockArray kASTCBlockArray[] = {
9701 {4, 4}, /* GL_COMPRESSED_RGBA_ASTC_4x4_KHR */
9702 {5, 4}, /* and GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR */
9703 {5, 5},
9704 {6, 5},
9705 {6, 6},
9706 {8, 5},
9707 {8, 6},
9708 {8, 8},
9709 {10, 5},
9710 {10, 6},
9711 {10, 8},
9712 {10, 10},
9713 {12, 10},
9714 {12, 12}};
9716 bool IsValidDXTSize(GLint level, GLsizei size) {
9717 return (size == 1) ||
9718 (size == 2) || !(size % kS3TCBlockWidth);
9721 bool IsValidPVRTCSize(GLint level, GLsizei size) {
9722 return GLES2Util::IsPOT(size);
9725 } // anonymous namespace.
9727 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9728 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9729 GLenum format, GLsizei* size_in_bytes) {
9730 base::CheckedNumeric<GLsizei> bytes_required(0);
9732 switch (format) {
9733 case GL_ATC_RGB_AMD:
9734 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9735 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9736 case GL_ETC1_RGB8_OES:
9737 bytes_required =
9738 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9739 bytes_required *=
9740 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9741 bytes_required *= kS3TCDXT1BlockSize;
9742 break;
9743 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
9744 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
9745 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
9746 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
9747 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
9748 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
9749 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
9750 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
9751 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
9752 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
9753 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
9754 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
9755 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
9756 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
9757 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
9758 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
9759 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
9760 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
9761 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
9762 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
9763 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
9764 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
9765 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
9766 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
9767 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
9768 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
9769 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
9770 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: {
9771 const int index = (format < GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) ?
9772 static_cast<int>(format - GL_COMPRESSED_RGBA_ASTC_4x4_KHR) :
9773 static_cast<int>(format - GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
9775 const int kBlockWidth = kASTCBlockArray[index].blockWidth;
9776 const int kBlockHeight = kASTCBlockArray[index].blockHeight;
9778 bytes_required =
9779 (width + kBlockWidth - 1) / kBlockWidth;
9780 bytes_required *=
9781 (height + kBlockHeight - 1) / kBlockHeight;
9783 bytes_required *= kASTCBlockSize;
9784 break;
9786 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9787 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9788 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9789 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9790 bytes_required =
9791 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9792 bytes_required *=
9793 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9794 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
9795 break;
9796 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9797 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9798 bytes_required = std::max(width, 8);
9799 bytes_required *= std::max(height, 8);
9800 bytes_required *= 4;
9801 bytes_required += 7;
9802 bytes_required /= 8;
9803 break;
9804 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9805 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9806 bytes_required = std::max(width, 16);
9807 bytes_required *= std::max(height, 8);
9808 bytes_required *= 2;
9809 bytes_required += 7;
9810 bytes_required /= 8;
9811 break;
9813 // ES3 formats.
9814 case GL_COMPRESSED_R11_EAC:
9815 case GL_COMPRESSED_SIGNED_R11_EAC:
9816 case GL_COMPRESSED_RGB8_ETC2:
9817 case GL_COMPRESSED_SRGB8_ETC2:
9818 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9819 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9820 bytes_required =
9821 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9822 bytes_required *=
9823 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9824 bytes_required *= 8;
9825 bytes_required *= depth;
9826 break;
9827 case GL_COMPRESSED_RG11_EAC:
9828 case GL_COMPRESSED_SIGNED_RG11_EAC:
9829 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9830 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9831 bytes_required =
9832 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9833 bytes_required *=
9834 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9835 bytes_required *= 16;
9836 bytes_required *= depth;
9837 break;
9838 default:
9839 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
9840 return false;
9843 if (!bytes_required.IsValid()) {
9844 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid size");
9845 return false;
9848 *size_in_bytes = bytes_required.ValueOrDefault(0);
9849 return true;
9852 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9853 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9854 GLenum format, GLsizei size) {
9855 GLsizei bytes_required = 0;
9856 if (!GetCompressedTexSizeInBytes(
9857 function_name, width, height, depth, format, &bytes_required)) {
9858 return false;
9861 if (size != bytes_required) {
9862 LOCAL_SET_GL_ERROR(
9863 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
9864 return false;
9867 return true;
9870 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9871 const char* function_name, GLenum target, GLint level,
9872 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
9873 switch (format) {
9874 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9875 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9876 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9877 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9878 DCHECK_EQ(1, depth); // 2D formats.
9879 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
9880 LOCAL_SET_GL_ERROR(
9881 GL_INVALID_OPERATION, function_name,
9882 "width or height invalid for level");
9883 return false;
9885 return true;
9886 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
9887 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
9888 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
9889 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
9890 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
9891 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
9892 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
9893 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
9894 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
9895 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
9896 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
9897 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
9898 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
9899 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
9900 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
9901 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
9902 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
9903 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
9904 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
9905 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
9906 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
9907 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
9908 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
9909 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
9910 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
9911 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
9912 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
9913 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
9914 case GL_ATC_RGB_AMD:
9915 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9916 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9917 case GL_ETC1_RGB8_OES:
9918 DCHECK_EQ(1, depth); // 2D formats.
9919 if (width <= 0 || height <= 0) {
9920 LOCAL_SET_GL_ERROR(
9921 GL_INVALID_OPERATION, function_name,
9922 "width or height invalid for level");
9923 return false;
9925 return true;
9926 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9927 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9928 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9929 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9930 DCHECK_EQ(1, depth); // 2D formats.
9931 if (!IsValidPVRTCSize(level, width) ||
9932 !IsValidPVRTCSize(level, height)) {
9933 LOCAL_SET_GL_ERROR(
9934 GL_INVALID_OPERATION, function_name,
9935 "width or height invalid for level");
9936 return false;
9938 return true;
9940 // ES3 formats.
9941 case GL_COMPRESSED_R11_EAC:
9942 case GL_COMPRESSED_SIGNED_R11_EAC:
9943 case GL_COMPRESSED_RG11_EAC:
9944 case GL_COMPRESSED_SIGNED_RG11_EAC:
9945 case GL_COMPRESSED_RGB8_ETC2:
9946 case GL_COMPRESSED_SRGB8_ETC2:
9947 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9948 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9949 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9950 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9951 if (width <= 0 || height <= 0 || depth <= 0) {
9952 LOCAL_SET_GL_ERROR(
9953 GL_INVALID_OPERATION, function_name,
9954 "width, height, or depth invalid");
9955 return false;
9957 if (target == GL_TEXTURE_3D) {
9958 LOCAL_SET_GL_ERROR(
9959 GL_INVALID_OPERATION, function_name,
9960 "target invalid for format");
9961 return false;
9963 return true;
9964 default:
9965 return false;
9969 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9970 const char* function_name,
9971 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9972 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9973 Texture* texture) {
9974 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9975 LOCAL_SET_GL_ERROR(
9976 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9977 return false;
9980 switch (format) {
9981 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9982 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9983 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9984 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9985 const int kBlockWidth = 4;
9986 const int kBlockHeight = 4;
9987 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9988 LOCAL_SET_GL_ERROR(
9989 GL_INVALID_OPERATION, function_name,
9990 "xoffset or yoffset not multiple of 4");
9991 return false;
9993 GLsizei tex_width = 0;
9994 GLsizei tex_height = 0;
9995 if (!texture->GetLevelSize(target, level,
9996 &tex_width, &tex_height, nullptr) ||
9997 width - xoffset > tex_width ||
9998 height - yoffset > tex_height) {
9999 LOCAL_SET_GL_ERROR(
10000 GL_INVALID_OPERATION, function_name, "dimensions out of range");
10001 return false;
10003 return ValidateCompressedTexDimensions(
10004 function_name, target, level, width, height, 1, format);
10006 case GL_ATC_RGB_AMD:
10007 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
10008 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
10009 LOCAL_SET_GL_ERROR(
10010 GL_INVALID_OPERATION, function_name,
10011 "not supported for ATC textures");
10012 return false;
10014 case GL_ETC1_RGB8_OES: {
10015 LOCAL_SET_GL_ERROR(
10016 GL_INVALID_OPERATION, function_name,
10017 "not supported for ECT1_RGB8_OES textures");
10018 return false;
10020 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
10021 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
10022 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
10023 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
10024 if ((xoffset != 0) || (yoffset != 0)) {
10025 LOCAL_SET_GL_ERROR(
10026 GL_INVALID_OPERATION, function_name,
10027 "xoffset and yoffset must be zero");
10028 return false;
10030 GLsizei tex_width = 0;
10031 GLsizei tex_height = 0;
10032 if (!texture->GetLevelSize(target, level,
10033 &tex_width, &tex_height, nullptr) ||
10034 width != tex_width ||
10035 height != tex_height) {
10036 LOCAL_SET_GL_ERROR(
10037 GL_INVALID_OPERATION, function_name,
10038 "dimensions must match existing texture level dimensions");
10039 return false;
10041 return ValidateCompressedTexDimensions(
10042 function_name, target, level, width, height, 1, format);
10045 // ES3 formats
10046 case GL_COMPRESSED_R11_EAC:
10047 case GL_COMPRESSED_SIGNED_R11_EAC:
10048 case GL_COMPRESSED_RG11_EAC:
10049 case GL_COMPRESSED_SIGNED_RG11_EAC:
10050 case GL_COMPRESSED_RGB8_ETC2:
10051 case GL_COMPRESSED_SRGB8_ETC2:
10052 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
10053 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
10054 case GL_COMPRESSED_RGBA8_ETC2_EAC:
10055 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
10057 const int kBlockSize = 4;
10058 GLsizei tex_width, tex_height;
10059 if (target == GL_TEXTURE_3D ||
10060 !texture->GetLevelSize(target, level,
10061 &tex_width, &tex_height, nullptr) ||
10062 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
10063 ((width % kBlockSize) && xoffset + width != tex_width) ||
10064 ((height % kBlockSize) && yoffset + height != tex_height)) {
10065 LOCAL_SET_GL_ERROR(
10066 GL_INVALID_OPERATION, function_name,
10067 "dimensions must match existing texture level dimensions");
10068 return false;
10070 return true;
10072 default:
10073 return false;
10077 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
10078 GLenum target,
10079 GLint level,
10080 GLenum internal_format,
10081 GLsizei width,
10082 GLsizei height,
10083 GLint border,
10084 GLsizei image_size,
10085 const void* data) {
10086 if (!validators_->texture_target.IsValid(target)) {
10087 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10088 "glCompressedTexImage2D", target, "target");
10089 return error::kNoError;
10091 if (!validators_->compressed_texture_format.IsValid(
10092 internal_format)) {
10093 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10094 "glCompressedTexImage2D", internal_format, "internal_format");
10095 return error::kNoError;
10097 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
10098 border != 0) {
10099 LOCAL_SET_GL_ERROR(
10100 GL_INVALID_VALUE,
10101 "glCompressedTexImage2D", "dimensions out of range");
10102 return error::kNoError;
10104 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10105 &state_, target);
10106 if (!texture_ref) {
10107 LOCAL_SET_GL_ERROR(
10108 GL_INVALID_VALUE,
10109 "glCompressedTexImage2D", "unknown texture target");
10110 return error::kNoError;
10112 Texture* texture = texture_ref->texture();
10113 if (texture->IsImmutable()) {
10114 LOCAL_SET_GL_ERROR(
10115 GL_INVALID_OPERATION,
10116 "glCompressedTexImage2D", "texture is immutable");
10117 return error::kNoError;
10119 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
10120 width, height, 1, internal_format) ||
10121 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
10122 1, internal_format, image_size)) {
10123 return error::kNoError;
10126 if (!EnsureGPUMemoryAvailable(image_size)) {
10127 LOCAL_SET_GL_ERROR(
10128 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
10129 return error::kNoError;
10132 if (texture->IsAttachedToFramebuffer()) {
10133 framebuffer_state_.clear_state_dirty = true;
10136 scoped_ptr<int8[]> zero;
10137 if (!data) {
10138 zero.reset(new int8[image_size]);
10139 memset(zero.get(), 0, image_size);
10140 data = zero.get();
10142 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
10143 glCompressedTexImage2D(
10144 target, level, internal_format, width, height, border, image_size, data);
10145 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
10146 if (error == GL_NO_ERROR) {
10147 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10148 width, height, 1, border, 0, 0,
10149 gfx::Rect(width, height));
10152 // This may be a slow command. Exit command processing to allow for
10153 // context preemption and GPU watchdog checks.
10154 ExitCommandProcessingEarly();
10155 return error::kNoError;
10158 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
10159 uint32 immediate_data_size,
10160 const void* cmd_data) {
10161 const gles2::cmds::CompressedTexImage2D& c =
10162 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
10163 GLenum target = static_cast<GLenum>(c.target);
10164 GLint level = static_cast<GLint>(c.level);
10165 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10166 GLsizei width = static_cast<GLsizei>(c.width);
10167 GLsizei height = static_cast<GLsizei>(c.height);
10168 GLint border = static_cast<GLint>(c.border);
10169 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
10170 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
10171 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
10172 const void* data = NULL;
10173 if (data_shm_id != 0 || data_shm_offset != 0) {
10174 data = GetSharedMemoryAs<const void*>(
10175 data_shm_id, data_shm_offset, image_size);
10176 if (!data) {
10177 return error::kOutOfBounds;
10180 return DoCompressedTexImage2D(
10181 target, level, internal_format, width, height, border, image_size, data);
10184 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
10185 uint32 immediate_data_size,
10186 const void* cmd_data) {
10187 const gles2::cmds::CompressedTexImage2DBucket& c =
10188 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
10189 GLenum target = static_cast<GLenum>(c.target);
10190 GLint level = static_cast<GLint>(c.level);
10191 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10192 GLsizei width = static_cast<GLsizei>(c.width);
10193 GLsizei height = static_cast<GLsizei>(c.height);
10194 GLint border = static_cast<GLint>(c.border);
10195 Bucket* bucket = GetBucket(c.bucket_id);
10196 if (!bucket) {
10197 return error::kInvalidArguments;
10199 uint32 data_size = bucket->size();
10200 GLsizei imageSize = data_size;
10201 const void* data = bucket->GetData(0, data_size);
10202 if (!data) {
10203 return error::kInvalidArguments;
10205 return DoCompressedTexImage2D(
10206 target, level, internal_format, width, height, border,
10207 imageSize, data);
10210 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
10211 uint32 immediate_data_size,
10212 const void* cmd_data) {
10213 const gles2::cmds::CompressedTexSubImage2DBucket& c =
10214 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
10215 GLenum target = static_cast<GLenum>(c.target);
10216 GLint level = static_cast<GLint>(c.level);
10217 GLint xoffset = static_cast<GLint>(c.xoffset);
10218 GLint yoffset = static_cast<GLint>(c.yoffset);
10219 GLsizei width = static_cast<GLsizei>(c.width);
10220 GLsizei height = static_cast<GLsizei>(c.height);
10221 GLenum format = static_cast<GLenum>(c.format);
10222 Bucket* bucket = GetBucket(c.bucket_id);
10223 if (!bucket) {
10224 return error::kInvalidArguments;
10226 uint32 data_size = bucket->size();
10227 GLsizei imageSize = data_size;
10228 const void* data = bucket->GetData(0, data_size);
10229 if (!data) {
10230 return error::kInvalidArguments;
10232 if (!validators_->texture_target.IsValid(target)) {
10233 LOCAL_SET_GL_ERROR(
10234 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
10235 return error::kNoError;
10237 if (!validators_->compressed_texture_format.IsValid(format)) {
10238 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10239 "glCompressedTexSubImage2D", format, "format");
10240 return error::kNoError;
10242 if (width < 0) {
10243 LOCAL_SET_GL_ERROR(
10244 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
10245 return error::kNoError;
10247 if (height < 0) {
10248 LOCAL_SET_GL_ERROR(
10249 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
10250 return error::kNoError;
10252 if (imageSize < 0) {
10253 LOCAL_SET_GL_ERROR(
10254 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
10255 return error::kNoError;
10257 DoCompressedTexSubImage2D(
10258 target, level, xoffset, yoffset, width, height, format, imageSize, data);
10259 return error::kNoError;
10262 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
10263 GLenum target,
10264 GLint level,
10265 GLenum internal_format,
10266 GLsizei width,
10267 GLsizei height,
10268 GLsizei depth,
10269 GLint border,
10270 GLsizei image_size,
10271 const void* data) {
10272 if (!validators_->texture_3_d_target.IsValid(target)) {
10273 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10274 "glCompressedTexImage3D", target, "target");
10275 return error::kNoError;
10277 if (!validators_->compressed_texture_format.IsValid(
10278 internal_format)) {
10279 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10280 "glCompressedTexImage3D", internal_format, "internal_format");
10281 return error::kNoError;
10283 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
10284 border != 0) {
10285 LOCAL_SET_GL_ERROR(
10286 GL_INVALID_VALUE,
10287 "glCompressedTexImage3D", "dimensions out of range");
10288 return error::kNoError;
10290 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10291 &state_, target);
10292 if (!texture_ref) {
10293 LOCAL_SET_GL_ERROR(
10294 GL_INVALID_VALUE,
10295 "glCompressedTexImage3D", "unknown texture target");
10296 return error::kNoError;
10298 Texture* texture = texture_ref->texture();
10299 if (texture->IsImmutable()) {
10300 LOCAL_SET_GL_ERROR(
10301 GL_INVALID_OPERATION,
10302 "glCompressedTexImage3D", "texture is immutable");
10303 return error::kNoError;
10306 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
10307 width, height, depth, internal_format) ||
10308 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
10309 depth, internal_format, image_size)) {
10310 return error::kNoError;
10313 if (!EnsureGPUMemoryAvailable(image_size)) {
10314 LOCAL_SET_GL_ERROR(
10315 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
10316 return error::kNoError;
10319 if (texture->IsAttachedToFramebuffer()) {
10320 framebuffer_state_.clear_state_dirty = true;
10323 scoped_ptr<int8[]> zero;
10324 if (!data) {
10325 zero.reset(new int8[image_size]);
10326 memset(zero.get(), 0, image_size);
10327 data = zero.get();
10329 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
10330 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
10331 border, image_size, data);
10332 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
10333 if (error == GL_NO_ERROR) {
10334 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10335 width, height, depth, border, 0, 0,
10336 gfx::Rect(width, height));
10339 // This may be a slow command. Exit command processing to allow for
10340 // context preemption and GPU watchdog checks.
10341 ExitCommandProcessingEarly();
10342 return error::kNoError;
10345 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
10346 uint32 immediate_data_size, const void* cmd_data) {
10347 if (!unsafe_es3_apis_enabled())
10348 return error::kUnknownCommand;
10350 const gles2::cmds::CompressedTexImage3D& c =
10351 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
10352 GLenum target = static_cast<GLenum>(c.target);
10353 GLint level = static_cast<GLint>(c.level);
10354 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10355 GLsizei width = static_cast<GLsizei>(c.width);
10356 GLsizei height = static_cast<GLsizei>(c.height);
10357 GLsizei depth = static_cast<GLsizei>(c.depth);
10358 GLint border = static_cast<GLint>(c.border);
10359 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
10360 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
10361 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
10362 const void* data = NULL;
10363 if (data_shm_id != 0 || data_shm_offset != 0) {
10364 data = GetSharedMemoryAs<const void*>(
10365 data_shm_id, data_shm_offset, image_size);
10366 if (!data) {
10367 return error::kOutOfBounds;
10370 return DoCompressedTexImage3D(target, level, internal_format, width, height,
10371 depth, border, image_size, data);
10374 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
10375 uint32 immediate_data_size, const void* cmd_data) {
10376 if (!unsafe_es3_apis_enabled())
10377 return error::kUnknownCommand;
10379 const gles2::cmds::CompressedTexImage3DBucket& c =
10380 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
10381 GLenum target = static_cast<GLenum>(c.target);
10382 GLint level = static_cast<GLint>(c.level);
10383 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10384 GLsizei width = static_cast<GLsizei>(c.width);
10385 GLsizei height = static_cast<GLsizei>(c.height);
10386 GLsizei depth = static_cast<GLsizei>(c.depth);
10387 GLint border = static_cast<GLint>(c.border);
10388 Bucket* bucket = GetBucket(c.bucket_id);
10389 if (!bucket) {
10390 return error::kInvalidArguments;
10392 uint32 data_size = bucket->size();
10393 GLsizei imageSize = data_size;
10394 const void* data = bucket->GetData(0, data_size);
10395 if (!data) {
10396 return error::kInvalidArguments;
10398 return DoCompressedTexImage3D(target, level, internal_format, width, height,
10399 depth, border, imageSize, data);
10402 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
10403 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
10404 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
10405 GLsizei image_size, const void* data) {
10406 if (!validators_->texture_3_d_target.IsValid(target)) {
10407 LOCAL_SET_GL_ERROR(
10408 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
10409 return;
10411 if (!validators_->compressed_texture_format.IsValid(format)) {
10412 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10413 "glCompressedTexSubImage3D", format, "format");
10414 return;
10416 if (width < 0 || height < 0 || depth < 0) {
10417 LOCAL_SET_GL_ERROR(
10418 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
10419 return;
10421 if (image_size < 0) {
10422 LOCAL_SET_GL_ERROR(
10423 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
10424 return;
10426 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10427 &state_, target);
10428 if (!texture_ref) {
10429 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
10430 "unknown texture for target");
10431 return;
10433 Texture* texture = texture_ref->texture();
10434 GLenum type = 0, internal_format = 0;
10435 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
10436 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
10437 "level does not exist");
10438 return;
10440 if (internal_format != format) {
10441 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
10442 "format does not match internal format");
10443 return;
10445 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
10446 width, height, depth)) {
10447 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
10448 "bad dimensions");
10449 return;
10451 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
10452 width, height, depth, format,
10453 image_size) ||
10454 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
10455 target, level, xoffset, yoffset,
10456 zoffset, width, height, depth,
10457 format, texture)) {
10458 return;
10461 // Note: There is no need to deal with texture cleared tracking here
10462 // because the validation above means you can only get here if the level
10463 // is already a matching compressed format and in that case
10464 // CompressedTexImage3D already cleared the texture.
10465 glCompressedTexSubImage3D(
10466 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
10467 image_size, data);
10469 // This may be a slow command. Exit command processing to allow for
10470 // context preemption and GPU watchdog checks.
10471 ExitCommandProcessingEarly();
10474 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
10475 uint32 immediate_data_size, const void* cmd_data) {
10476 if (!unsafe_es3_apis_enabled())
10477 return error::kUnknownCommand;
10478 const gles2::cmds::CompressedTexSubImage3DBucket& c =
10479 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
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 Bucket* bucket = GetBucket(c.bucket_id);
10490 if (!bucket) {
10491 return error::kInvalidArguments;
10493 uint32 data_size = bucket->size();
10494 GLsizei image_size = data_size;
10495 const void* data = bucket->GetData(0, data_size);
10496 if (!data) {
10497 return error::kInvalidArguments;
10499 DoCompressedTexSubImage3D(
10500 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
10501 image_size, data);
10502 return error::kNoError;
10505 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
10506 const void* cmd_data) {
10507 const gles2::cmds::TexImage2D& c =
10508 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
10509 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
10510 "width", c.width, "height", c.height);
10511 // Set as failed for now, but if it successed, this will be set to not failed.
10512 texture_state_.tex_image_failed = true;
10513 GLenum target = static_cast<GLenum>(c.target);
10514 GLint level = static_cast<GLint>(c.level);
10515 // TODO(kloveless): Change TexImage2D command to use unsigned integer
10516 // for internalformat.
10517 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10518 GLsizei width = static_cast<GLsizei>(c.width);
10519 GLsizei height = static_cast<GLsizei>(c.height);
10520 GLint border = static_cast<GLint>(c.border);
10521 GLenum format = static_cast<GLenum>(c.format);
10522 GLenum type = static_cast<GLenum>(c.type);
10523 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10524 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10525 uint32 pixels_size;
10526 if (!GLES2Util::ComputeImageDataSizes(
10527 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10528 NULL, NULL)) {
10529 return error::kOutOfBounds;
10531 const void* pixels = NULL;
10532 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10533 pixels = GetSharedMemoryAs<const void*>(
10534 pixels_shm_id, pixels_shm_offset, pixels_size);
10535 if (!pixels) {
10536 return error::kOutOfBounds;
10540 // For testing only. Allows us to stress the ability to respond to OOM errors.
10541 if (workarounds().simulate_out_of_memory_on_large_textures &&
10542 (width * height >= 4096 * 4096)) {
10543 LOCAL_SET_GL_ERROR(
10544 GL_OUT_OF_MEMORY,
10545 "glTexImage2D", "synthetic out of memory");
10546 return error::kNoError;
10549 TextureManager::DoTexImageArguments args = {
10550 target, level, internal_format, width, height, 1, border, format, type,
10551 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
10552 texture_manager()->ValidateAndDoTexImage(
10553 &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
10555 // This may be a slow command. Exit command processing to allow for
10556 // context preemption and GPU watchdog checks.
10557 ExitCommandProcessingEarly();
10558 return error::kNoError;
10561 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
10562 const void* cmd_data) {
10563 if (!unsafe_es3_apis_enabled())
10564 return error::kUnknownCommand;
10566 const gles2::cmds::TexImage3D& c =
10567 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
10568 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
10569 "widthXheight", c.width * c.height, "depth", c.depth);
10570 // Set as failed for now, but if it successed, this will be set to not failed.
10571 texture_state_.tex_image_failed = true;
10572 GLenum target = static_cast<GLenum>(c.target);
10573 GLint level = static_cast<GLint>(c.level);
10574 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10575 GLsizei width = static_cast<GLsizei>(c.width);
10576 GLsizei height = static_cast<GLsizei>(c.height);
10577 GLsizei depth = static_cast<GLsizei>(c.depth);
10578 GLint border = static_cast<GLint>(c.border);
10579 GLenum format = static_cast<GLenum>(c.format);
10580 GLenum type = static_cast<GLenum>(c.type);
10581 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10582 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10583 uint32 pixels_size;
10584 if (!GLES2Util::ComputeImageDataSizes(
10585 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
10586 NULL, NULL)) {
10587 return error::kOutOfBounds;
10589 const void* pixels = NULL;
10590 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10591 pixels = GetSharedMemoryAs<const void*>(
10592 pixels_shm_id, pixels_shm_offset, pixels_size);
10593 if (!pixels) {
10594 return error::kOutOfBounds;
10598 // For testing only. Allows us to stress the ability to respond to OOM errors.
10599 if (workarounds().simulate_out_of_memory_on_large_textures &&
10600 (width * height * depth >= 4096 * 4096)) {
10601 LOCAL_SET_GL_ERROR(
10602 GL_OUT_OF_MEMORY,
10603 "glTexImage3D", "synthetic out of memory");
10604 return error::kNoError;
10607 TextureManager::DoTexImageArguments args = {
10608 target, level, internal_format, width, height, depth, border, format, type,
10609 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
10610 texture_manager()->ValidateAndDoTexImage(
10611 &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
10613 // This may be a slow command. Exit command processing to allow for
10614 // context preemption and GPU watchdog checks.
10615 ExitCommandProcessingEarly();
10616 return error::kNoError;
10619 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10620 GLenum target,
10621 GLint level,
10622 GLint xoffset,
10623 GLint yoffset,
10624 GLsizei width,
10625 GLsizei height,
10626 GLenum format,
10627 GLsizei image_size,
10628 const void * data) {
10629 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10630 &state_, target);
10631 if (!texture_ref) {
10632 LOCAL_SET_GL_ERROR(
10633 GL_INVALID_OPERATION,
10634 "glCompressedTexSubImage2D", "unknown texture for target");
10635 return;
10637 Texture* texture = texture_ref->texture();
10638 GLenum type = 0;
10639 GLenum internal_format = 0;
10640 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
10641 LOCAL_SET_GL_ERROR(
10642 GL_INVALID_OPERATION,
10643 "glCompressedTexSubImage2D", "level does not exist.");
10644 return;
10646 if (internal_format != format) {
10647 LOCAL_SET_GL_ERROR(
10648 GL_INVALID_OPERATION,
10649 "glCompressedTexSubImage2D", "format does not match internal format.");
10650 return;
10652 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
10653 height, 1)) {
10654 LOCAL_SET_GL_ERROR(
10655 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
10656 return;
10659 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10660 width, height, 1, format, image_size) ||
10661 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10662 target, level, xoffset, yoffset, 0,
10663 width, height, 1, format, texture)) {
10664 return;
10668 // Note: There is no need to deal with texture cleared tracking here
10669 // because the validation above means you can only get here if the level
10670 // is already a matching compressed format and in that case
10671 // CompressedTexImage2D already cleared the texture.
10672 glCompressedTexSubImage2D(
10673 target, level, xoffset, yoffset, width, height, format, image_size, data);
10675 // This may be a slow command. Exit command processing to allow for
10676 // context preemption and GPU watchdog checks.
10677 ExitCommandProcessingEarly();
10680 static void Clip(
10681 GLint start, GLint range, GLint sourceRange,
10682 GLint* out_start, GLint* out_range) {
10683 DCHECK(out_start);
10684 DCHECK(out_range);
10685 if (start < 0) {
10686 range += start;
10687 start = 0;
10689 GLint end = start + range;
10690 if (end > sourceRange) {
10691 range -= end - sourceRange;
10693 *out_start = start;
10694 *out_range = range;
10697 void GLES2DecoderImpl::DoCopyTexImage2D(
10698 GLenum target,
10699 GLint level,
10700 GLenum internal_format,
10701 GLint x,
10702 GLint y,
10703 GLsizei width,
10704 GLsizei height,
10705 GLint border) {
10706 DCHECK(!ShouldDeferReads());
10707 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10708 &state_, target);
10709 if (!texture_ref) {
10710 LOCAL_SET_GL_ERROR(
10711 GL_INVALID_OPERATION,
10712 "glCopyTexImage2D", "unknown texture for target");
10713 return;
10715 Texture* texture = texture_ref->texture();
10716 if (texture->IsImmutable()) {
10717 LOCAL_SET_GL_ERROR(
10718 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
10719 return;
10721 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
10722 border != 0) {
10723 LOCAL_SET_GL_ERROR(
10724 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
10725 return;
10727 if (!texture_manager()->ValidateFormatAndTypeCombination(
10728 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
10729 GL_UNSIGNED_BYTE)) {
10730 return;
10733 // Check we have compatible formats.
10734 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10735 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10736 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
10738 if ((channels_needed & channels_exist) != channels_needed) {
10739 LOCAL_SET_GL_ERROR(
10740 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
10741 return;
10744 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10745 LOCAL_SET_GL_ERROR(
10746 GL_INVALID_OPERATION,
10747 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10748 return;
10751 uint32 estimated_size = 0;
10752 if (!GLES2Util::ComputeImageDataSizes(
10753 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10754 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
10755 LOCAL_SET_GL_ERROR(
10756 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
10757 return;
10760 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10761 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
10762 return;
10765 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10766 return;
10769 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10770 LOCAL_SET_GL_ERROR(
10771 GL_INVALID_OPERATION,
10772 "glCopyTexImage2D", "source and destination textures are the same");
10773 return;
10776 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10777 return;
10780 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10781 ScopedResolvedFrameBufferBinder binder(this, false, true);
10782 gfx::Size size = GetBoundReadFrameBufferSize();
10784 if (texture->IsAttachedToFramebuffer()) {
10785 framebuffer_state_.clear_state_dirty = true;
10788 // Clip to size to source dimensions
10789 GLint copyX = 0;
10790 GLint copyY = 0;
10791 GLint copyWidth = 0;
10792 GLint copyHeight = 0;
10793 Clip(x, width, size.width(), &copyX, &copyWidth);
10794 Clip(y, height, size.height(), &copyY, &copyHeight);
10796 if (copyX != x ||
10797 copyY != y ||
10798 copyWidth != width ||
10799 copyHeight != height) {
10800 // some part was clipped so clear the rect.
10801 uint32 pixels_size = 0;
10802 if (!GLES2Util::ComputeImageDataSizes(
10803 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10804 state_.unpack_alignment, &pixels_size, NULL, NULL)) {
10805 LOCAL_SET_GL_ERROR(
10806 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
10807 return;
10809 scoped_ptr<char[]> zero(new char[pixels_size]);
10810 memset(zero.get(), 0, pixels_size);
10811 ScopedModifyPixels modify(texture_ref);
10812 glTexImage2D(target, level, internal_format, width, height, border,
10813 internal_format, GL_UNSIGNED_BYTE, zero.get());
10814 if (copyHeight > 0 && copyWidth > 0) {
10815 GLint dx = copyX - x;
10816 GLint dy = copyY - y;
10817 GLint destX = dx;
10818 GLint destY = dy;
10819 glCopyTexSubImage2D(target, level,
10820 destX, destY, copyX, copyY,
10821 copyWidth, copyHeight);
10823 } else {
10824 ScopedModifyPixels modify(texture_ref);
10825 glCopyTexImage2D(target, level, internal_format,
10826 copyX, copyY, copyWidth, copyHeight, border);
10828 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10829 if (error == GL_NO_ERROR) {
10830 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10831 width, height, 1, border, internal_format,
10832 GL_UNSIGNED_BYTE, gfx::Rect(width, height));
10835 // This may be a slow command. Exit command processing to allow for
10836 // context preemption and GPU watchdog checks.
10837 ExitCommandProcessingEarly();
10840 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10841 GLenum target,
10842 GLint level,
10843 GLint xoffset,
10844 GLint yoffset,
10845 GLint x,
10846 GLint y,
10847 GLsizei width,
10848 GLsizei height) {
10849 DCHECK(!ShouldDeferReads());
10850 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10851 &state_, target);
10852 if (!texture_ref) {
10853 LOCAL_SET_GL_ERROR(
10854 GL_INVALID_OPERATION,
10855 "glCopyTexSubImage2D", "unknown texture for target");
10856 return;
10858 Texture* texture = texture_ref->texture();
10859 GLenum type = 0;
10860 GLenum format = 0;
10861 if (!texture->GetLevelType(target, level, &type, &format) ||
10862 !texture->ValidForTexture(
10863 target, level, xoffset, yoffset, 0, width, height, 1)) {
10864 LOCAL_SET_GL_ERROR(
10865 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
10866 return;
10869 // Check we have compatible formats.
10870 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10871 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10872 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
10874 if (!channels_needed ||
10875 (channels_needed & channels_exist) != channels_needed) {
10876 LOCAL_SET_GL_ERROR(
10877 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
10878 return;
10881 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10882 LOCAL_SET_GL_ERROR(
10883 GL_INVALID_OPERATION,
10884 "glCopySubImage2D", "can not be used with depth or stencil textures");
10885 return;
10888 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10889 return;
10892 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10893 LOCAL_SET_GL_ERROR(
10894 GL_INVALID_OPERATION,
10895 "glCopyTexSubImage2D", "source and destination textures are the same");
10896 return;
10899 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10900 return;
10903 ScopedResolvedFrameBufferBinder binder(this, false, true);
10904 gfx::Size size = GetBoundReadFrameBufferSize();
10905 GLint copyX = 0;
10906 GLint copyY = 0;
10907 GLint copyWidth = 0;
10908 GLint copyHeight = 0;
10909 Clip(x, width, size.width(), &copyX, &copyWidth);
10910 Clip(y, height, size.height(), &copyY, &copyHeight);
10912 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
10913 height != size.height()) {
10914 gfx::Rect cleared_rect;
10915 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10916 gfx::Rect(xoffset, yoffset, width, height),
10917 &cleared_rect)) {
10918 DCHECK_GE(cleared_rect.size().GetArea(),
10919 texture->GetLevelClearedRect(target, level).size().GetArea());
10920 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10921 cleared_rect);
10922 } else {
10923 // Otherwise clear part of texture level that is not already cleared.
10924 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10925 level)) {
10926 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
10927 "dimensions too big");
10928 return;
10931 } else {
10932 // Write all pixels in below.
10933 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10936 if (copyX != x ||
10937 copyY != y ||
10938 copyWidth != width ||
10939 copyHeight != height) {
10940 // some part was clipped so clear the sub rect.
10941 uint32 pixels_size = 0;
10942 if (!GLES2Util::ComputeImageDataSizes(
10943 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10944 NULL, NULL)) {
10945 LOCAL_SET_GL_ERROR(
10946 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
10947 return;
10949 scoped_ptr<char[]> zero(new char[pixels_size]);
10950 memset(zero.get(), 0, pixels_size);
10951 ScopedModifyPixels modify(texture_ref);
10952 glTexSubImage2D(
10953 target, level, xoffset, yoffset, width, height,
10954 format, type, zero.get());
10957 if (copyHeight > 0 && copyWidth > 0) {
10958 GLint dx = copyX - x;
10959 GLint dy = copyY - y;
10960 GLint destX = xoffset + dx;
10961 GLint destY = yoffset + dy;
10962 ScopedModifyPixels modify(texture_ref);
10963 glCopyTexSubImage2D(target, level,
10964 destX, destY, copyX, copyY,
10965 copyWidth, copyHeight);
10968 // This may be a slow command. Exit command processing to allow for
10969 // context preemption and GPU watchdog checks.
10970 ExitCommandProcessingEarly();
10973 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10974 error::Error* error,
10975 const char* function_name,
10976 GLenum target,
10977 GLint level,
10978 GLint xoffset,
10979 GLint yoffset,
10980 GLsizei width,
10981 GLsizei height,
10982 GLenum format,
10983 GLenum type,
10984 const void * data) {
10985 (*error) = error::kNoError;
10986 if (!validators_->texture_target.IsValid(target)) {
10987 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10988 return false;
10990 if (width < 0) {
10991 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10992 return false;
10994 if (height < 0) {
10995 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10996 return false;
10998 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10999 &state_, target);
11000 if (!texture_ref) {
11001 LOCAL_SET_GL_ERROR(
11002 GL_INVALID_OPERATION,
11003 function_name, "unknown texture for target");
11004 return false;
11006 Texture* texture = texture_ref->texture();
11007 GLenum current_type = 0;
11008 GLenum internal_format = 0;
11009 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
11010 LOCAL_SET_GL_ERROR(
11011 GL_INVALID_OPERATION, function_name, "level does not exist.");
11012 return false;
11014 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
11015 function_name, format, type, internal_format, level)) {
11016 return false;
11018 if (type != current_type && !feature_info_->IsES3Enabled()) {
11019 LOCAL_SET_GL_ERROR(
11020 GL_INVALID_OPERATION,
11021 function_name, "type does not match type of texture.");
11022 return false;
11024 if (!texture->ValidForTexture(
11025 target, level, xoffset, yoffset, 0, width, height, 1)) {
11026 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
11027 return false;
11029 if ((GLES2Util::GetChannelsForFormat(format) &
11030 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0
11031 && !feature_info_->IsES3Enabled()) {
11032 LOCAL_SET_GL_ERROR(
11033 GL_INVALID_OPERATION,
11034 function_name, "can not supply data for depth or stencil textures");
11035 return false;
11037 if (data == NULL) {
11038 (*error) = error::kOutOfBounds;
11039 return false;
11041 return true;
11044 error::Error GLES2DecoderImpl::DoTexSubImage2D(
11045 GLenum target,
11046 GLint level,
11047 GLint xoffset,
11048 GLint yoffset,
11049 GLsizei width,
11050 GLsizei height,
11051 GLenum format,
11052 GLenum type,
11053 const void * data) {
11054 error::Error error = error::kNoError;
11055 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
11056 xoffset, yoffset, width, height, format, type, data)) {
11057 return error;
11059 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11060 &state_, target);
11061 Texture* texture = texture_ref->texture();
11062 GLsizei tex_width = 0;
11063 GLsizei tex_height = 0;
11064 bool ok = texture->GetLevelSize(
11065 target, level, &tex_width, &tex_height, nullptr);
11066 DCHECK(ok);
11067 if (xoffset != 0 || yoffset != 0 ||
11068 width != tex_width || height != tex_height) {
11069 gfx::Rect cleared_rect;
11070 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
11071 gfx::Rect(xoffset, yoffset, width, height),
11072 &cleared_rect)) {
11073 DCHECK_GE(cleared_rect.size().GetArea(),
11074 texture->GetLevelClearedRect(target, level).size().GetArea());
11075 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
11076 cleared_rect);
11077 } else {
11078 // Otherwise clear part of texture level that is not already cleared.
11079 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
11080 level)) {
11081 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D",
11082 "dimensions too big");
11083 return error::kNoError;
11086 ScopedTextureUploadTimer timer(&texture_state_);
11087 glTexSubImage2D(
11088 target, level, xoffset, yoffset, width, height, format, type, data);
11089 return error::kNoError;
11092 if (!texture_state_.texsubimage_faster_than_teximage &&
11093 !texture->IsImmutable() &&
11094 !texture->HasImages()) {
11095 ScopedTextureUploadTimer timer(&texture_state_);
11096 GLenum internal_format;
11097 GLenum tex_type;
11098 texture->GetLevelType(target, level, &tex_type, &internal_format);
11099 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
11100 // to look it up.
11101 glTexImage2D(
11102 target, level, internal_format, width, height, 0, format, type, data);
11103 } else {
11104 ScopedTextureUploadTimer timer(&texture_state_);
11105 glTexSubImage2D(
11106 target, level, xoffset, yoffset, width, height, format, type, data);
11108 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
11110 // This may be a slow command. Exit command processing to allow for
11111 // context preemption and GPU watchdog checks.
11112 ExitCommandProcessingEarly();
11113 return error::kNoError;
11116 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
11117 const void* cmd_data) {
11118 const gles2::cmds::TexSubImage2D& c =
11119 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
11120 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
11121 "width", c.width, "height", c.height);
11122 GLboolean internal = static_cast<GLboolean>(c.internal);
11123 if (internal == GL_TRUE && texture_state_.tex_image_failed)
11124 return error::kNoError;
11126 GLenum target = static_cast<GLenum>(c.target);
11127 GLint level = static_cast<GLint>(c.level);
11128 GLint xoffset = static_cast<GLint>(c.xoffset);
11129 GLint yoffset = static_cast<GLint>(c.yoffset);
11130 GLsizei width = static_cast<GLsizei>(c.width);
11131 GLsizei height = static_cast<GLsizei>(c.height);
11132 GLenum format = static_cast<GLenum>(c.format);
11133 GLenum type = static_cast<GLenum>(c.type);
11134 uint32 data_size;
11135 if (!GLES2Util::ComputeImageDataSizes(
11136 width, height, 1, format, type, state_.unpack_alignment, &data_size,
11137 NULL, NULL)) {
11138 return error::kOutOfBounds;
11140 const void* pixels = GetSharedMemoryAs<const void*>(
11141 c.pixels_shm_id, c.pixels_shm_offset, data_size);
11142 return DoTexSubImage2D(
11143 target, level, xoffset, yoffset, width, height, format, type, pixels);
11146 error::Error GLES2DecoderImpl::DoTexSubImage3D(
11147 GLenum target,
11148 GLint level,
11149 GLint xoffset,
11150 GLint yoffset,
11151 GLint zoffset,
11152 GLsizei width,
11153 GLsizei height,
11154 GLsizei depth,
11155 GLenum format,
11156 GLenum type,
11157 const void * data) {
11158 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11159 &state_, target);
11160 if (!texture_ref) {
11161 LOCAL_SET_GL_ERROR(
11162 GL_INVALID_ENUM, "glTexSubImage3D", "invalid target");
11165 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
11166 ScopedTextureUploadTimer timer(&texture_state_);
11167 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
11168 depth, format, type, data);
11169 GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
11170 if (error == GL_NO_ERROR) {
11171 // TODO(zmo): This is not 100% correct because only part of the level
11172 // image is cleared.
11173 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
11176 // This may be a slow command. Exit command processing to allow for
11177 // context preemption and GPU watchdog checks.
11178 ExitCommandProcessingEarly();
11179 return error::kNoError;
11182 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
11183 const void* cmd_data) {
11184 if (!unsafe_es3_apis_enabled())
11185 return error::kUnknownCommand;
11187 const gles2::cmds::TexSubImage3D& c =
11188 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
11189 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
11190 "widthXheight", c.width * c.height, "depth", c.depth);
11191 GLboolean internal = static_cast<GLboolean>(c.internal);
11192 if (internal == GL_TRUE && texture_state_.tex_image_failed)
11193 return error::kNoError;
11195 GLenum target = static_cast<GLenum>(c.target);
11196 GLint level = static_cast<GLint>(c.level);
11197 GLint xoffset = static_cast<GLint>(c.xoffset);
11198 GLint yoffset = static_cast<GLint>(c.yoffset);
11199 GLint zoffset = static_cast<GLint>(c.zoffset);
11200 GLsizei width = static_cast<GLsizei>(c.width);
11201 GLsizei height = static_cast<GLsizei>(c.height);
11202 GLsizei depth = static_cast<GLsizei>(c.depth);
11203 GLenum format = static_cast<GLenum>(c.format);
11204 GLenum type = static_cast<GLenum>(c.type);
11205 uint32 data_size;
11206 if (!GLES2Util::ComputeImageDataSizes(
11207 width, height, depth, format, type, state_.unpack_alignment, &data_size,
11208 NULL, NULL)) {
11209 return error::kOutOfBounds;
11211 const void* pixels = GetSharedMemoryAs<const void*>(
11212 c.pixels_shm_id, c.pixels_shm_offset, data_size);
11213 return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
11214 height, depth, format, type, pixels);
11217 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
11218 uint32 immediate_data_size,
11219 const void* cmd_data) {
11220 const gles2::cmds::GetVertexAttribPointerv& c =
11221 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
11222 GLuint index = static_cast<GLuint>(c.index);
11223 GLenum pname = static_cast<GLenum>(c.pname);
11224 typedef cmds::GetVertexAttribPointerv::Result Result;
11225 Result* result = GetSharedMemoryAs<Result*>(
11226 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
11227 if (!result) {
11228 return error::kOutOfBounds;
11230 // Check that the client initialized the result.
11231 if (result->size != 0) {
11232 return error::kInvalidArguments;
11234 if (!validators_->vertex_pointer.IsValid(pname)) {
11235 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11236 "glGetVertexAttribPointerv", pname, "pname");
11237 return error::kNoError;
11239 if (index >= group_->max_vertex_attribs()) {
11240 LOCAL_SET_GL_ERROR(
11241 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
11242 return error::kNoError;
11244 result->SetNumResults(1);
11245 *result->GetData() =
11246 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
11247 return error::kNoError;
11250 template <class T>
11251 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
11252 GLint fake_location,
11253 uint32 shm_id,
11254 uint32 shm_offset,
11255 error::Error* error,
11256 GLint* real_location,
11257 GLuint* service_id,
11258 SizedResult<T>** result_pointer,
11259 GLenum* result_type,
11260 GLsizei* result_size) {
11261 DCHECK(error);
11262 DCHECK(service_id);
11263 DCHECK(result_pointer);
11264 DCHECK(result_type);
11265 DCHECK(result_size);
11266 DCHECK(real_location);
11267 *error = error::kNoError;
11268 // Make sure we have enough room for the result on failure.
11269 SizedResult<T>* result;
11270 result = GetSharedMemoryAs<SizedResult<T>*>(
11271 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
11272 if (!result) {
11273 *error = error::kOutOfBounds;
11274 return false;
11276 *result_pointer = result;
11277 // Set the result size to 0 so the client does not have to check for success.
11278 result->SetNumResults(0);
11279 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
11280 if (!program) {
11281 return false;
11283 if (!program->IsValid()) {
11284 // Program was not linked successfully. (ie, glLinkProgram)
11285 LOCAL_SET_GL_ERROR(
11286 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
11287 return false;
11289 *service_id = program->service_id();
11290 GLint array_index = -1;
11291 const Program::UniformInfo* uniform_info =
11292 program->GetUniformInfoByFakeLocation(
11293 fake_location, real_location, &array_index);
11294 if (!uniform_info) {
11295 // No such location.
11296 LOCAL_SET_GL_ERROR(
11297 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
11298 return false;
11300 GLenum type = uniform_info->type;
11301 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
11302 if (num_elements == 0) {
11303 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
11304 return false;
11306 result = GetSharedMemoryAs<SizedResult<T>*>(
11307 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
11308 if (!result) {
11309 *error = error::kOutOfBounds;
11310 return false;
11312 result->SetNumResults(num_elements);
11313 *result_size = num_elements * sizeof(T);
11314 *result_type = type;
11315 return true;
11318 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
11319 const void* cmd_data) {
11320 const gles2::cmds::GetUniformiv& c =
11321 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
11322 GLuint program = c.program;
11323 GLint fake_location = c.location;
11324 GLuint service_id;
11325 GLenum result_type;
11326 GLsizei result_size;
11327 GLint real_location = -1;
11328 Error error;
11329 cmds::GetUniformiv::Result* result;
11330 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
11331 c.params_shm_offset, &error, &real_location,
11332 &service_id, &result, &result_type,
11333 &result_size)) {
11334 glGetUniformiv(
11335 service_id, real_location, result->GetData());
11337 return error;
11340 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
11341 const void* cmd_data) {
11342 if (!unsafe_es3_apis_enabled())
11343 return error::kUnknownCommand;
11345 const gles2::cmds::GetUniformuiv& c =
11346 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
11347 GLuint program = c.program;
11348 GLint fake_location = c.location;
11349 GLuint service_id;
11350 GLenum result_type;
11351 GLsizei result_size;
11352 GLint real_location = -1;
11353 Error error;
11354 cmds::GetUniformuiv::Result* result;
11355 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
11356 c.params_shm_offset, &error, &real_location,
11357 &service_id, &result, &result_type,
11358 &result_size)) {
11359 glGetUniformuiv(
11360 service_id, real_location, result->GetData());
11362 return error;
11365 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
11366 const void* cmd_data) {
11367 const gles2::cmds::GetUniformfv& c =
11368 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
11369 GLuint program = c.program;
11370 GLint fake_location = c.location;
11371 GLuint service_id;
11372 GLint real_location = -1;
11373 Error error;
11374 cmds::GetUniformfv::Result* result;
11375 GLenum result_type;
11376 GLsizei result_size;
11377 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
11378 c.params_shm_offset, &error, &real_location,
11379 &service_id, &result, &result_type,
11380 &result_size)) {
11381 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
11382 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
11383 GLsizei num_values = result_size / sizeof(GLfloat);
11384 scoped_ptr<GLint[]> temp(new GLint[num_values]);
11385 glGetUniformiv(service_id, real_location, temp.get());
11386 GLfloat* dst = result->GetData();
11387 for (GLsizei ii = 0; ii < num_values; ++ii) {
11388 dst[ii] = (temp[ii] != 0);
11390 } else {
11391 glGetUniformfv(service_id, real_location, result->GetData());
11394 return error;
11397 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
11398 uint32 immediate_data_size,
11399 const void* cmd_data) {
11400 const gles2::cmds::GetShaderPrecisionFormat& c =
11401 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
11402 GLenum shader_type = static_cast<GLenum>(c.shadertype);
11403 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
11404 typedef cmds::GetShaderPrecisionFormat::Result Result;
11405 Result* result = GetSharedMemoryAs<Result*>(
11406 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11407 if (!result) {
11408 return error::kOutOfBounds;
11410 // Check that the client initialized the result.
11411 if (result->success != 0) {
11412 return error::kInvalidArguments;
11414 if (!validators_->shader_type.IsValid(shader_type)) {
11415 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11416 "glGetShaderPrecisionFormat", shader_type, "shader_type");
11417 return error::kNoError;
11419 if (!validators_->shader_precision.IsValid(precision_type)) {
11420 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11421 "glGetShaderPrecisionFormat", precision_type, "precision_type");
11422 return error::kNoError;
11425 result->success = 1; // true
11427 GLint range[2] = { 0, 0 };
11428 GLint precision = 0;
11429 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
11431 result->min_range = range[0];
11432 result->max_range = range[1];
11433 result->precision = precision;
11435 return error::kNoError;
11438 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
11439 uint32 immediate_data_size,
11440 const void* cmd_data) {
11441 const gles2::cmds::GetAttachedShaders& c =
11442 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
11443 uint32 result_size = c.result_size;
11444 GLuint program_id = static_cast<GLuint>(c.program);
11445 Program* program = GetProgramInfoNotShader(
11446 program_id, "glGetAttachedShaders");
11447 if (!program) {
11448 return error::kNoError;
11450 typedef cmds::GetAttachedShaders::Result Result;
11451 uint32 max_count = Result::ComputeMaxResults(result_size);
11452 Result* result = GetSharedMemoryAs<Result*>(
11453 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
11454 if (!result) {
11455 return error::kOutOfBounds;
11457 // Check that the client initialized the result.
11458 if (result->size != 0) {
11459 return error::kInvalidArguments;
11461 GLsizei count = 0;
11462 glGetAttachedShaders(
11463 program->service_id(), max_count, &count, result->GetData());
11464 for (GLsizei ii = 0; ii < count; ++ii) {
11465 if (!shader_manager()->GetClientId(result->GetData()[ii],
11466 &result->GetData()[ii])) {
11467 NOTREACHED();
11468 return error::kGenericError;
11471 result->SetNumResults(count);
11472 return error::kNoError;
11475 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
11476 uint32 immediate_data_size,
11477 const void* cmd_data) {
11478 const gles2::cmds::GetActiveUniform& c =
11479 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
11480 GLuint program_id = c.program;
11481 GLuint index = c.index;
11482 uint32 name_bucket_id = c.name_bucket_id;
11483 typedef cmds::GetActiveUniform::Result Result;
11484 Result* result = GetSharedMemoryAs<Result*>(
11485 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11486 if (!result) {
11487 return error::kOutOfBounds;
11489 // Check that the client initialized the result.
11490 if (result->success != 0) {
11491 return error::kInvalidArguments;
11493 Program* program = GetProgramInfoNotShader(
11494 program_id, "glGetActiveUniform");
11495 if (!program) {
11496 return error::kNoError;
11498 const Program::UniformInfo* uniform_info =
11499 program->GetUniformInfo(index);
11500 if (!uniform_info) {
11501 LOCAL_SET_GL_ERROR(
11502 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
11503 return error::kNoError;
11505 result->success = 1; // true.
11506 result->size = uniform_info->size;
11507 result->type = uniform_info->type;
11508 Bucket* bucket = CreateBucket(name_bucket_id);
11509 bucket->SetFromString(uniform_info->name.c_str());
11510 return error::kNoError;
11513 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
11514 uint32 immediate_data_size, const void* cmd_data) {
11515 if (!unsafe_es3_apis_enabled())
11516 return error::kUnknownCommand;
11517 const gles2::cmds::GetActiveUniformBlockiv& c =
11518 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
11519 GLuint program_id = c.program;
11520 GLuint index = static_cast<GLuint>(c.index);
11521 GLenum pname = static_cast<GLenum>(c.pname);
11522 Program* program = GetProgramInfoNotShader(
11523 program_id, "glGetActiveUniformBlockiv");
11524 if (!program) {
11525 return error::kNoError;
11527 GLuint service_id = program->service_id();
11528 GLint link_status = GL_FALSE;
11529 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11530 if (link_status != GL_TRUE) {
11531 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11532 "glGetActiveActiveUniformBlockiv", "program not linked");
11533 return error::kNoError;
11535 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
11536 GLsizei num_values = 1;
11537 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
11538 GLint num = 0;
11539 glGetActiveUniformBlockiv(
11540 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
11541 GLenum error = glGetError();
11542 if (error != GL_NO_ERROR) {
11543 // Assume this will the same error if calling with pname.
11544 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
11545 return error::kNoError;
11547 num_values = static_cast<GLsizei>(num);
11549 typedef cmds::GetActiveUniformBlockiv::Result Result;
11550 Result* result = GetSharedMemoryAs<Result*>(
11551 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
11552 GLint* params = result ? result->GetData() : NULL;
11553 if (params == NULL) {
11554 return error::kOutOfBounds;
11556 // Check that the client initialized the result.
11557 if (result->size != 0) {
11558 return error::kInvalidArguments;
11560 glGetActiveUniformBlockiv(service_id, index, pname, params);
11561 GLenum error = glGetError();
11562 if (error == GL_NO_ERROR) {
11563 result->SetNumResults(num_values);
11564 } else {
11565 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
11567 return error::kNoError;
11570 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11571 uint32 immediate_data_size, const void* cmd_data) {
11572 if (!unsafe_es3_apis_enabled())
11573 return error::kUnknownCommand;
11574 const gles2::cmds::GetActiveUniformBlockName& c =
11575 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
11576 GLuint program_id = c.program;
11577 GLuint index = c.index;
11578 uint32 name_bucket_id = c.name_bucket_id;
11579 typedef cmds::GetActiveUniformBlockName::Result Result;
11580 Result* result = GetSharedMemoryAs<Result*>(
11581 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11582 if (!result) {
11583 return error::kOutOfBounds;
11585 // Check that the client initialized the result.
11586 if (*result != 0) {
11587 return error::kInvalidArguments;
11589 Program* program = GetProgramInfoNotShader(
11590 program_id, "glGetActiveUniformBlockName");
11591 if (!program) {
11592 return error::kNoError;
11594 GLuint service_id = program->service_id();
11595 GLint link_status = GL_FALSE;
11596 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11597 if (link_status != GL_TRUE) {
11598 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11599 "glGetActiveActiveUniformBlockName", "program not linked");
11600 return error::kNoError;
11602 GLint max_length = 0;
11603 glGetProgramiv(
11604 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
11605 // Increase one so &buffer[0] is always valid.
11606 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
11607 std::vector<char> buffer(buf_size);
11608 GLsizei length = 0;
11609 glGetActiveUniformBlockName(
11610 service_id, index, buf_size, &length, &buffer[0]);
11611 if (length == 0) {
11612 *result = 0;
11613 return error::kNoError;
11615 *result = 1;
11616 Bucket* bucket = CreateBucket(name_bucket_id);
11617 DCHECK_GT(buf_size, length);
11618 DCHECK_EQ(0, buffer[length]);
11619 bucket->SetFromString(&buffer[0]);
11620 return error::kNoError;
11623 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
11624 uint32 immediate_data_size, const void* cmd_data) {
11625 if (!unsafe_es3_apis_enabled())
11626 return error::kUnknownCommand;
11627 const gles2::cmds::GetActiveUniformsiv& c =
11628 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
11629 GLuint program_id = c.program;
11630 GLenum pname = static_cast<GLenum>(c.pname);
11631 Bucket* bucket = GetBucket(c.indices_bucket_id);
11632 if (!bucket) {
11633 return error::kInvalidArguments;
11635 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
11636 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
11637 typedef cmds::GetActiveUniformsiv::Result Result;
11638 Result* result = GetSharedMemoryAs<Result*>(
11639 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
11640 GLint* params = result ? result->GetData() : NULL;
11641 if (params == NULL) {
11642 return error::kOutOfBounds;
11644 // Check that the client initialized the result.
11645 if (result->size != 0) {
11646 return error::kInvalidArguments;
11648 Program* program = GetProgramInfoNotShader(
11649 program_id, "glGetActiveUniformsiv");
11650 if (!program) {
11651 return error::kNoError;
11653 GLuint service_id = program->service_id();
11654 GLint link_status = GL_FALSE;
11655 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11656 if (link_status != GL_TRUE) {
11657 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11658 "glGetActiveUniformsiv", "program not linked");
11659 return error::kNoError;
11661 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11662 glGetActiveUniformsiv(service_id, count, indices, pname, params);
11663 GLenum error = glGetError();
11664 if (error == GL_NO_ERROR) {
11665 result->SetNumResults(count);
11666 } else {
11667 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
11669 return error::kNoError;
11672 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
11673 const void* cmd_data) {
11674 const gles2::cmds::GetActiveAttrib& c =
11675 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
11676 GLuint program_id = c.program;
11677 GLuint index = c.index;
11678 uint32 name_bucket_id = c.name_bucket_id;
11679 typedef cmds::GetActiveAttrib::Result Result;
11680 Result* result = GetSharedMemoryAs<Result*>(
11681 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11682 if (!result) {
11683 return error::kOutOfBounds;
11685 // Check that the client initialized the result.
11686 if (result->success != 0) {
11687 return error::kInvalidArguments;
11689 Program* program = GetProgramInfoNotShader(
11690 program_id, "glGetActiveAttrib");
11691 if (!program) {
11692 return error::kNoError;
11694 const Program::VertexAttrib* attrib_info =
11695 program->GetAttribInfo(index);
11696 if (!attrib_info) {
11697 LOCAL_SET_GL_ERROR(
11698 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
11699 return error::kNoError;
11701 result->success = 1; // true.
11702 result->size = attrib_info->size;
11703 result->type = attrib_info->type;
11704 Bucket* bucket = CreateBucket(name_bucket_id);
11705 bucket->SetFromString(attrib_info->name.c_str());
11706 return error::kNoError;
11709 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
11710 const void* cmd_data) {
11711 #if 1 // No binary shader support.
11712 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
11713 return error::kNoError;
11714 #else
11715 GLsizei n = static_cast<GLsizei>(c.n);
11716 if (n < 0) {
11717 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
11718 return error::kNoError;
11720 GLsizei length = static_cast<GLsizei>(c.length);
11721 if (length < 0) {
11722 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
11723 return error::kNoError;
11725 uint32 data_size;
11726 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
11727 return error::kOutOfBounds;
11729 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
11730 c.shaders_shm_id, c.shaders_shm_offset, data_size);
11731 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
11732 const void* binary = GetSharedMemoryAs<const void*>(
11733 c.binary_shm_id, c.binary_shm_offset, length);
11734 if (shaders == NULL || binary == NULL) {
11735 return error::kOutOfBounds;
11737 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11738 for (GLsizei ii = 0; ii < n; ++ii) {
11739 Shader* shader = GetShader(shaders[ii]);
11740 if (!shader) {
11741 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
11742 return error::kNoError;
11744 service_ids[ii] = shader->service_id();
11746 // TODO(gman): call glShaderBinary
11747 return error::kNoError;
11748 #endif
11751 void GLES2DecoderImpl::DoSwapBuffers() {
11752 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
11754 int this_frame_number = frame_number_++;
11755 // TRACE_EVENT for gpu tests:
11756 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11757 TRACE_EVENT_SCOPE_THREAD,
11758 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11759 "width", (is_offscreen ? offscreen_size_.width() :
11760 surface_->GetSize().width()));
11761 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11762 "offscreen", is_offscreen,
11763 "frame", this_frame_number);
11765 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11768 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
11769 "GLES2Decoder", "SwapBuffer");
11771 bool is_tracing;
11772 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11773 &is_tracing);
11774 if (is_tracing) {
11775 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
11776 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
11777 is_offscreen ? offscreen_size_ : surface_->GetSize());
11780 // If offscreen then don't actually SwapBuffers to the display. Just copy
11781 // the rendered frame to another frame buffer.
11782 if (is_offscreen) {
11783 TRACE_EVENT2("gpu", "Offscreen",
11784 "width", offscreen_size_.width(), "height", offscreen_size_.height());
11785 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
11786 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11787 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11788 // fix this.
11789 if (workarounds().needs_offscreen_buffer_workaround) {
11790 offscreen_saved_frame_buffer_->Create();
11791 glFinish();
11794 // Allocate the offscreen saved color texture.
11795 DCHECK(offscreen_saved_color_format_);
11796 offscreen_saved_color_texture_->AllocateStorage(
11797 offscreen_size_, offscreen_saved_color_format_, false);
11799 offscreen_saved_frame_buffer_->AttachRenderTexture(
11800 offscreen_saved_color_texture_.get());
11801 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
11802 if (offscreen_saved_frame_buffer_->CheckStatus() !=
11803 GL_FRAMEBUFFER_COMPLETE) {
11804 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11805 << "because offscreen saved FBO was incomplete.";
11806 MarkContextLost(error::kUnknown);
11807 group_->LoseContexts(error::kUnknown);
11808 return;
11811 // Clear the offscreen color texture.
11812 // TODO(piman): Is this still necessary?
11814 ScopedFrameBufferBinder binder(this,
11815 offscreen_saved_frame_buffer_->id());
11816 glClearColor(0, 0, 0, 0);
11817 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
11818 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
11819 glClear(GL_COLOR_BUFFER_BIT);
11820 RestoreClearState();
11824 UpdateParentTextureInfo();
11827 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
11828 return;
11829 ScopedGLErrorSuppressor suppressor(
11830 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11832 if (IsOffscreenBufferMultisampled()) {
11833 // For multisampled buffers, resolve the frame buffer.
11834 ScopedResolvedFrameBufferBinder binder(this, true, false);
11835 } else {
11836 ScopedFrameBufferBinder binder(this,
11837 offscreen_target_frame_buffer_->id());
11839 if (offscreen_target_buffer_preserved_) {
11840 // Copy the target frame buffer to the saved offscreen texture.
11841 offscreen_saved_color_texture_->Copy(
11842 offscreen_saved_color_texture_->size(),
11843 offscreen_saved_color_format_);
11844 } else {
11845 // Flip the textures in the parent context via the texture manager.
11846 if (!!offscreen_saved_color_texture_info_.get())
11847 offscreen_saved_color_texture_info_->texture()->
11848 SetServiceId(offscreen_target_color_texture_->id());
11850 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
11851 offscreen_target_frame_buffer_->AttachRenderTexture(
11852 offscreen_target_color_texture_.get());
11855 // Ensure the side effects of the copy are visible to the parent
11856 // context. There is no need to do this for ANGLE because it uses a
11857 // single D3D device for all contexts.
11858 if (!feature_info_->gl_version_info().is_angle)
11859 glFlush();
11861 } else {
11862 if (surface_->SwapBuffers() == gfx::SwapResult::SWAP_FAILED) {
11863 LOG(ERROR) << "Context lost because SwapBuffers failed.";
11864 if (!CheckResetStatus()) {
11865 MarkContextLost(error::kUnknown);
11866 group_->LoseContexts(error::kUnknown);
11871 // This may be a slow command. Exit command processing to allow for
11872 // context preemption and GPU watchdog checks.
11873 ExitCommandProcessingEarly();
11876 void GLES2DecoderImpl::DoSwapInterval(int interval) {
11877 context_->SetSwapInterval(interval);
11880 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11881 uint32 immediate_data_size,
11882 const void* cmd_data) {
11883 const gles2::cmds::EnableFeatureCHROMIUM& c =
11884 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
11885 Bucket* bucket = GetBucket(c.bucket_id);
11886 if (!bucket || bucket->size() == 0) {
11887 return error::kInvalidArguments;
11889 typedef cmds::EnableFeatureCHROMIUM::Result Result;
11890 Result* result = GetSharedMemoryAs<Result*>(
11891 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11892 if (!result) {
11893 return error::kOutOfBounds;
11895 // Check that the client initialized the result.
11896 if (*result != 0) {
11897 return error::kInvalidArguments;
11899 std::string feature_str;
11900 if (!bucket->GetAsString(&feature_str)) {
11901 return error::kInvalidArguments;
11904 // TODO(gman): make this some kind of table to function pointer thingy.
11905 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11906 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11907 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
11908 buffer_manager()->set_allow_fixed_attribs(true);
11909 // TODO(gman): decide how to remove the need for this const_cast.
11910 // I could make validators_ non const but that seems bad as this is the only
11911 // place it is needed. I could make some special friend class of validators
11912 // just to allow this to set them. That seems silly. I could refactor this
11913 // code to use the extension mechanism or the initialization attributes to
11914 // turn this feature on. Given that the only real point of this is to make
11915 // the conformance tests pass and given that there is lots of real work that
11916 // needs to be done it seems like refactoring for one to one of those
11917 // methods is a very low priority.
11918 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
11919 } else {
11920 return error::kNoError;
11923 *result = 1; // true.
11924 return error::kNoError;
11927 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11928 uint32 immediate_data_size,
11929 const void* cmd_data) {
11930 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
11931 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
11932 cmd_data);
11933 Bucket* bucket = CreateBucket(c.bucket_id);
11934 scoped_refptr<FeatureInfo> info(new FeatureInfo());
11935 info->Initialize(disallowed_features_);
11936 bucket->SetFromString(info->extensions().c_str());
11937 return error::kNoError;
11940 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11941 uint32 immediate_data_size,
11942 const void* cmd_data) {
11943 const gles2::cmds::RequestExtensionCHROMIUM& c =
11944 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
11945 Bucket* bucket = GetBucket(c.bucket_id);
11946 if (!bucket || bucket->size() == 0) {
11947 return error::kInvalidArguments;
11949 std::string feature_str;
11950 if (!bucket->GetAsString(&feature_str)) {
11951 return error::kInvalidArguments;
11954 bool desire_standard_derivatives = false;
11955 bool desire_frag_depth = false;
11956 bool desire_draw_buffers = false;
11957 bool desire_shader_texture_lod = false;
11958 if (IsWebGLContext()) {
11959 desire_standard_derivatives =
11960 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
11961 desire_frag_depth =
11962 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
11963 desire_draw_buffers =
11964 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
11965 desire_shader_texture_lod =
11966 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
11969 if (desire_standard_derivatives != derivatives_explicitly_enabled_ ||
11970 desire_frag_depth != frag_depth_explicitly_enabled_ ||
11971 desire_draw_buffers != draw_buffers_explicitly_enabled_ ||
11972 desire_shader_texture_lod != shader_texture_lod_explicitly_enabled_) {
11973 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
11974 frag_depth_explicitly_enabled_ |= desire_frag_depth;
11975 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
11976 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
11977 InitializeShaderTranslator();
11980 UpdateCapabilities();
11982 return error::kNoError;
11985 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11986 uint32 immediate_data_size,
11987 const void* cmd_data) {
11988 const gles2::cmds::GetProgramInfoCHROMIUM& c =
11989 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
11990 GLuint program_id = static_cast<GLuint>(c.program);
11991 uint32 bucket_id = c.bucket_id;
11992 Bucket* bucket = CreateBucket(bucket_id);
11993 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
11994 Program* program = NULL;
11995 program = GetProgram(program_id);
11996 if (!program || !program->IsValid()) {
11997 return error::kNoError;
11999 program->GetProgramInfo(program_manager(), bucket);
12000 return error::kNoError;
12003 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
12004 uint32 immediate_data_size, const void* cmd_data) {
12005 if (!unsafe_es3_apis_enabled())
12006 return error::kUnknownCommand;
12007 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
12008 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
12009 GLuint program_id = static_cast<GLuint>(c.program);
12010 uint32 bucket_id = c.bucket_id;
12011 Bucket* bucket = CreateBucket(bucket_id);
12012 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
12013 Program* program = NULL;
12014 program = GetProgram(program_id);
12015 if (!program || !program->IsValid()) {
12016 return error::kNoError;
12018 program->GetUniformBlocks(bucket);
12019 return error::kNoError;
12022 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
12023 uint32 immediate_data_size, const void* cmd_data) {
12024 if (!unsafe_es3_apis_enabled())
12025 return error::kUnknownCommand;
12026 const gles2::cmds::GetUniformsES3CHROMIUM& c =
12027 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
12028 GLuint program_id = static_cast<GLuint>(c.program);
12029 uint32 bucket_id = c.bucket_id;
12030 Bucket* bucket = CreateBucket(bucket_id);
12031 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
12032 Program* program = NULL;
12033 program = GetProgram(program_id);
12034 if (!program || !program->IsValid()) {
12035 return error::kNoError;
12037 program->GetUniformsES3(bucket);
12038 return error::kNoError;
12041 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
12042 uint32 immediate_data_size,
12043 const void* cmd_data) {
12044 if (!unsafe_es3_apis_enabled())
12045 return error::kUnknownCommand;
12046 const gles2::cmds::GetTransformFeedbackVarying& c =
12047 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
12048 GLuint program_id = c.program;
12049 GLuint index = c.index;
12050 uint32 name_bucket_id = c.name_bucket_id;
12051 typedef cmds::GetTransformFeedbackVarying::Result Result;
12052 Result* result = GetSharedMemoryAs<Result*>(
12053 c.result_shm_id, c.result_shm_offset, sizeof(*result));
12054 if (!result) {
12055 return error::kOutOfBounds;
12057 // Check that the client initialized the result.
12058 if (result->success != 0) {
12059 return error::kInvalidArguments;
12061 Program* program = GetProgramInfoNotShader(
12062 program_id, "glGetTransformFeedbackVarying");
12063 if (!program) {
12064 return error::kNoError;
12066 GLuint service_id = program->service_id();
12067 GLint link_status = GL_FALSE;
12068 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
12069 if (link_status != GL_TRUE) {
12070 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12071 "glGetTransformFeedbackVarying", "program not linked");
12072 return error::kNoError;
12074 GLint max_length = 0;
12075 glGetProgramiv(
12076 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
12077 max_length = std::max(1, max_length);
12078 std::vector<char> buffer(max_length);
12079 GLsizei length = 0;
12080 GLsizei size = 0;
12081 GLenum type = 0;
12082 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
12083 glGetTransformFeedbackVarying(
12084 service_id, index, max_length, &length, &size, &type, &buffer[0]);
12085 GLenum error = glGetError();
12086 if (error != GL_NO_ERROR) {
12087 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
12088 return error::kNoError;
12090 result->success = 1; // true.
12091 result->size = static_cast<int32_t>(size);
12092 result->type = static_cast<uint32_t>(type);
12093 Bucket* bucket = CreateBucket(name_bucket_id);
12094 DCHECK(length >= 0 && length < max_length);
12095 buffer[length] = '\0'; // Just to be safe.
12096 bucket->SetFromString(&buffer[0]);
12097 return error::kNoError;
12100 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
12101 uint32 immediate_data_size, const void* cmd_data) {
12102 if (!unsafe_es3_apis_enabled())
12103 return error::kUnknownCommand;
12104 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
12105 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
12106 cmd_data);
12107 GLuint program_id = static_cast<GLuint>(c.program);
12108 uint32 bucket_id = c.bucket_id;
12109 Bucket* bucket = CreateBucket(bucket_id);
12110 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
12111 Program* program = NULL;
12112 program = GetProgram(program_id);
12113 if (!program || !program->IsValid()) {
12114 return error::kNoError;
12116 program->GetTransformFeedbackVaryings(bucket);
12117 return error::kNoError;
12120 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
12121 return context_lost_reason_;
12124 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
12125 GLenum reset_status) const {
12126 switch (reset_status) {
12127 case GL_NO_ERROR:
12128 // TODO(kbr): improve the precision of the error code in this case.
12129 // Consider delegating to context for error code if MakeCurrent fails.
12130 return error::kUnknown;
12131 case GL_GUILTY_CONTEXT_RESET_ARB:
12132 return error::kGuilty;
12133 case GL_INNOCENT_CONTEXT_RESET_ARB:
12134 return error::kInnocent;
12135 case GL_UNKNOWN_CONTEXT_RESET_ARB:
12136 return error::kUnknown;
12139 NOTREACHED();
12140 return error::kUnknown;
12143 bool GLES2DecoderImpl::WasContextLost() const {
12144 return context_was_lost_;
12147 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
12148 return WasContextLost() && reset_by_robustness_extension_;
12151 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
12152 // Only lose the context once.
12153 if (WasContextLost())
12154 return;
12156 // Don't make GL calls in here, the context might not be current.
12157 context_lost_reason_ = reason;
12158 current_decoder_error_ = error::kLostContext;
12159 context_was_lost_ = true;
12162 bool GLES2DecoderImpl::CheckResetStatus() {
12163 DCHECK(!WasContextLost());
12164 DCHECK(context_->IsCurrent(NULL));
12166 if (IsRobustnessSupported()) {
12167 // If the reason for the call was a GL error, we can try to determine the
12168 // reset status more accurately.
12169 GLenum driver_status = glGetGraphicsResetStatusARB();
12170 if (driver_status == GL_NO_ERROR)
12171 return false;
12173 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
12174 << " context lost via ARB/EXT_robustness. Reset status = "
12175 << GLES2Util::GetStringEnum(driver_status);
12177 // Don't pretend we know which client was responsible.
12178 if (workarounds().use_virtualized_gl_contexts)
12179 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
12181 switch (driver_status) {
12182 case GL_GUILTY_CONTEXT_RESET_ARB:
12183 MarkContextLost(error::kGuilty);
12184 break;
12185 case GL_INNOCENT_CONTEXT_RESET_ARB:
12186 MarkContextLost(error::kInnocent);
12187 break;
12188 case GL_UNKNOWN_CONTEXT_RESET_ARB:
12189 MarkContextLost(error::kUnknown);
12190 break;
12191 default:
12192 NOTREACHED();
12193 return false;
12195 reset_by_robustness_extension_ = true;
12196 return true;
12198 return false;
12201 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
12202 uint32 immediate_data_size,
12203 const void* cmd_data) {
12204 return error::kUnknownCommand;
12207 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
12208 uint32 immediate_data_size,
12209 const void* cmd_data) {
12210 const gles2::cmds::WaitSyncPointCHROMIUM& c =
12211 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
12212 uint32 sync_point = c.sync_point;
12213 if (wait_sync_point_callback_.is_null())
12214 return error::kNoError;
12216 return wait_sync_point_callback_.Run(sync_point) ?
12217 error::kNoError : error::kDeferCommandUntilLater;
12220 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
12221 uint32 immediate_data_size,
12222 const void* cmd_data) {
12223 if (surface_->DeferDraws())
12224 return error::kDeferCommandUntilLater;
12225 if (!surface_->SetBackbufferAllocation(false))
12226 return error::kLostContext;
12227 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
12228 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
12229 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
12230 return error::kNoError;
12233 bool GLES2DecoderImpl::GenQueriesEXTHelper(
12234 GLsizei n, const GLuint* client_ids) {
12235 for (GLsizei ii = 0; ii < n; ++ii) {
12236 if (query_manager_->GetQuery(client_ids[ii])) {
12237 return false;
12240 query_manager_->GenQueries(n, client_ids);
12241 return true;
12244 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
12245 GLsizei n, const GLuint* client_ids) {
12246 for (GLsizei ii = 0; ii < n; ++ii) {
12247 query_manager_->RemoveQuery(client_ids[ii]);
12251 bool GLES2DecoderImpl::HasPendingQueries() const {
12252 return query_manager_.get() && query_manager_->HavePendingQueries();
12255 void GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
12256 if (!query_manager_.get())
12257 return;
12258 if (!query_manager_->ProcessPendingQueries(did_finish))
12259 current_decoder_error_ = error::kOutOfBounds;
12262 // Note that if there are no pending readpixels right now,
12263 // this function will call the callback immediately.
12264 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
12265 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
12266 pending_readpixel_fences_.back()->callbacks.push_back(callback);
12267 } else {
12268 callback.Run();
12272 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish) {
12273 // Note: |did_finish| guarantees that the GPU has passed the fence but
12274 // we cannot assume that GLFence::HasCompleted() will return true yet as
12275 // that's not guaranteed by all GLFence implementations.
12276 while (!pending_readpixel_fences_.empty() &&
12277 (did_finish ||
12278 pending_readpixel_fences_.front()->fence->HasCompleted())) {
12279 std::vector<base::Closure> callbacks =
12280 pending_readpixel_fences_.front()->callbacks;
12281 pending_readpixel_fences_.pop();
12282 for (size_t i = 0; i < callbacks.size(); i++) {
12283 callbacks[i].Run();
12288 bool GLES2DecoderImpl::HasMoreIdleWork() const {
12289 return !pending_readpixel_fences_.empty() ||
12290 gpu_tracer_->HasTracesToProcess();
12293 void GLES2DecoderImpl::PerformIdleWork() {
12294 gpu_tracer_->ProcessTraces();
12295 ProcessPendingReadPixels(false);
12298 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
12299 const void* cmd_data) {
12300 const gles2::cmds::BeginQueryEXT& c =
12301 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
12302 GLenum target = static_cast<GLenum>(c.target);
12303 GLuint client_id = static_cast<GLuint>(c.id);
12304 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
12305 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12307 switch (target) {
12308 case GL_COMMANDS_ISSUED_CHROMIUM:
12309 case GL_LATENCY_QUERY_CHROMIUM:
12310 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
12311 case GL_GET_ERROR_QUERY_CHROMIUM:
12312 break;
12313 case GL_COMMANDS_COMPLETED_CHROMIUM:
12314 if (!features().chromium_sync_query) {
12315 LOCAL_SET_GL_ERROR(
12316 GL_INVALID_OPERATION, "glBeginQueryEXT",
12317 "not enabled for commands completed queries");
12318 return error::kNoError;
12320 break;
12321 case GL_SAMPLES_PASSED:
12322 case GL_ANY_SAMPLES_PASSED:
12323 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
12324 if (!features().occlusion_query_boolean) {
12325 LOCAL_SET_GL_ERROR(
12326 GL_INVALID_OPERATION, "glBeginQueryEXT",
12327 "not enabled for occlusion queries");
12328 return error::kNoError;
12330 break;
12331 case GL_TIME_ELAPSED:
12332 if (!query_manager_->GPUTimingAvailable()) {
12333 LOCAL_SET_GL_ERROR(
12334 GL_INVALID_OPERATION, "glBeginQueryEXT",
12335 "not enabled for timing queries");
12336 return error::kNoError;
12338 break;
12339 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
12340 if (feature_info_->IsES3Enabled()) {
12341 break;
12343 // Fall through.
12344 default:
12345 LOCAL_SET_GL_ERROR(
12346 GL_INVALID_ENUM, "glBeginQueryEXT",
12347 "unknown query target");
12348 return error::kNoError;
12351 if (query_manager_->GetActiveQuery(target)) {
12352 LOCAL_SET_GL_ERROR(
12353 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
12354 return error::kNoError;
12357 if (client_id == 0) {
12358 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
12359 return error::kNoError;
12362 QueryManager::Query* query = query_manager_->GetQuery(client_id);
12363 if (!query) {
12364 if (!query_manager_->IsValidQuery(client_id)) {
12365 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12366 "glBeginQueryEXT",
12367 "id not made by glGenQueriesEXT");
12368 return error::kNoError;
12370 query = query_manager_->CreateQuery(
12371 target, client_id, sync_shm_id, sync_shm_offset);
12374 if (query->target() != target) {
12375 LOCAL_SET_GL_ERROR(
12376 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
12377 return error::kNoError;
12378 } else if (query->shm_id() != sync_shm_id ||
12379 query->shm_offset() != sync_shm_offset) {
12380 DLOG(ERROR) << "Shared memory used by query not the same as before";
12381 return error::kInvalidArguments;
12384 if (!query_manager_->BeginQuery(query)) {
12385 return error::kOutOfBounds;
12388 return error::kNoError;
12391 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
12392 const void* cmd_data) {
12393 const gles2::cmds::EndQueryEXT& c =
12394 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
12395 GLenum target = static_cast<GLenum>(c.target);
12396 uint32 submit_count = static_cast<GLuint>(c.submit_count);
12398 QueryManager::Query* query = query_manager_->GetActiveQuery(target);
12399 if (!query) {
12400 LOCAL_SET_GL_ERROR(
12401 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
12402 return error::kNoError;
12405 if (!query_manager_->EndQuery(query, submit_count)) {
12406 return error::kOutOfBounds;
12409 query_manager_->ProcessPendingTransferQueries();
12411 return error::kNoError;
12414 error::Error GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size,
12415 const void* cmd_data) {
12416 const gles2::cmds::QueryCounterEXT& c =
12417 *static_cast<const gles2::cmds::QueryCounterEXT*>(cmd_data);
12418 GLuint client_id = static_cast<GLuint>(c.id);
12419 GLenum target = static_cast<GLenum>(c.target);
12420 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
12421 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12422 uint32 submit_count = static_cast<GLuint>(c.submit_count);
12424 switch (target) {
12425 case GL_TIMESTAMP:
12426 if (!query_manager_->GPUTimingAvailable()) {
12427 LOCAL_SET_GL_ERROR(
12428 GL_INVALID_OPERATION, "glQueryCounterEXT",
12429 "not enabled for timing queries");
12430 return error::kNoError;
12432 break;
12433 default:
12434 LOCAL_SET_GL_ERROR(
12435 GL_INVALID_ENUM, "glQueryCounterEXT",
12436 "unknown query target");
12437 return error::kNoError;
12440 QueryManager::Query* query = query_manager_->GetQuery(client_id);
12441 if (!query) {
12442 if (!query_manager_->IsValidQuery(client_id)) {
12443 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12444 "glQueryCounterEXT",
12445 "id not made by glGenQueriesEXT");
12446 return error::kNoError;
12448 query = query_manager_->CreateQuery(
12449 target, client_id, sync_shm_id, sync_shm_offset);
12451 if (!query_manager_->QueryCounter(query, submit_count)) {
12452 return error::kOutOfBounds;
12455 return error::kNoError;
12458 error::Error GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
12459 uint32 immediate_data_size, const void* cmd_data) {
12460 const gles2::cmds::SetDisjointValueSyncCHROMIUM& c =
12461 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM*>(cmd_data);
12462 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
12463 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12465 query_manager_->SetDisjointSync(sync_shm_id, sync_shm_offset);
12466 return error::kNoError;
12469 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
12470 GLsizei n, const GLuint* client_ids) {
12471 for (GLsizei ii = 0; ii < n; ++ii) {
12472 if (GetVertexAttribManager(client_ids[ii])) {
12473 return false;
12477 if (!features().native_vertex_array_object) {
12478 // Emulated VAO
12479 for (GLsizei ii = 0; ii < n; ++ii) {
12480 CreateVertexAttribManager(client_ids[ii], 0, true);
12482 } else {
12483 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
12485 glGenVertexArraysOES(n, service_ids.get());
12486 for (GLsizei ii = 0; ii < n; ++ii) {
12487 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
12491 return true;
12494 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
12495 GLsizei n, const GLuint* client_ids) {
12496 for (GLsizei ii = 0; ii < n; ++ii) {
12497 VertexAttribManager* vao =
12498 GetVertexAttribManager(client_ids[ii]);
12499 if (vao && !vao->IsDeleted()) {
12500 if (state_.vertex_attrib_manager.get() == vao) {
12501 DoBindVertexArrayOES(0);
12503 RemoveVertexAttribManager(client_ids[ii]);
12508 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
12509 VertexAttribManager* vao = NULL;
12510 if (client_id != 0) {
12511 vao = GetVertexAttribManager(client_id);
12512 if (!vao) {
12513 // Unlike most Bind* methods, the spec explicitly states that VertexArray
12514 // only allows names that have been previously generated. As such, we do
12515 // not generate new names here.
12516 LOCAL_SET_GL_ERROR(
12517 GL_INVALID_OPERATION,
12518 "glBindVertexArrayOES", "bad vertex array id.");
12519 current_decoder_error_ = error::kNoError;
12520 return;
12522 } else {
12523 vao = state_.default_vertex_attrib_manager.get();
12526 // Only set the VAO state if it's changed
12527 if (state_.vertex_attrib_manager.get() != vao) {
12528 state_.vertex_attrib_manager = vao;
12529 if (!features().native_vertex_array_object) {
12530 EmulateVertexArrayState();
12531 } else {
12532 GLuint service_id = vao->service_id();
12533 glBindVertexArrayOES(service_id);
12538 // Used when OES_vertex_array_object isn't natively supported
12539 void GLES2DecoderImpl::EmulateVertexArrayState() {
12540 // Setup the Vertex attribute state
12541 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
12542 RestoreStateForAttrib(vv, true);
12545 // Setup the element buffer
12546 Buffer* element_array_buffer =
12547 state_.vertex_attrib_manager->element_array_buffer();
12548 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
12549 element_array_buffer ? element_array_buffer->service_id() : 0);
12552 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
12553 const VertexAttribManager* vao =
12554 GetVertexAttribManager(client_id);
12555 return vao && vao->IsValid() && !vao->IsDeleted();
12558 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id) {
12559 GLuint service_id = 0;
12560 return path_manager()->GetPath(client_id, &service_id) &&
12561 glIsPathNV(service_id) == GL_TRUE;
12564 #if defined(OS_MACOSX)
12565 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
12566 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
12567 texture_id);
12568 if (it != texture_to_io_surface_map_.end()) {
12569 // Found a previous IOSurface bound to this texture; release it.
12570 IOSurfaceRef surface = it->second;
12571 CFRelease(surface);
12572 texture_to_io_surface_map_.erase(it);
12575 #endif
12577 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12578 GLenum target, GLsizei width, GLsizei height,
12579 GLuint io_surface_id, GLuint plane) {
12580 #if defined(OS_MACOSX)
12581 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
12582 LOCAL_SET_GL_ERROR(
12583 GL_INVALID_OPERATION,
12584 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12585 return;
12588 if (target != GL_TEXTURE_RECTANGLE_ARB) {
12589 // This might be supported in the future, and if we could require
12590 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12591 // could delete a lot of code. For now, perform strict validation so we
12592 // know what's going on.
12593 LOCAL_SET_GL_ERROR(
12594 GL_INVALID_OPERATION,
12595 "glTexImageIOSurface2DCHROMIUM",
12596 "requires TEXTURE_RECTANGLE_ARB target");
12597 return;
12600 // Default target might be conceptually valid, but disallow it to avoid
12601 // accidents.
12602 TextureRef* texture_ref =
12603 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12604 if (!texture_ref) {
12605 LOCAL_SET_GL_ERROR(
12606 GL_INVALID_OPERATION,
12607 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12608 return;
12611 // Look up the new IOSurface. Note that because of asynchrony
12612 // between processes this might fail; during live resizing the
12613 // plugin process might allocate and release an IOSurface before
12614 // this process gets a chance to look it up. Hold on to any old
12615 // IOSurface in this case.
12616 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
12617 if (!surface) {
12618 LOCAL_SET_GL_ERROR(
12619 GL_INVALID_OPERATION,
12620 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12621 return;
12624 // Release any IOSurface previously bound to this texture.
12625 ReleaseIOSurfaceForTexture(texture_ref->service_id());
12627 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12628 texture_to_io_surface_map_.insert(
12629 std::make_pair(texture_ref->service_id(), surface));
12631 CGLContextObj context =
12632 static_cast<CGLContextObj>(context_->GetHandle());
12634 CGLError err = CGLTexImageIOSurface2D(
12635 context,
12636 target,
12637 GL_RGBA,
12638 width,
12639 height,
12640 GL_BGRA,
12641 GL_UNSIGNED_INT_8_8_8_8_REV,
12642 surface,
12643 plane);
12645 if (err != kCGLNoError) {
12646 LOCAL_SET_GL_ERROR(
12647 GL_INVALID_OPERATION,
12648 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12649 return;
12652 texture_manager()->SetLevelInfo(
12653 texture_ref, target, 0, GL_RGBA, width, height, 1, 0, GL_BGRA,
12654 GL_UNSIGNED_INT_8_8_8_8_REV, gfx::Rect(width, height));
12656 #else
12657 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12658 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12659 #endif
12662 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
12663 switch (internalformat) {
12664 case GL_R8:
12665 case GL_R8_SNORM:
12666 case GL_R16F:
12667 case GL_R32F:
12668 return GL_RED;
12669 case GL_R8UI:
12670 case GL_R8I:
12671 case GL_R16UI:
12672 case GL_R16I:
12673 case GL_R32UI:
12674 case GL_R32I:
12675 return GL_RED_INTEGER;
12676 case GL_RG8:
12677 case GL_RG8_SNORM:
12678 case GL_RG16F:
12679 case GL_RG32F:
12680 return GL_RG;
12681 case GL_RG8UI:
12682 case GL_RG8I:
12683 case GL_RG16UI:
12684 case GL_RG16I:
12685 case GL_RG32UI:
12686 case GL_RG32I:
12687 return GL_RG_INTEGER;
12688 case GL_ATC_RGB_AMD:
12689 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
12690 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
12691 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
12692 case GL_ETC1_RGB8_OES:
12693 case GL_RGB8:
12694 case GL_R11F_G11F_B10F:
12695 case GL_RGB565:
12696 case GL_RGB8_SNORM:
12697 case GL_RGB9_E5:
12698 case GL_RGB16F:
12699 case GL_RGB32F:
12700 return GL_RGB;
12701 case GL_RGB8UI:
12702 case GL_RGB8I:
12703 case GL_RGB16UI:
12704 case GL_RGB16I:
12705 case GL_RGB32UI:
12706 case GL_RGB32I:
12707 return GL_RGB_INTEGER;
12708 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
12709 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
12710 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
12711 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
12712 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
12713 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
12714 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
12715 case GL_RGBA8:
12716 case GL_SRGB8_ALPHA8:
12717 case GL_RGBA8_SNORM:
12718 case GL_RGBA4:
12719 case GL_RGB5_A1:
12720 case GL_RGB10_A2:
12721 case GL_RGBA16F:
12722 case GL_RGBA32F:
12723 return GL_RGBA;
12724 case GL_RGBA8UI:
12725 case GL_RGBA8I:
12726 case GL_RGB10_A2UI:
12727 case GL_RGBA16UI:
12728 case GL_RGBA16I:
12729 case GL_RGBA32UI:
12730 case GL_RGBA32I:
12731 return GL_RGBA_INTEGER;
12732 case GL_DEPTH_COMPONENT16:
12733 case GL_DEPTH_COMPONENT24:
12734 case GL_DEPTH_COMPONENT32F:
12735 return GL_DEPTH_COMPONENT;
12736 case GL_DEPTH24_STENCIL8:
12737 case GL_DEPTH32F_STENCIL8:
12738 return GL_DEPTH_STENCIL;
12739 case GL_LUMINANCE8_ALPHA8_EXT:
12740 return GL_LUMINANCE_ALPHA;
12741 case GL_LUMINANCE8_EXT:
12742 return GL_LUMINANCE;
12743 case GL_ALPHA8_EXT:
12744 return GL_ALPHA;
12745 case GL_ALPHA32F_EXT:
12746 return GL_ALPHA;
12747 case GL_LUMINANCE32F_EXT:
12748 return GL_LUMINANCE;
12749 case GL_LUMINANCE_ALPHA32F_EXT:
12750 return GL_LUMINANCE_ALPHA;
12751 case GL_ALPHA16F_EXT:
12752 return GL_ALPHA;
12753 case GL_LUMINANCE16F_EXT:
12754 return GL_LUMINANCE;
12755 case GL_LUMINANCE_ALPHA16F_EXT:
12756 return GL_LUMINANCE_ALPHA;
12757 case GL_BGRA8_EXT:
12758 return GL_BGRA_EXT;
12759 default:
12760 return GL_NONE;
12764 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12765 const char* function_name,
12766 GLenum target,
12767 TextureRef* source_texture_ref,
12768 TextureRef* dest_texture_ref,
12769 GLenum dest_internal_format) {
12770 if (!source_texture_ref || !dest_texture_ref) {
12771 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12772 return false;
12775 if (GL_TEXTURE_2D != target) {
12776 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12777 "invalid texture target");
12778 return false;
12781 Texture* source_texture = source_texture_ref->texture();
12782 Texture* dest_texture = dest_texture_ref->texture();
12783 if (source_texture == dest_texture) {
12784 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12785 "source and destination textures are the same");
12786 return false;
12789 if (dest_texture->target() != GL_TEXTURE_2D ||
12790 (source_texture->target() != GL_TEXTURE_2D &&
12791 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12792 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12793 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12794 "invalid texture target binding");
12795 return false;
12798 GLenum source_type = 0;
12799 GLenum source_internal_format = 0;
12800 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12801 &source_internal_format);
12803 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12804 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12805 // renderable on some platforms.
12806 bool valid_dest_format = dest_internal_format == GL_RGB ||
12807 dest_internal_format == GL_RGBA ||
12808 dest_internal_format == GL_BGRA_EXT;
12809 bool valid_source_format =
12810 source_internal_format == GL_R8 || source_internal_format == GL_ALPHA ||
12811 source_internal_format == GL_RGB || source_internal_format == GL_RGBA ||
12812 source_internal_format == GL_LUMINANCE ||
12813 source_internal_format == GL_LUMINANCE_ALPHA ||
12814 source_internal_format == GL_BGRA_EXT ||
12815 source_internal_format == GL_RGB_YCBCR_422_CHROMIUM;
12816 if (!valid_source_format || !valid_dest_format) {
12817 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12818 "invalid internal format");
12819 return false;
12821 return true;
12824 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12825 const char* function_name,
12826 GLenum target,
12827 TextureRef* source_texture_ref,
12828 TextureRef* dest_texture_ref) {
12829 if (!source_texture_ref || !dest_texture_ref) {
12830 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12831 return false;
12834 if (GL_TEXTURE_2D != target) {
12835 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12836 "invalid texture target");
12837 return false;
12840 Texture* source_texture = source_texture_ref->texture();
12841 Texture* dest_texture = dest_texture_ref->texture();
12842 if (source_texture == dest_texture) {
12843 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12844 "source and destination textures are the same");
12845 return false;
12848 if (dest_texture->target() != GL_TEXTURE_2D ||
12849 (source_texture->target() != GL_TEXTURE_2D &&
12850 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12851 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12852 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12853 "invalid texture target binding");
12854 return false;
12857 GLenum source_type = 0;
12858 GLenum source_internal_format = 0;
12859 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12860 &source_internal_format);
12862 bool valid_format =
12863 source_internal_format == GL_ATC_RGB_AMD ||
12864 source_internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD ||
12865 source_internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
12866 source_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ||
12867 source_internal_format == GL_ETC1_RGB8_OES;
12869 if (!valid_format) {
12870 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12871 "invalid internal format");
12872 return false;
12875 return true;
12878 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12879 GLenum target,
12880 GLuint source_id,
12881 GLuint dest_id,
12882 GLenum internal_format,
12883 GLenum dest_type,
12884 GLboolean unpack_flip_y,
12885 GLboolean unpack_premultiply_alpha,
12886 GLboolean unpack_unmultiply_alpha) {
12887 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12889 TextureRef* source_texture_ref = GetTexture(source_id);
12890 TextureRef* dest_texture_ref = GetTexture(dest_id);
12891 Texture* source_texture = source_texture_ref->texture();
12892 Texture* dest_texture = dest_texture_ref->texture();
12893 int source_width = 0;
12894 int source_height = 0;
12895 gfx::GLImage* image =
12896 source_texture->GetLevelImage(source_texture->target(), 0);
12897 if (image) {
12898 gfx::Size size = image->GetSize();
12899 source_width = size.width();
12900 source_height = size.height();
12901 if (source_width <= 0 || source_height <= 0) {
12902 LOCAL_SET_GL_ERROR(
12903 GL_INVALID_VALUE,
12904 "glCopyTextureChromium", "invalid image size");
12905 return;
12907 } else {
12908 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12909 &source_width, &source_height, nullptr)) {
12910 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12911 "glCopyTextureChromium",
12912 "source texture has no level 0");
12913 return;
12916 // Check that this type of texture is allowed.
12917 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12918 source_width, source_height, 1)) {
12919 LOCAL_SET_GL_ERROR(
12920 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
12921 return;
12925 GLenum source_type = 0;
12926 GLenum source_internal_format = 0;
12927 source_texture->GetLevelType(
12928 source_texture->target(), 0, &source_type, &source_internal_format);
12930 if (dest_texture->IsImmutable()) {
12931 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
12932 "texture is immutable");
12933 return;
12936 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
12937 source_texture_ref, dest_texture_ref,
12938 internal_format)) {
12939 return;
12942 // Clear the source texture if necessary.
12943 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12944 source_texture->target(), 0)) {
12945 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
12946 "dimensions too big");
12947 return;
12950 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12951 // needed because it takes 10s of milliseconds to initialize.
12952 if (!copy_texture_CHROMIUM_.get()) {
12953 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12954 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12955 copy_texture_CHROMIUM_->Initialize(this);
12956 RestoreCurrentFramebufferBindings();
12957 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12958 return;
12961 GLenum dest_type_previous = dest_type;
12962 GLenum dest_internal_format = internal_format;
12963 int dest_width = 0;
12964 int dest_height = 0;
12965 bool dest_level_defined = dest_texture->GetLevelSize(
12966 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12968 if (dest_level_defined) {
12969 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
12970 &dest_internal_format);
12973 // Resize the destination texture to the dimensions of the source texture.
12974 if (!dest_level_defined || dest_width != source_width ||
12975 dest_height != source_height ||
12976 dest_internal_format != internal_format ||
12977 dest_type_previous != dest_type) {
12978 // Ensure that the glTexImage2D succeeds.
12979 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12980 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12981 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
12982 0, internal_format, dest_type, NULL);
12983 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12984 if (error != GL_NO_ERROR) {
12985 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12986 return;
12989 texture_manager()->SetLevelInfo(
12990 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
12991 source_height, 1, 0, internal_format, dest_type,
12992 gfx::Rect(source_width, source_height));
12993 } else {
12994 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12995 true);
12998 ScopedModifyPixels modify(dest_texture_ref);
13000 // Try using GLImage::CopyTexSubImage when possible.
13001 bool unpack_premultiply_alpha_change =
13002 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
13003 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
13004 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
13005 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
13006 gfx::Rect(0, 0, source_width, source_height))) {
13007 return;
13011 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
13013 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
13014 // before presenting.
13015 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
13016 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
13017 // instead of using kIdentityMatrix crbug.com/226218.
13018 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
13019 this, source_texture->target(), source_texture->service_id(),
13020 dest_texture->service_id(), source_width, source_height,
13021 unpack_flip_y == GL_TRUE,
13022 unpack_premultiply_alpha == GL_TRUE,
13023 unpack_unmultiply_alpha == GL_TRUE,
13024 kIdentityMatrix);
13025 } else {
13026 copy_texture_CHROMIUM_->DoCopyTexture(
13027 this, source_texture->target(), source_texture->service_id(),
13028 source_internal_format, dest_texture->service_id(), internal_format,
13029 source_width, source_height,
13030 unpack_flip_y == GL_TRUE,
13031 unpack_premultiply_alpha == GL_TRUE,
13032 unpack_unmultiply_alpha == GL_TRUE);
13035 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13038 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
13039 GLenum target,
13040 GLuint source_id,
13041 GLuint dest_id,
13042 GLint xoffset,
13043 GLint yoffset,
13044 GLint x,
13045 GLint y,
13046 GLsizei width,
13047 GLsizei height,
13048 GLboolean unpack_flip_y,
13049 GLboolean unpack_premultiply_alpha,
13050 GLboolean unpack_unmultiply_alpha) {
13051 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
13053 TextureRef* source_texture_ref = GetTexture(source_id);
13054 TextureRef* dest_texture_ref = GetTexture(dest_id);
13055 Texture* source_texture = source_texture_ref->texture();
13056 Texture* dest_texture = dest_texture_ref->texture();
13057 int source_width = 0;
13058 int source_height = 0;
13059 gfx::GLImage* image =
13060 source_texture->GetLevelImage(source_texture->target(), 0);
13061 if (image) {
13062 gfx::Size size = image->GetSize();
13063 source_width = size.width();
13064 source_height = size.height();
13065 if (source_width <= 0 || source_height <= 0) {
13066 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
13067 "invalid image size");
13068 return;
13070 } else {
13071 if (!source_texture->GetLevelSize(source_texture->target(), 0,
13072 &source_width, &source_height, nullptr)) {
13073 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
13074 "source texture has no level 0");
13075 return;
13078 // Check that this type of texture is allowed.
13079 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
13080 source_width, source_height, 1)) {
13081 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
13082 "source texture bad dimensions");
13083 return;
13087 GLenum source_type = 0;
13088 GLenum source_internal_format = 0;
13089 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
13090 &source_internal_format);
13091 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
13092 width, height, 1)) {
13093 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
13094 "source texture bad dimensions.");
13095 return;
13098 GLenum dest_type = 0;
13099 GLenum dest_internal_format = 0;
13100 bool dest_level_defined = dest_texture->GetLevelType(
13101 dest_texture->target(), 0, &dest_type, &dest_internal_format);
13102 if (!dest_level_defined) {
13103 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
13104 "destination texture is not defined");
13105 return;
13107 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
13108 yoffset, 0, width, height, 1)) {
13109 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
13110 "destination texture bad dimensions.");
13111 return;
13114 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
13115 source_texture_ref, dest_texture_ref,
13116 dest_internal_format)) {
13117 return;
13120 // Clear the source texture if necessary.
13121 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
13122 source_texture->target(), 0)) {
13123 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
13124 "source texture dimensions too big");
13125 return;
13128 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13129 // needed because it takes 10s of milliseconds to initialize.
13130 if (!copy_texture_CHROMIUM_.get()) {
13131 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
13132 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
13133 copy_texture_CHROMIUM_->Initialize(this);
13134 RestoreCurrentFramebufferBindings();
13135 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
13136 return;
13139 int dest_width = 0;
13140 int dest_height = 0;
13141 bool ok = dest_texture->GetLevelSize(
13142 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
13143 DCHECK(ok);
13144 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
13145 height != dest_height) {
13146 gfx::Rect cleared_rect;
13147 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
13148 gfx::Rect(xoffset, yoffset, width, height),
13149 &cleared_rect)) {
13150 DCHECK_GE(cleared_rect.size().GetArea(),
13151 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
13152 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
13153 cleared_rect);
13154 } else {
13155 // Otherwise clear part of texture level that is not already cleared.
13156 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
13157 0)) {
13158 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
13159 "destination texture dimensions too big");
13160 return;
13163 } else {
13164 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
13165 true);
13168 ScopedModifyPixels modify(dest_texture_ref);
13170 // Try using GLImage::CopyTexSubImage when possible.
13171 bool unpack_premultiply_alpha_change =
13172 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
13173 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
13174 ScopedTextureBinder binder(
13175 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
13176 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
13177 gfx::Rect(x, y, width, height))) {
13178 return;
13182 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
13184 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13185 // crbug.com/226218.
13186 copy_texture_CHROMIUM_->DoCopySubTexture(
13187 this, source_texture->target(), source_texture->service_id(),
13188 source_internal_format, dest_texture->service_id(), dest_internal_format,
13189 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
13190 source_width, source_height,
13191 unpack_flip_y == GL_TRUE,
13192 unpack_premultiply_alpha == GL_TRUE,
13193 unpack_unmultiply_alpha == GL_TRUE);
13195 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13198 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target,
13199 GLuint source_id,
13200 GLuint dest_id) {
13201 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
13203 TextureRef* source_texture_ref = GetTexture(source_id);
13204 TextureRef* dest_texture_ref = GetTexture(dest_id);
13205 Texture* source_texture = source_texture_ref->texture();
13206 Texture* dest_texture = dest_texture_ref->texture();
13207 int source_width = 0;
13208 int source_height = 0;
13209 gfx::GLImage* image =
13210 source_texture->GetLevelImage(source_texture->target(), 0);
13211 if (image) {
13212 gfx::Size size = image->GetSize();
13213 source_width = size.width();
13214 source_height = size.height();
13215 if (source_width <= 0 || source_height <= 0) {
13216 LOCAL_SET_GL_ERROR(
13217 GL_INVALID_VALUE,
13218 "glCompressedCopyTextureCHROMIUM", "invalid image size");
13219 return;
13221 } else {
13222 if (!source_texture->GetLevelSize(source_texture->target(), 0,
13223 &source_width, &source_height, nullptr)) {
13224 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
13225 "glCompressedCopyTextureCHROMIUM",
13226 "source texture has no level 0");
13227 return;
13230 // Check that this type of texture is allowed.
13231 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
13232 source_width, source_height, 1)) {
13233 LOCAL_SET_GL_ERROR(
13234 GL_INVALID_VALUE, "glCompressedCopyTextureCHROMIUM",
13235 "Bad dimensions");
13236 return;
13240 GLenum source_type = 0;
13241 GLenum source_internal_format = 0;
13242 source_texture->GetLevelType(
13243 source_texture->target(), 0, &source_type, &source_internal_format);
13245 if (dest_texture->IsImmutable()) {
13246 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13247 "glCompressedCopyTextureCHROMIUM",
13248 "texture is immutable");
13249 return;
13252 if (!ValidateCompressedCopyTextureCHROMIUM(
13253 "glCompressedCopyTextureCHROMIUM",
13254 target,
13255 source_texture_ref, dest_texture_ref)) {
13256 return;
13259 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13260 // needed because it takes 10s of milliseconds to initialize.
13261 if (!copy_texture_CHROMIUM_.get()) {
13262 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
13263 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
13264 copy_texture_CHROMIUM_->Initialize(this);
13265 RestoreCurrentFramebufferBindings();
13266 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
13267 return;
13270 // Clear the source texture if necessary.
13271 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
13272 source_texture->target(), 0)) {
13273 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopyTextureCHROMIUM",
13274 "dimensions too big");
13275 return;
13278 ScopedTextureBinder binder(
13279 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
13281 ScopedModifyPixels modify(dest_texture_ref);
13283 // Try using GLImage::CopyTexImage when possible.
13284 if (image) {
13285 GLenum dest_type = 0;
13286 GLenum dest_internal_format = 0;
13287 int dest_width = 0;
13288 int dest_height = 0;
13289 bool dest_level_defined = dest_texture->GetLevelSize(
13290 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
13292 if (dest_level_defined) {
13293 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
13294 &dest_internal_format);
13297 // Resize the destination texture to the dimensions of the source texture.
13298 if (!dest_level_defined || dest_width != source_width ||
13299 dest_height != source_height ||
13300 dest_internal_format != source_internal_format) {
13301 GLsizei source_size = 0;
13303 bool did_get_size = GetCompressedTexSizeInBytes(
13304 "glCompressedCopyTextureCHROMIUM", source_width, source_height,
13305 1, source_internal_format, &source_size);
13306 DCHECK(did_get_size);
13308 // Ensure that the glCompressedTexImage2D succeeds.
13309 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13310 glCompressedTexImage2D(GL_TEXTURE_2D, 0, source_internal_format,
13311 source_width, source_height, 0, source_size,
13312 NULL);
13313 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
13314 if (error != GL_NO_ERROR) {
13315 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
13316 return;
13319 texture_manager()->SetLevelInfo(
13320 dest_texture_ref, GL_TEXTURE_2D, 0, source_internal_format,
13321 source_width, source_height, 1, 0, source_internal_format,
13322 source_type, gfx::Rect(source_width, source_height));
13323 } else {
13324 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
13325 true);
13328 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
13329 gfx::Rect(0, 0, source_width, source_height))) {
13330 return;
13334 TRACE_EVENT0(
13335 "gpu",
13336 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
13338 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
13340 // As a fallback, copy into a non-compressed GL_RGBA texture.
13341 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13342 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height,
13343 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
13344 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
13345 if (error != GL_NO_ERROR) {
13346 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
13347 return;
13350 texture_manager()->SetLevelInfo(
13351 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, source_width,
13352 source_height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13353 gfx::Rect(source_width, source_height));
13355 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
13356 // before presenting.
13357 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
13358 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
13359 // instead of using kIdentityMatrix crbug.com/226218.
13360 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
13361 this, source_texture->target(), source_texture->service_id(),
13362 dest_texture->service_id(), source_width, source_height,
13363 false, false, false, kIdentityMatrix);
13364 } else {
13365 copy_texture_CHROMIUM_->DoCopyTexture(
13366 this, source_texture->target(), source_texture->service_id(),
13367 source_internal_format, dest_texture->service_id(), GL_RGBA,
13368 source_width, source_height, false, false, false);
13371 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13374 void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target,
13375 GLuint source_id,
13376 GLuint dest_id,
13377 GLint xoffset,
13378 GLint yoffset,
13379 GLint x,
13380 GLint y,
13381 GLsizei width,
13382 GLsizei height) {
13383 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM");
13385 TextureRef* source_texture_ref = GetTexture(source_id);
13386 TextureRef* dest_texture_ref = GetTexture(dest_id);
13387 Texture* source_texture = source_texture_ref->texture();
13388 Texture* dest_texture = dest_texture_ref->texture();
13389 int source_width = 0;
13390 int source_height = 0;
13391 gfx::GLImage* image =
13392 source_texture->GetLevelImage(source_texture->target(), 0);
13393 if (image) {
13394 gfx::Size size = image->GetSize();
13395 source_width = size.width();
13396 source_height = size.height();
13397 if (source_width <= 0 || source_height <= 0) {
13398 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
13399 "invalid image size");
13400 return;
13402 } else {
13403 if (!source_texture->GetLevelSize(source_texture->target(), 0,
13404 &source_width, &source_height, nullptr)) {
13405 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
13406 "source texture has no level 0");
13407 return;
13410 // Check that this type of texture is allowed.
13411 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
13412 source_width, source_height, 1)) {
13413 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
13414 "source texture bad dimensions");
13415 return;
13419 GLenum source_type = 0;
13420 GLenum source_internal_format = 0;
13421 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
13422 &source_internal_format);
13423 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
13424 width, height, 1)) {
13425 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
13426 "source texture bad dimensions.");
13427 return;
13430 GLenum dest_type = 0;
13431 GLenum dest_internal_format = 0;
13432 bool dest_level_defined = dest_texture->GetLevelType(
13433 dest_texture->target(), 0, &dest_type, &dest_internal_format);
13434 if (!dest_level_defined) {
13435 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13436 "glCompressedCopySubTextureCHROMIUM",
13437 "destination texture is not defined");
13438 return;
13440 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
13441 yoffset, 0, width, height, 1)) {
13442 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
13443 "destination texture bad dimensions.");
13444 return;
13447 if (!ValidateCompressedCopyTextureCHROMIUM(
13448 "glCompressedCopySubTextureCHROMIUM", target, source_texture_ref,
13449 dest_texture_ref)) {
13450 return;
13453 if (!ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
13454 source_texture->target(), 0, x, y, 0,
13455 width, height, 1,
13456 source_internal_format,
13457 source_texture) ||
13458 !ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
13459 dest_texture->target(), 0,
13460 xoffset, yoffset, 0, width, height, 1,
13461 dest_internal_format,
13462 dest_texture)) {
13463 return;
13466 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13467 // needed because it takes 10s of milliseconds to initialize.
13468 if (!copy_texture_CHROMIUM_.get()) {
13469 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopySubTextureCHROMIUM");
13470 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
13471 copy_texture_CHROMIUM_->Initialize(this);
13472 RestoreCurrentFramebufferBindings();
13473 if (LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM") !=
13474 GL_NO_ERROR) {
13475 return;
13479 // Clear the source texture if necessary.
13480 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
13481 source_texture->target(), 0)) {
13482 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopySubTextureCHROMIUM",
13483 "source texture dimensions too big");
13484 return;
13487 int dest_width = 0;
13488 int dest_height = 0;
13489 bool ok = dest_texture->GetLevelSize(
13490 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
13491 DCHECK(ok);
13492 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
13493 height != dest_height) {
13494 gfx::Rect cleared_rect;
13495 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
13496 gfx::Rect(xoffset, yoffset, width, height),
13497 &cleared_rect)) {
13498 DCHECK_GE(cleared_rect.size().GetArea(),
13499 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
13500 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
13501 cleared_rect);
13502 } else {
13503 // Otherwise clear part of texture level that is not already cleared.
13504 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
13505 0)) {
13506 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY,
13507 "glCompressedCopySubTextureCHROMIUM",
13508 "destination texture dimensions too big");
13509 return;
13512 } else {
13513 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
13514 true);
13517 ScopedTextureBinder binder(
13518 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
13520 ScopedModifyPixels modify(dest_texture_ref);
13522 // Try using GLImage::CopyTexSubImage when possible.
13523 if (image) {
13524 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
13525 gfx::Rect(x, y, width, height))) {
13526 return;
13530 TRACE_EVENT0(
13531 "gpu",
13532 "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback");
13534 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
13536 // As a fallback, copy into a non-compressed GL_RGBA texture.
13537 if (dest_internal_format != GL_RGBA) {
13538 // To preserve the contents of the original destination texture we must
13539 // first copy the original destination texture to a temporary storage, then
13540 // copy it back to the original destination texture.
13541 GLuint tmp_service_id;
13542 glGenTextures(1, &tmp_service_id);
13543 DCHECK_NE(0u, tmp_service_id);
13545 glBindTexture(GL_TEXTURE_2D, tmp_service_id);
13547 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13548 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA,
13549 GL_UNSIGNED_BYTE, NULL);
13550 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13551 if (error != GL_NO_ERROR)
13552 return;
13554 copy_texture_CHROMIUM_->DoCopyTexture(
13555 this, dest_texture->target(), dest_texture->service_id(),
13556 dest_internal_format, tmp_service_id, GL_RGBA,
13557 dest_width, dest_height, false, false, false);
13559 // Redefine destination texture to use RGBA.
13560 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
13561 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13562 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA,
13563 GL_UNSIGNED_BYTE, NULL);
13564 error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13565 if (error != GL_NO_ERROR)
13566 return;
13568 texture_manager()->SetLevelInfo(
13569 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height,
13570 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(dest_width, dest_height));
13572 copy_texture_CHROMIUM_->DoCopyTexture(
13573 this, GL_TEXTURE_2D, tmp_service_id, GL_RGBA,
13574 dest_texture->service_id(), GL_RGBA,
13575 dest_width, dest_height, false, false, false);
13577 glDeleteTextures(1, &tmp_service_id);
13580 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13581 // crbug.com/226218.
13582 copy_texture_CHROMIUM_->DoCopySubTexture(
13583 this, source_texture->target(), source_texture->service_id(),
13584 source_internal_format, dest_texture->service_id(), GL_RGBA,
13585 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
13586 source_width, source_height, false, false, false);
13588 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13591 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
13592 switch (internalformat) {
13593 case GL_R8:
13594 return GL_UNSIGNED_BYTE;
13595 case GL_R8_SNORM:
13596 return GL_BYTE;
13597 case GL_R16F:
13598 return GL_HALF_FLOAT;
13599 case GL_R32F:
13600 return GL_FLOAT;
13601 case GL_R8UI:
13602 return GL_UNSIGNED_BYTE;
13603 case GL_R8I:
13604 return GL_BYTE;
13605 case GL_R16UI:
13606 return GL_UNSIGNED_SHORT;
13607 case GL_R16I:
13608 return GL_SHORT;
13609 case GL_R32UI:
13610 return GL_UNSIGNED_INT;
13611 case GL_R32I:
13612 return GL_INT;
13613 case GL_RG8:
13614 return GL_UNSIGNED_BYTE;
13615 case GL_RG8_SNORM:
13616 return GL_BYTE;
13617 case GL_RG16F:
13618 return GL_HALF_FLOAT;
13619 case GL_RG32F:
13620 return GL_FLOAT;
13621 case GL_RG8UI:
13622 return GL_UNSIGNED_BYTE;
13623 case GL_RG8I:
13624 return GL_BYTE;
13625 case GL_RG16UI:
13626 return GL_UNSIGNED_SHORT;
13627 case GL_RG16I:
13628 return GL_SHORT;
13629 case GL_RG32UI:
13630 return GL_UNSIGNED_INT;
13631 case GL_RG32I:
13632 return GL_INT;
13633 case GL_RGB8:
13634 case GL_SRGB8:
13635 return GL_UNSIGNED_BYTE;
13636 case GL_R11F_G11F_B10F:
13637 return GL_UNSIGNED_INT_10F_11F_11F_REV;
13638 case GL_RGB565:
13639 return GL_UNSIGNED_SHORT_5_6_5;
13640 case GL_RGB8_SNORM:
13641 return GL_BYTE;
13642 case GL_RGB9_E5:
13643 return GL_UNSIGNED_INT_5_9_9_9_REV;
13644 case GL_RGB16F:
13645 return GL_HALF_FLOAT;
13646 case GL_RGB32F:
13647 return GL_FLOAT;
13648 case GL_RGB8UI:
13649 return GL_UNSIGNED_BYTE;
13650 case GL_RGB8I:
13651 return GL_BYTE;
13652 case GL_RGB16UI:
13653 return GL_UNSIGNED_SHORT;
13654 case GL_RGB16I:
13655 return GL_SHORT;
13656 case GL_RGB32UI:
13657 return GL_UNSIGNED_INT;
13658 case GL_RGB32I:
13659 return GL_INT;
13660 case GL_RGBA8:
13661 return GL_UNSIGNED_BYTE;
13662 case GL_SRGB8_ALPHA8:
13663 return GL_UNSIGNED_BYTE;
13664 case GL_RGBA8_SNORM:
13665 return GL_BYTE;
13666 case GL_RGBA4:
13667 return GL_UNSIGNED_SHORT_4_4_4_4;
13668 case GL_RGB10_A2:
13669 return GL_UNSIGNED_INT_2_10_10_10_REV;
13670 case GL_RGB5_A1:
13671 return GL_UNSIGNED_SHORT_5_5_5_1;
13672 case GL_RGBA16F:
13673 return GL_HALF_FLOAT;
13674 case GL_RGBA32F:
13675 return GL_FLOAT;
13676 case GL_RGBA8UI:
13677 return GL_UNSIGNED_BYTE;
13678 case GL_RGBA8I:
13679 return GL_BYTE;
13680 case GL_RGB10_A2UI:
13681 return GL_UNSIGNED_INT_2_10_10_10_REV;
13682 case GL_RGBA16UI:
13683 return GL_UNSIGNED_SHORT;
13684 case GL_RGBA16I:
13685 return GL_SHORT;
13686 case GL_RGBA32I:
13687 return GL_INT;
13688 case GL_RGBA32UI:
13689 return GL_UNSIGNED_INT;
13690 case GL_DEPTH_COMPONENT16:
13691 return GL_UNSIGNED_SHORT;
13692 case GL_DEPTH_COMPONENT24:
13693 return GL_UNSIGNED_INT;
13694 case GL_DEPTH_COMPONENT32F:
13695 return GL_FLOAT;
13696 case GL_DEPTH24_STENCIL8:
13697 return GL_UNSIGNED_INT_24_8;
13698 case GL_DEPTH32F_STENCIL8:
13699 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
13700 case GL_LUMINANCE8_ALPHA8_EXT:
13701 return GL_UNSIGNED_BYTE;
13702 case GL_LUMINANCE8_EXT:
13703 return GL_UNSIGNED_BYTE;
13704 case GL_ALPHA8_EXT:
13705 return GL_UNSIGNED_BYTE;
13706 case GL_ALPHA32F_EXT:
13707 return GL_FLOAT;
13708 case GL_LUMINANCE32F_EXT:
13709 return GL_FLOAT;
13710 case GL_LUMINANCE_ALPHA32F_EXT:
13711 return GL_FLOAT;
13712 case GL_ALPHA16F_EXT:
13713 return GL_HALF_FLOAT_OES;
13714 case GL_LUMINANCE16F_EXT:
13715 return GL_HALF_FLOAT_OES;
13716 case GL_LUMINANCE_ALPHA16F_EXT:
13717 return GL_HALF_FLOAT_OES;
13718 case GL_BGRA8_EXT:
13719 return GL_UNSIGNED_BYTE;
13720 default:
13721 return GL_NONE;
13725 void GLES2DecoderImpl::DoTexStorage2DEXT(
13726 GLenum target,
13727 GLint levels,
13728 GLenum internal_format,
13729 GLsizei width,
13730 GLsizei height) {
13731 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
13732 "width", width, "height", height);
13733 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
13734 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
13735 LOCAL_SET_GL_ERROR(
13736 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
13737 return;
13739 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13740 &state_, target);
13741 if (!texture_ref) {
13742 LOCAL_SET_GL_ERROR(
13743 GL_INVALID_OPERATION,
13744 "glTexStorage2DEXT", "unknown texture for target");
13745 return;
13747 Texture* texture = texture_ref->texture();
13748 if (texture->IsAttachedToFramebuffer()) {
13749 framebuffer_state_.clear_state_dirty = true;
13751 if (texture->IsImmutable()) {
13752 LOCAL_SET_GL_ERROR(
13753 GL_INVALID_OPERATION,
13754 "glTexStorage2DEXT", "texture is immutable");
13755 return;
13758 GLenum format = ExtractFormatFromStorageFormat(internal_format);
13759 GLenum type = ExtractTypeFromStorageFormat(internal_format);
13762 GLsizei level_width = width;
13763 GLsizei level_height = height;
13764 uint32 estimated_size = 0;
13765 for (int ii = 0; ii < levels; ++ii) {
13766 uint32 level_size = 0;
13767 if (!GLES2Util::ComputeImageDataSizes(
13768 level_width, level_height, 1, format, type, state_.unpack_alignment,
13769 &estimated_size, NULL, NULL) ||
13770 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
13771 LOCAL_SET_GL_ERROR(
13772 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
13773 return;
13775 level_width = std::max(1, level_width >> 1);
13776 level_height = std::max(1, level_height >> 1);
13778 if (!EnsureGPUMemoryAvailable(estimated_size)) {
13779 LOCAL_SET_GL_ERROR(
13780 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
13781 return;
13785 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13786 glTexStorage2DEXT(target, levels, internal_format, width, height);
13787 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13788 if (error == GL_NO_ERROR) {
13789 GLsizei level_width = width;
13790 GLsizei level_height = height;
13792 GLenum cur_format = feature_info_->IsES3Enabled() ?
13793 internal_format : format;
13794 for (int ii = 0; ii < levels; ++ii) {
13795 if (target == GL_TEXTURE_CUBE_MAP) {
13796 for (int jj = 0; jj < 6; ++jj) {
13797 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj;
13798 texture_manager()->SetLevelInfo(texture_ref, face, ii, cur_format,
13799 level_width, level_height, 1, 0,
13800 format, type, gfx::Rect());
13802 } else {
13803 texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format,
13804 level_width, level_height, 1, 0,
13805 format, type, gfx::Rect());
13807 level_width = std::max(1, level_width >> 1);
13808 level_height = std::max(1, level_height >> 1);
13810 texture->SetImmutable(true);
13814 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13815 uint32 immediate_data_size,
13816 const void* cmd_data) {
13817 return error::kUnknownCommand;
13820 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
13821 const GLbyte* data) {
13822 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13823 "context", logger_.GetLogPrefix(),
13824 "mailbox[0]", static_cast<unsigned char>(data[0]));
13826 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13827 &state_, target);
13828 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
13831 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
13832 GLenum target, const GLbyte* data) {
13833 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13834 "context", logger_.GetLogPrefix(),
13835 "mailbox[0]", static_cast<unsigned char>(data[0]));
13837 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
13838 target, data);
13841 void GLES2DecoderImpl::ProduceTextureRef(const char* func_name,
13842 TextureRef* texture_ref,
13843 GLenum target,
13844 const GLbyte* data) {
13845 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13846 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
13847 "mailbox that was not generated by "
13848 "GenMailboxCHROMIUM.";
13850 if (!texture_ref) {
13851 LOCAL_SET_GL_ERROR(
13852 GL_INVALID_OPERATION, func_name, "unknown texture for target");
13853 return;
13856 Texture* produced = texture_manager()->Produce(texture_ref);
13857 if (!produced) {
13858 LOCAL_SET_GL_ERROR(
13859 GL_INVALID_OPERATION, func_name, "invalid texture");
13860 return;
13863 if (produced->target() != target) {
13864 LOCAL_SET_GL_ERROR(
13865 GL_INVALID_OPERATION, func_name, "invalid target");
13866 return;
13869 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
13872 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
13873 const GLbyte* data) {
13874 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13875 "context", logger_.GetLogPrefix(),
13876 "mailbox[0]", static_cast<unsigned char>(data[0]));
13877 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13878 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13879 "mailbox that was not generated by "
13880 "GenMailboxCHROMIUM.";
13882 scoped_refptr<TextureRef> texture_ref =
13883 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13884 if (!texture_ref.get()) {
13885 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13886 "glConsumeTextureCHROMIUM",
13887 "unknown texture for target");
13888 return;
13890 GLuint client_id = texture_ref->client_id();
13891 if (!client_id) {
13892 LOCAL_SET_GL_ERROR(
13893 GL_INVALID_OPERATION,
13894 "glConsumeTextureCHROMIUM", "unknown texture for target");
13895 return;
13897 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13898 if (!texture) {
13899 LOCAL_SET_GL_ERROR(
13900 GL_INVALID_OPERATION,
13901 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13902 return;
13904 if (texture->target() != target) {
13905 LOCAL_SET_GL_ERROR(
13906 GL_INVALID_OPERATION,
13907 "glConsumeTextureCHROMIUM", "invalid target");
13908 return;
13911 DeleteTexturesHelper(1, &client_id);
13912 texture_ref = texture_manager()->Consume(client_id, texture);
13913 glBindTexture(target, texture_ref->service_id());
13915 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
13916 unit.bind_target = target;
13917 switch (target) {
13918 case GL_TEXTURE_2D:
13919 unit.bound_texture_2d = texture_ref;
13920 break;
13921 case GL_TEXTURE_CUBE_MAP:
13922 unit.bound_texture_cube_map = texture_ref;
13923 break;
13924 case GL_TEXTURE_EXTERNAL_OES:
13925 unit.bound_texture_external_oes = texture_ref;
13926 break;
13927 case GL_TEXTURE_RECTANGLE_ARB:
13928 unit.bound_texture_rectangle_arb = texture_ref;
13929 break;
13930 default:
13931 NOTREACHED(); // Validation should prevent us getting here.
13932 break;
13936 void GLES2DecoderImpl::EnsureTextureForClientId(
13937 GLenum target,
13938 GLuint client_id) {
13939 TextureRef* texture_ref = GetTexture(client_id);
13940 if (!texture_ref) {
13941 GLuint service_id;
13942 glGenTextures(1, &service_id);
13943 DCHECK_NE(0u, service_id);
13944 texture_ref = CreateTexture(client_id, service_id);
13945 texture_manager()->SetTarget(texture_ref, target);
13946 glBindTexture(target, service_id);
13947 RestoreCurrentTextureBindings(&state_, target);
13951 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13952 // provided is associated with a service_id/TextureRef for consistency, even if
13953 // the resulting texture is incomplete.
13954 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13955 uint32_t immediate_data_size,
13956 const void* cmd_data) {
13957 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
13958 *static_cast<
13959 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
13960 cmd_data);
13961 GLenum target = static_cast<GLenum>(c.target);
13962 uint32_t data_size;
13963 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
13964 return error::kOutOfBounds;
13966 if (data_size > immediate_data_size) {
13967 return error::kOutOfBounds;
13969 const GLbyte* mailbox =
13970 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
13971 if (!validators_->texture_bind_target.IsValid(target)) {
13972 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13973 "glCreateAndConsumeTextureCHROMIUM", target, "target");
13974 return error::kNoError;
13976 if (mailbox == NULL) {
13977 return error::kOutOfBounds;
13979 uint32_t client_id = c.client_id;
13980 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
13981 return error::kNoError;
13984 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
13985 const GLbyte* data, GLuint client_id) {
13986 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13987 "context", logger_.GetLogPrefix(),
13988 "mailbox[0]", static_cast<unsigned char>(data[0]));
13989 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13990 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13991 "passed a mailbox that was not "
13992 "generated by GenMailboxCHROMIUM.";
13994 TextureRef* texture_ref = GetTexture(client_id);
13995 if (texture_ref) {
13996 // No need to call EnsureTextureForClientId here, the client_id already has
13997 // an associated texture.
13998 LOCAL_SET_GL_ERROR(
13999 GL_INVALID_OPERATION,
14000 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
14001 return;
14003 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
14004 if (!texture) {
14005 EnsureTextureForClientId(target, client_id);
14006 LOCAL_SET_GL_ERROR(
14007 GL_INVALID_OPERATION,
14008 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
14009 return;
14012 if (texture->target() != target) {
14013 EnsureTextureForClientId(target, client_id);
14014 LOCAL_SET_GL_ERROR(
14015 GL_INVALID_OPERATION,
14016 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
14017 return;
14020 texture_ref = texture_manager()->Consume(client_id, texture);
14023 void GLES2DecoderImpl::DoApplyScreenSpaceAntialiasingCHROMIUM() {
14024 // Apply CMAA(Conservative Morphological Anti-Aliasing) algorithm to the
14025 // color attachments of currently bound draw framebuffer.
14026 // Reference GL_INTEL_framebuffer_CMAA for details.
14027 glApplyFramebufferAttachmentCMAAINTEL();
14030 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
14031 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
14032 return valuebuffer && valuebuffer->IsValid();
14035 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
14036 GLuint client_id) {
14037 Valuebuffer* valuebuffer = NULL;
14038 if (client_id != 0) {
14039 valuebuffer = GetValuebuffer(client_id);
14040 if (!valuebuffer) {
14041 if (!group_->bind_generates_resource()) {
14042 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
14043 "id not generated by glBindValuebufferCHROMIUM");
14044 return;
14047 // It's a new id so make a valuebuffer for it.
14048 CreateValuebuffer(client_id);
14049 valuebuffer = GetValuebuffer(client_id);
14051 valuebuffer->MarkAsValid();
14053 state_.bound_valuebuffer = valuebuffer;
14056 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
14057 GLenum subscription) {
14058 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
14059 return;
14061 state_.bound_valuebuffer.get()->AddSubscription(subscription);
14064 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
14065 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
14066 return;
14068 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
14071 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
14072 GLenum target,
14073 GLenum subscription) {
14074 if (!CheckCurrentValuebufferForSubscription(
14075 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
14076 return;
14078 if (!CheckSubscriptionTarget(location, subscription,
14079 "glPopulateSubscribedValuesCHROMIUM")) {
14080 return;
14082 const ValueState* state =
14083 state_.bound_valuebuffer.get()->GetState(subscription);
14084 if (state) {
14085 switch (subscription) {
14086 case GL_MOUSE_POSITION_CHROMIUM:
14087 DoUniform2iv(location, 1, state->int_value);
14088 break;
14089 default:
14090 NOTREACHED() << "Unhandled uniform subscription target "
14091 << subscription;
14092 break;
14097 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
14098 GLsizei length, const GLchar* marker) {
14099 if (!marker) {
14100 marker = "";
14102 debug_marker_manager_.SetMarker(
14103 length ? std::string(marker, length) : std::string(marker));
14106 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
14107 GLsizei /*length*/, const GLchar* /*marker*/) {
14110 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
14113 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
14114 GLenum target, GLint image_id) {
14115 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
14117 if (target == GL_TEXTURE_CUBE_MAP) {
14118 LOCAL_SET_GL_ERROR(
14119 GL_INVALID_ENUM,
14120 "glBindTexImage2DCHROMIUM", "invalid target");
14121 return;
14124 // Default target might be conceptually valid, but disallow it to avoid
14125 // accidents.
14126 TextureRef* texture_ref =
14127 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
14128 if (!texture_ref) {
14129 LOCAL_SET_GL_ERROR(
14130 GL_INVALID_OPERATION,
14131 "glBindTexImage2DCHROMIUM", "no texture bound");
14132 return;
14135 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
14136 if (!gl_image) {
14137 LOCAL_SET_GL_ERROR(
14138 GL_INVALID_OPERATION,
14139 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
14140 return;
14144 ScopedGLErrorSuppressor suppressor(
14145 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
14146 if (!gl_image->BindTexImage(target)) {
14147 LOCAL_SET_GL_ERROR(
14148 GL_INVALID_OPERATION,
14149 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
14150 return;
14154 gfx::Size size = gl_image->GetSize();
14155 texture_manager()->SetLevelInfo(
14156 texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(),
14157 size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE,
14158 gfx::Rect(size));
14159 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
14162 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
14163 GLenum target, GLint image_id) {
14164 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
14166 // Default target might be conceptually valid, but disallow it to avoid
14167 // accidents.
14168 TextureRef* texture_ref =
14169 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
14170 if (!texture_ref) {
14171 LOCAL_SET_GL_ERROR(
14172 GL_INVALID_OPERATION,
14173 "glReleaseTexImage2DCHROMIUM", "no texture bound");
14174 return;
14177 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
14178 if (!gl_image) {
14179 LOCAL_SET_GL_ERROR(
14180 GL_INVALID_OPERATION,
14181 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
14182 return;
14185 // Do nothing when image is not currently bound.
14186 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
14187 return;
14190 ScopedGLErrorSuppressor suppressor(
14191 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
14192 gl_image->ReleaseTexImage(target);
14195 texture_manager()->SetLevelInfo(
14196 texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0,
14197 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect());
14200 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
14201 uint32 immediate_data_size,
14202 const void* cmd_data) {
14203 const gles2::cmds::TraceBeginCHROMIUM& c =
14204 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
14205 Bucket* category_bucket = GetBucket(c.category_bucket_id);
14206 Bucket* name_bucket = GetBucket(c.name_bucket_id);
14207 if (!category_bucket || category_bucket->size() == 0 ||
14208 !name_bucket || name_bucket->size() == 0) {
14209 return error::kInvalidArguments;
14212 std::string category_name;
14213 std::string trace_name;
14214 if (!category_bucket->GetAsString(&category_name) ||
14215 !name_bucket->GetAsString(&trace_name)) {
14216 return error::kInvalidArguments;
14219 debug_marker_manager_.PushGroup(trace_name);
14220 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
14221 LOCAL_SET_GL_ERROR(
14222 GL_INVALID_OPERATION,
14223 "glTraceBeginCHROMIUM", "unable to create begin trace");
14224 return error::kNoError;
14226 return error::kNoError;
14229 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
14230 debug_marker_manager_.PopGroup();
14231 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
14232 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
14233 "glTraceEndCHROMIUM", "no trace begin found");
14234 return;
14238 void GLES2DecoderImpl::DoDrawBuffersEXT(
14239 GLsizei count, const GLenum* bufs) {
14240 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
14241 LOCAL_SET_GL_ERROR(
14242 GL_INVALID_VALUE,
14243 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
14244 return;
14247 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
14248 if (framebuffer) {
14249 for (GLsizei i = 0; i < count; ++i) {
14250 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
14251 bufs[i] != GL_NONE) {
14252 LOCAL_SET_GL_ERROR(
14253 GL_INVALID_OPERATION,
14254 "glDrawBuffersEXT",
14255 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
14256 return;
14259 glDrawBuffersARB(count, bufs);
14260 framebuffer->SetDrawBuffers(count, bufs);
14261 } else { // backbuffer
14262 if (count > 1 ||
14263 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
14264 LOCAL_SET_GL_ERROR(
14265 GL_INVALID_OPERATION,
14266 "glDrawBuffersEXT",
14267 "more than one buffer or bufs not GL_NONE or GL_BACK");
14268 return;
14270 GLenum mapped_buf = bufs[0];
14271 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
14272 bufs[0] == GL_BACK) {
14273 mapped_buf = GL_COLOR_ATTACHMENT0;
14275 glDrawBuffersARB(count, &mapped_buf);
14276 back_buffer_draw_buffer_ = bufs[0];
14280 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
14281 MarkContextLost(GetContextLostReasonFromResetStatus(current));
14282 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
14283 reset_by_robustness_extension_ = true;
14286 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
14287 // On Adreno Android devices we need to use a workaround to force caches to
14288 // clear.
14289 if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) {
14290 context_->ReleaseCurrent(nullptr);
14291 context_->MakeCurrent(surface_.get());
14295 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
14296 const GLfloat* matrix) {
14297 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
14298 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
14299 if (!features().chromium_path_rendering) {
14300 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
14301 "glMatrixLoadfCHROMIUM",
14302 "function not available");
14303 return;
14306 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
14307 ? state_.projection_matrix
14308 : state_.modelview_matrix;
14309 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
14310 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
14311 // since the values of the _NV and _CHROMIUM tokens match.
14312 glMatrixLoadfEXT(matrix_mode, matrix);
14315 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
14316 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
14317 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
14319 if (!features().chromium_path_rendering) {
14320 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
14321 "glMatrixLoadIdentityCHROMIUM",
14322 "function not available");
14323 return;
14326 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
14327 ? state_.projection_matrix
14328 : state_.modelview_matrix;
14329 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
14330 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
14331 // since the values of the _NV and _CHROMIUM tokens match.
14332 glMatrixLoadIdentityEXT(matrix_mode);
14335 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
14336 uint32_t immediate_data_size, const void* cmd_data) {
14337 if (!unsafe_es3_apis_enabled())
14338 return error::kUnknownCommand;
14339 const gles2::cmds::UniformBlockBinding& c =
14340 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
14341 GLuint client_id = c.program;
14342 GLuint index = static_cast<GLuint>(c.index);
14343 GLuint binding = static_cast<GLuint>(c.binding);
14344 Program* program = GetProgramInfoNotShader(
14345 client_id, "glUniformBlockBinding");
14346 if (!program) {
14347 return error::kNoError;
14349 GLuint service_id = program->service_id();
14350 glUniformBlockBinding(service_id, index, binding);
14351 return error::kNoError;
14354 error::Error GLES2DecoderImpl::HandleClientWaitSync(
14355 uint32_t immediate_data_size, const void* cmd_data) {
14356 if (!unsafe_es3_apis_enabled())
14357 return error::kUnknownCommand;
14358 const gles2::cmds::ClientWaitSync& c =
14359 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
14360 GLuint sync = static_cast<GLuint>(c.sync);
14361 GLbitfield flags = static_cast<GLbitfield>(c.flags);
14362 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
14363 typedef cmds::ClientWaitSync::Result Result;
14364 Result* result_dst = GetSharedMemoryAs<Result*>(
14365 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
14366 if (!result_dst) {
14367 return error::kOutOfBounds;
14369 if (*result_dst != GL_WAIT_FAILED) {
14370 return error::kInvalidArguments;
14372 GLsync service_sync = 0;
14373 if (!group_->GetSyncServiceId(sync, &service_sync)) {
14374 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
14375 return error::kNoError;
14377 *result_dst = glClientWaitSync(service_sync, flags, timeout);
14378 return error::kNoError;
14381 error::Error GLES2DecoderImpl::HandleWaitSync(
14382 uint32_t immediate_data_size, const void* cmd_data) {
14383 if (!unsafe_es3_apis_enabled())
14384 return error::kUnknownCommand;
14385 const gles2::cmds::WaitSync& c =
14386 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
14387 GLuint sync = static_cast<GLuint>(c.sync);
14388 GLbitfield flags = static_cast<GLbitfield>(c.flags);
14389 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
14390 GLsync service_sync = 0;
14391 if (!group_->GetSyncServiceId(sync, &service_sync)) {
14392 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
14393 return error::kNoError;
14395 glWaitSync(service_sync, flags, timeout);
14396 return error::kNoError;
14399 error::Error GLES2DecoderImpl::HandleGetInternalformativ(
14400 uint32_t immediate_data_size, const void* cmd_data) {
14401 if (!unsafe_es3_apis_enabled())
14402 return error::kUnknownCommand;
14403 const gles2::cmds::GetInternalformativ& c =
14404 *static_cast<const gles2::cmds::GetInternalformativ*>(cmd_data);
14405 GLenum target = static_cast<GLenum>(c.target);
14406 GLenum format = static_cast<GLenum>(c.format);
14407 GLenum pname = static_cast<GLenum>(c.pname);
14408 if (!validators_->render_buffer_target.IsValid(target)) {
14409 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target, "target");
14410 return error::kNoError;
14412 if (!validators_->render_buffer_format.IsValid(format)) {
14413 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format, "format");
14414 return error::kNoError;
14416 if (!validators_->internal_format_parameter.IsValid(pname)) {
14417 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname, "pname");
14418 return error::kNoError;
14420 typedef cmds::GetInternalformativ::Result Result;
14421 GLsizei num_values = 0;
14422 switch (pname) {
14423 case GL_NUM_SAMPLE_COUNTS:
14424 num_values = 1;
14425 break;
14426 case GL_SAMPLES:
14428 GLint value = 0;
14429 glGetInternalformativ(target, format, GL_NUM_SAMPLE_COUNTS, 1, &value);
14430 num_values = static_cast<GLsizei>(value);
14432 break;
14433 default:
14434 NOTREACHED();
14435 break;
14437 Result* result = GetSharedMemoryAs<Result*>(
14438 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
14439 GLint* params = result ? result->GetData() : NULL;
14440 if (params == NULL) {
14441 return error::kOutOfBounds;
14443 // Check that the client initialized the result.
14444 if (result->size != 0) {
14445 return error::kInvalidArguments;
14447 glGetInternalformativ(target, format, pname, num_values, params);
14448 result->SetNumResults(num_values);
14449 return error::kNoError;
14452 error::Error GLES2DecoderImpl::HandleMapBufferRange(
14453 uint32_t immediate_data_size, const void* cmd_data) {
14454 if (!unsafe_es3_apis_enabled()) {
14455 return error::kUnknownCommand;
14457 const gles2::cmds::MapBufferRange& c =
14458 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
14459 GLenum target = static_cast<GLenum>(c.target);
14460 GLbitfield access = static_cast<GLbitfield>(c.access);
14461 GLintptr offset = static_cast<GLintptr>(c.offset);
14462 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
14464 typedef cmds::MapBufferRange::Result Result;
14465 Result* result = GetSharedMemoryAs<Result*>(
14466 c.result_shm_id, c.result_shm_offset, sizeof(*result));
14467 if (!result) {
14468 return error::kOutOfBounds;
14470 if (*result != 0) {
14471 *result = 0;
14472 return error::kInvalidArguments;
14474 int8_t* mem =
14475 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
14476 if (!mem) {
14477 return error::kOutOfBounds;
14480 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
14481 if ((access & mask) == mask) {
14482 // TODO(zmo): To be on the safe side, always map
14483 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
14484 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
14485 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
14487 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14488 // undefined behaviors.
14489 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
14490 if ((access & mask) == mask) {
14491 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
14492 "incompatible access bits");
14493 return error::kNoError;
14495 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
14496 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
14497 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14498 access = (access | GL_MAP_READ_BIT);
14500 void* ptr = glMapBufferRange(target, offset, size, access);
14501 if (ptr == nullptr) {
14502 return error::kNoError;
14504 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14505 DCHECK(buffer);
14506 buffer->SetMappedRange(offset, size, access, ptr,
14507 GetSharedMemoryBuffer(c.data_shm_id));
14508 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14509 memcpy(mem, ptr, size);
14511 *result = 1;
14512 return error::kNoError;
14515 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
14516 uint32_t immediate_data_size, const void* cmd_data) {
14517 if (!unsafe_es3_apis_enabled()) {
14518 return error::kUnknownCommand;
14520 const gles2::cmds::UnmapBuffer& c =
14521 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
14522 GLenum target = static_cast<GLenum>(c.target);
14524 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14525 if (!buffer) {
14526 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
14527 return error::kNoError;
14529 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
14530 if (!mapped_range) {
14531 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
14532 "buffer is unmapped");
14533 return error::kNoError;
14535 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
14536 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
14537 GL_MAP_FLUSH_EXPLICIT_BIT) {
14538 // If we don't need to write back, or explict flush is required, no copying
14539 // back is needed.
14540 } else {
14541 void* mem = mapped_range->GetShmPointer();
14542 if (!mem) {
14543 return error::kOutOfBounds;
14545 DCHECK(mapped_range->pointer);
14546 memcpy(mapped_range->pointer, mem, mapped_range->size);
14548 buffer->RemoveMappedRange();
14549 GLboolean rt = glUnmapBuffer(target);
14550 if (rt == GL_FALSE) {
14551 // At this point, we have already done the necessary validation, so
14552 // GL_FALSE indicates data corruption.
14553 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14554 // the second unmap could still return GL_FALSE. For now, we simply lose
14555 // the contexts in the share group.
14556 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14557 // Need to lose current context before broadcasting!
14558 MarkContextLost(error::kGuilty);
14559 group_->LoseContexts(error::kInnocent);
14560 return error::kLostContext;
14562 return error::kNoError;
14565 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14566 TextureRef* texture_ref) {
14567 Texture* texture = texture_ref->texture();
14568 DoDidUseTexImageIfNeeded(texture, texture->target());
14571 // Note that GL_LOST_CONTEXT is specific to GLES.
14572 // For desktop GL we have to query the reset status proactively.
14573 void GLES2DecoderImpl::OnContextLostError() {
14574 if (!WasContextLost()) {
14575 // Need to lose current context before broadcasting!
14576 CheckResetStatus();
14577 group_->LoseContexts(error::kUnknown);
14578 reset_by_robustness_extension_ = true;
14582 void GLES2DecoderImpl::OnOutOfMemoryError() {
14583 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
14584 error::ContextLostReason other = error::kOutOfMemory;
14585 if (CheckResetStatus()) {
14586 other = error::kUnknown;
14587 } else {
14588 // Need to lose current context before broadcasting!
14589 MarkContextLost(error::kOutOfMemory);
14591 group_->LoseContexts(other);
14595 error::Error GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14596 uint32 immediate_data_size,
14597 const void* cmd_data) {
14598 static const char kFunctionName[] = "glGenPathsCHROMIUM";
14599 const gles2::cmds::GenPathsCHROMIUM& c =
14600 *static_cast<const gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
14601 if (!features().chromium_path_rendering) {
14602 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14603 "function not available");
14604 return error::kNoError;
14607 GLsizei range = static_cast<GLsizei>(c.range);
14608 if (range < 0) {
14609 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14610 return error::kNoError;
14613 GLuint first_client_id = static_cast<GLuint>(c.first_client_id);
14614 if (first_client_id == 0)
14615 return error::kInvalidArguments;
14617 if (range == 0)
14618 return error::kNoError;
14620 if (!GenPathsCHROMIUMHelper(first_client_id, range))
14621 return error::kInvalidArguments;
14623 return error::kNoError;
14625 error::Error GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14626 uint32_t immediate_data_size,
14627 const void* cmd_data) {
14628 static const char kFunctionName[] = "glDeletePathsCHROMIUM";
14629 const gles2::cmds::DeletePathsCHROMIUM& c =
14630 *static_cast<const gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
14631 if (!features().chromium_path_rendering) {
14632 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14633 "function not available");
14634 return error::kNoError;
14637 GLsizei range = static_cast<GLsizei>(c.range);
14638 if (range < 0) {
14639 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14640 return error::kNoError;
14643 if (range == 0)
14644 return error::kNoError;
14646 GLuint first_client_id = c.first_client_id;
14647 // first_client_id can be 0, because non-existing path ids are skipped.
14649 if (!DeletePathsCHROMIUMHelper(first_client_id, range))
14650 return error::kInvalidArguments;
14652 return error::kNoError;
14655 error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14656 uint32 immediate_data_size,
14657 const void* cmd_data) {
14658 static const char kFunctionName[] = "glPathCommandsCHROMIUM";
14659 const gles2::cmds::PathCommandsCHROMIUM& c =
14660 *static_cast<const gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
14661 if (!features().chromium_path_rendering) {
14662 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14663 "function not available");
14664 return error::kNoError;
14667 GLuint service_id = 0;
14668 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14669 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14670 "invalid path name");
14671 return error::kNoError;
14674 GLsizei num_commands = static_cast<GLsizei>(c.numCommands);
14675 if (num_commands < 0) {
14676 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCommands < 0");
14677 return error::kNoError;
14680 GLsizei num_coords = static_cast<uint32>(c.numCoords);
14681 if (num_coords < 0) {
14682 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCoords < 0");
14683 return error::kNoError;
14686 GLenum coord_type = static_cast<uint32>(c.coordType);
14687 if (!validators_->path_coord_type.IsValid(static_cast<GLint>(coord_type))) {
14688 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid coordType");
14689 return error::kNoError;
14692 const GLubyte* commands = NULL;
14693 base::CheckedNumeric<GLsizei> num_coords_expected = 0;
14695 if (num_commands > 0) {
14696 uint32 commands_shm_id = static_cast<uint32>(c.commands_shm_id);
14697 uint32 commands_shm_offset = static_cast<uint32>(c.commands_shm_offset);
14698 if (commands_shm_id != 0 || commands_shm_offset != 0)
14699 commands = GetSharedMemoryAs<const GLubyte*>(
14700 commands_shm_id, commands_shm_offset, num_commands);
14702 if (!commands)
14703 return error::kOutOfBounds;
14705 for (GLsizei i = 0; i < num_commands; ++i) {
14706 switch (commands[i]) {
14707 case GL_CLOSE_PATH_CHROMIUM:
14708 // Close has no coords.
14709 break;
14710 case GL_MOVE_TO_CHROMIUM:
14711 // Fallthrough.
14712 case GL_LINE_TO_CHROMIUM:
14713 num_coords_expected += 2;
14714 break;
14715 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
14716 num_coords_expected += 4;
14717 break;
14718 case GL_CUBIC_CURVE_TO_CHROMIUM:
14719 num_coords_expected += 6;
14720 break;
14721 case GL_CONIC_CURVE_TO_CHROMIUM:
14722 num_coords_expected += 5;
14723 break;
14724 default:
14725 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid command");
14726 return error::kNoError;
14731 if (!num_coords_expected.IsValid() ||
14732 num_coords != num_coords_expected.ValueOrDie()) {
14733 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14734 "numCoords does not match commands");
14735 return error::kNoError;
14738 const void* coords = NULL;
14740 if (num_coords > 0) {
14741 uint32 coords_size = 0;
14742 uint32 coord_type_size =
14743 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
14744 if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size))
14745 return error::kOutOfBounds;
14747 uint32 coords_shm_id = static_cast<uint32>(c.coords_shm_id);
14748 uint32 coords_shm_offset = static_cast<uint32>(c.coords_shm_offset);
14749 if (coords_shm_id != 0 || coords_shm_offset != 0)
14750 coords = GetSharedMemoryAs<const void*>(coords_shm_id, coords_shm_offset,
14751 coords_size);
14753 if (!coords)
14754 return error::kOutOfBounds;
14757 glPathCommandsNV(service_id, num_commands, commands, num_coords, coord_type,
14758 coords);
14760 return error::kNoError;
14763 error::Error GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14764 uint32 immediate_data_size,
14765 const void* cmd_data) {
14766 static const char kFunctionName[] = "glPathParameterfCHROMIUM";
14767 const gles2::cmds::PathParameterfCHROMIUM& c =
14768 *static_cast<const gles2::cmds::PathParameterfCHROMIUM*>(cmd_data);
14769 if (!features().chromium_path_rendering) {
14770 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14771 "function not available");
14772 return error::kNoError;
14774 GLuint service_id = 0;
14775 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14776 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14777 "invalid path name");
14778 return error::kNoError;
14781 GLenum pname = static_cast<GLenum>(c.pname);
14782 GLfloat value = static_cast<GLfloat>(c.value);
14783 bool hasValueError = false;
14785 switch (pname) {
14786 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14787 case GL_PATH_MITER_LIMIT_CHROMIUM:
14788 hasValueError = std::isnan(value) || !std::isfinite(value) || value < 0;
14789 break;
14790 case GL_PATH_STROKE_BOUND_CHROMIUM:
14791 value = std::max(std::min(1.0f, value), 0.0f);
14792 break;
14793 case GL_PATH_END_CAPS_CHROMIUM:
14794 hasValueError = !validators_->path_parameter_cap_values.IsValid(
14795 static_cast<GLint>(value));
14796 break;
14797 case GL_PATH_JOIN_STYLE_CHROMIUM:
14798 hasValueError = !validators_->path_parameter_join_values.IsValid(
14799 static_cast<GLint>(value));
14800 break;
14801 default:
14802 DCHECK(!validators_->path_parameter.IsValid(pname));
14803 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14804 return error::kNoError;
14806 DCHECK(validators_->path_parameter.IsValid(pname));
14808 if (hasValueError) {
14809 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14810 return error::kNoError;
14813 glPathParameterfNV(service_id, pname, value);
14814 return error::kNoError;
14817 error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14818 uint32 immediate_data_size,
14819 const void* cmd_data) {
14820 static const char kFunctionName[] = "glPathParameteriCHROMIUM";
14821 const gles2::cmds::PathParameteriCHROMIUM& c =
14822 *static_cast<const gles2::cmds::PathParameteriCHROMIUM*>(cmd_data);
14823 if (!features().chromium_path_rendering) {
14824 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14825 "function not available");
14826 return error::kNoError;
14828 GLuint service_id = 0;
14829 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14830 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14831 "invalid path name");
14832 return error::kNoError;
14835 GLenum pname = static_cast<GLenum>(c.pname);
14836 GLint value = static_cast<GLint>(c.value);
14837 bool hasValueError = false;
14839 switch (pname) {
14840 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14841 case GL_PATH_MITER_LIMIT_CHROMIUM:
14842 hasValueError = value < 0;
14843 break;
14844 case GL_PATH_STROKE_BOUND_CHROMIUM:
14845 value = std::max(std::min(1, value), 0);
14846 break;
14847 case GL_PATH_END_CAPS_CHROMIUM:
14848 hasValueError = !validators_->path_parameter_cap_values.IsValid(value);
14849 break;
14850 case GL_PATH_JOIN_STYLE_CHROMIUM:
14851 hasValueError = !validators_->path_parameter_join_values.IsValid(value);
14852 break;
14853 default:
14854 DCHECK(!validators_->path_parameter.IsValid(pname));
14855 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14856 return error::kNoError;
14858 DCHECK(validators_->path_parameter.IsValid(pname));
14860 if (hasValueError) {
14861 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14862 return error::kNoError;
14865 glPathParameteriNV(service_id, pname, value);
14866 return error::kNoError;
14869 error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14870 uint32 immediate_data_size,
14871 const void* cmd_data) {
14872 static const char kFunctionName[] = "glStencilFillPathCHROMIUM";
14873 const gles2::cmds::StencilFillPathCHROMIUM& c =
14874 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(cmd_data);
14875 if (!features().chromium_path_rendering) {
14876 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14877 "function not available");
14878 return error::kNoError;
14880 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14881 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14882 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14883 return error::kNoError;
14885 GLuint mask = static_cast<GLuint>(c.mask);
14886 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14887 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14888 GLES2Util::IsNPOT(mask + 1)) {
14889 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14890 "mask + 1 is not power of two");
14891 return error::kNoError;
14893 GLuint service_id = 0;
14894 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14895 // "If /path/ does not name an existing path object, the command does
14896 // nothing (and no error is generated)."
14897 // This holds for other rendering functions, too.
14898 return error::kNoError;
14900 ApplyDirtyState();
14901 glStencilFillPathNV(service_id, fill_mode, mask);
14902 return error::kNoError;
14905 error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14906 uint32 immediate_data_size,
14907 const void* cmd_data) {
14908 static const char kFunctionName[] = "glStencilStrokePathCHROMIUM";
14909 const gles2::cmds::StencilStrokePathCHROMIUM& c =
14910 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data);
14911 if (!features().chromium_path_rendering) {
14912 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14913 "function not available");
14914 return error::kNoError;
14916 GLuint service_id = 0;
14917 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14918 return error::kNoError;
14920 GLint reference = static_cast<GLint>(c.reference);
14921 GLuint mask = static_cast<GLuint>(c.mask);
14922 ApplyDirtyState();
14923 glStencilStrokePathNV(service_id, reference, mask);
14924 return error::kNoError;
14927 error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14928 uint32 immediate_data_size,
14929 const void* cmd_data) {
14930 static const char kFunctionName[] = "glCoverFillPathCHROMIUM";
14931 const gles2::cmds::CoverFillPathCHROMIUM& c =
14932 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data);
14933 if (!features().chromium_path_rendering) {
14934 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14935 "function not available");
14936 return error::kNoError;
14938 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14939 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14940 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14941 return error::kNoError;
14943 GLuint service_id = 0;
14944 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14945 return error::kNoError;
14947 ApplyDirtyState();
14948 glCoverFillPathNV(service_id, cover_mode);
14949 return error::kNoError;
14952 error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14953 uint32 immediate_data_size,
14954 const void* cmd_data) {
14955 static const char kFunctionName[] = "glCoverStrokePathCHROMIUM";
14956 const gles2::cmds::CoverStrokePathCHROMIUM& c =
14957 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data);
14958 if (!features().chromium_path_rendering) {
14959 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14960 "function not available");
14961 return error::kNoError;
14963 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14964 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14965 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14966 return error::kNoError;
14968 GLuint service_id = 0;
14969 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14970 return error::kNoError;
14972 ApplyDirtyState();
14973 glCoverStrokePathNV(service_id, cover_mode);
14974 return error::kNoError;
14977 error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14978 uint32 immediate_data_size,
14979 const void* cmd_data) {
14980 static const char kFunctionName[] = "glStencilThenCoverFillPathCHROMIUM";
14981 const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
14982 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
14983 cmd_data);
14984 if (!features().chromium_path_rendering) {
14985 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14986 "function not available");
14987 return error::kNoError;
14989 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14990 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14991 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14992 return error::kNoError;
14994 GLuint mask = static_cast<GLuint>(c.mask);
14995 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14996 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14997 GLES2Util::IsNPOT(mask + 1)) {
14998 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14999 "mask + 1 is not power of two");
15000 return error::kNoError;
15002 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
15003 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
15004 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
15005 return error::kNoError;
15007 GLuint service_id = 0;
15008 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
15009 return error::kNoError;
15011 ApplyDirtyState();
15012 glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode);
15013 return error::kNoError;
15016 error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
15017 uint32 immediate_data_size,
15018 const void* cmd_data) {
15019 static const char kFunctionName[] = "glStencilThenCoverStrokePathCHROMIUM";
15020 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
15021 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
15022 cmd_data);
15023 if (!features().chromium_path_rendering) {
15024 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
15025 "function not available");
15026 return error::kNoError;
15028 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
15029 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
15030 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
15031 return error::kNoError;
15033 GLuint service_id = 0;
15034 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
15035 return error::kNoError;
15037 GLint reference = static_cast<GLint>(c.reference);
15038 GLuint mask = static_cast<GLuint>(c.mask);
15039 ApplyDirtyState();
15040 glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode);
15041 return error::kNoError;
15044 // Include the auto-generated part of this file. We split this because it means
15045 // we can easily edit the non-auto generated parts right here in this file
15046 // instead of having to edit some template or the code generator.
15047 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
15049 } // namespace gles2
15050 } // namespace gpu