Merge from Chromium at DEPS revision r202854
This commit was generated by merge_to_master.py.
Change-Id: Idca323f71ef844a9e04f454d4f070b1e398f2deb
diff --git a/gpu/DEPS b/gpu/DEPS
index 43b6a19..074d493 100644
--- a/gpu/DEPS
+++ b/gpu/DEPS
@@ -5,12 +5,6 @@
"+third_party/re2",
"+third_party/smhasher",
"+third_party/protbuf",
- "+../../gpu_export.h",
- "+../command_buffer",
- "+../client",
- "+../common",
- "+../GLES2",
- "+../service",
"+crypto",
"+ui/gfx",
"+ui/gl",
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_map_image.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_map_image.txt
new file mode 100644
index 0000000..6304fda
--- /dev/null
+++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_map_image.txt
@@ -0,0 +1,107 @@
+Name
+
+ CHROMIUM_map_image
+
+Name Strings
+
+ GL_CHROMIUM_map_image
+
+Version
+
+ Last Modifed Date: May 9, 2013
+
+Dependencies
+
+ OpenGL ES 2.0 is required.
+
+Overview
+
+ This extension allows for more efficient uploading of texture data through
+ Chromium's OpenGL ES 2.0 implementation.
+
+ For security reasons Chromium accesses the GPU from a separate process. User
+ processes are not allowed to access the GPU directly. This multi-process
+ architechure has the advantage that GPU operations can be secured and
+ pipelined but it has the disadvantage that all data that is going to be
+ passed to GPU must first be made available to the separate GPU process.
+
+ This extension helps the application directly allocate and access texture
+ memory.
+
+Issues
+
+ None
+
+New Tokens
+
+ None
+
+New Procedures and Functions
+
+ GLuint CreateImageCHROMIUM (GLsizei width, GLsizei height,
+ GLenum internalformat)
+
+ Allocate an image with width equal to <width> and height equal
+ to <height> stored in format <internalformat>.
+
+ Returns a unique identifier for the allocated image that could be used
+ in subsequent operations.
+
+ INVALID_VALUE is generated if <width> or <height> is nonpositive.
+
+ void DestroyImageCHROMIUM (GLuint image_id)
+
+ Frees the image previously allocated by a call to CreateImageCHROMIUM.
+
+ INVALID_OPERATION is generated if <image_id> is not a valid image id.
+
+ void* MapImageCHROMIUM (GLuint image_id, GLenum access)
+
+ Returns a pointer to in the user memory for the application to modify
+ the image. <access> parameter defines if the user will read or write the
+ pixels.
+
+ INVALID_OPERATION is generated if <image_id> is not a valid image id.
+
+ INVALID_OPERATION is generated if the image was already mapped by a previous
+ call to this method.
+
+ INVALID_ENUM is generated if <access> is not one of WRITE_ONLY, READ_ONLY
+ and READ_WRITE.
+
+ void UnmapImageCHROMIUM (GLuint image_id)
+
+ Removes the mapping created by a call to MapImageCHROMIUM.
+
+ Note that after calling UnmapImageCHROMIUM the application should assume
+ that the memory returned by MapImageCHROMIUM is off limits and is no longer
+ accessible by the application. Accessing it after calling
+ UnmapImageCHROMIUM will produce undefined results.
+
+ INVALID_OPERATION is generated if <image_id> is not a valid image id.
+
+ INVALID_OPERATION is generated if the image was not already mapped by a
+ previous call to MapImageCHROMIUM.
+
+ void GetImageParameterivCHROMIUM(GLuint image_id, GLenum pname,
+ GLint* params)
+
+ Sets <params> to the integer value of the parameter specified by <pname>
+ for the image specified by <image_id>. <params> is expected to be
+ properly allocated before calling this method.
+
+ INVALID_OPERATION is generated if <image_id> is not a valid image id.
+
+ INVALID_ENUM is generated if <pname> is not IMAGE_ROWBYTES_CHROMIUM.
+
+Errors
+
+ None.
+
+New State
+
+ None.
+
+Revision History
+
+ 5/9/2013 Documented the extension
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h
index fa099e6..e8970e0 100644
--- a/gpu/GLES2/gl2chromium_autogen.h
+++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -182,6 +182,8 @@
#define glEnableFeatureCHROMIUM GLES2_GET_FUN(EnableFeatureCHROMIUM)
#define glMapBufferCHROMIUM GLES2_GET_FUN(MapBufferCHROMIUM)
#define glUnmapBufferCHROMIUM GLES2_GET_FUN(UnmapBufferCHROMIUM)
+#define glMapImageCHROMIUM GLES2_GET_FUN(MapImageCHROMIUM)
+#define glUnmapImageCHROMIUM GLES2_GET_FUN(UnmapImageCHROMIUM)
#define glMapBufferSubDataCHROMIUM GLES2_GET_FUN(MapBufferSubDataCHROMIUM)
#define glUnmapBufferSubDataCHROMIUM GLES2_GET_FUN(UnmapBufferSubDataCHROMIUM)
#define glMapTexSubImage2DCHROMIUM GLES2_GET_FUN(MapTexSubImage2DCHROMIUM)
@@ -199,6 +201,10 @@
CreateStreamTextureCHROMIUM)
#define glDestroyStreamTextureCHROMIUM GLES2_GET_FUN( \
DestroyStreamTextureCHROMIUM)
+#define glCreateImageCHROMIUM GLES2_GET_FUN(CreateImageCHROMIUM)
+#define glDestroyImageCHROMIUM GLES2_GET_FUN(DestroyImageCHROMIUM)
+#define glGetImageParameterivCHROMIUM GLES2_GET_FUN( \
+ GetImageParameterivCHROMIUM)
#define glGetTranslatedShaderSourceANGLE GLES2_GET_FUN( \
GetTranslatedShaderSourceANGLE)
#define glPostSubBufferCHROMIUM GLES2_GET_FUN(PostSubBufferCHROMIUM)
diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h
index 9193467..2568074 100644
--- a/gpu/GLES2/gl2extchromium.h
+++ b/gpu/GLES2/gl2extchromium.h
@@ -94,6 +94,39 @@
#endif
#endif /* GL_CHROMIUM_pixel_transfer_buffer_object */
+/* GL_CHROMIUM_map_image */
+#ifndef GL_CHROMIUM_map_image
+#define GL_CHROMIUM_map_image 1
+
+#ifndef GL_IMAGE_ROWBYTES_CHROMIUM
+#define GL_IMAGE_ROWBYTES_CHROMIUM 0x78F0
+#endif
+
+#ifndef GL_READ_WRITE
+#define GL_READ_WRITE 0x88BA
+#endif
+
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint GL_APIENTRY glCreateImageCHROMIUM(
+ GLsizei width, GLsizei height, GLenum internalformat);
+GL_APICALL void GL_APIENTRY glDestroyImageCHROMIUM(GLuint image_id);
+GL_APICALL void GL_APIENTRY glGetImageParameterivCHROMIUM(
+ GLuint image_id, GLenum pname, GLint* params);
+GL_APICALL void* GL_APIENTRY glMapImageCHROMIUM(GLuint image_id, GLenum access);
+GL_APICALL void GL_APIENTRY glUnmapImageCHROMIUM(GLuint image_id);
+#endif
+typedef GLuint (GL_APIENTRYP PFNGLCREATEIMAGECHROMIUMPROC) (
+ GLsizei width, GLsizei height, GLenum internalformat);
+typedef void (
+ GL_APIENTRYP PFNGLDESTROYIMAGECHROMIUMPROC) (GLuint image_id);
+typedef void (
+ GL_APIENTRYP PFNGLGETIMAGEPARAMETERIVCHROMIUMPROC) (
+ GLuint image_id, GLenum pname, GLint* params);
+typedef void* (GL_APIENTRYP PFNGLMAPIMAGECHROMIUMPROC) (
+ GLuint image_id, GLenum access);
+typedef void (GL_APIENTRYP PFNGLUNMAPIMAGECHROMIUMPROC) (GLuint image_id);
+#endif /* GL_CHROMIUM_map_image */
+
/* GL_CHROMIUM_map_sub */
#ifndef GL_CHROMIUM_map_sub
#define GL_CHROMIUM_map_sub 1
@@ -542,7 +575,8 @@
#ifndef GL_CHROMIUM_resize
#define GL_CHROMIUM_resize 1
#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glResizeCHROMIUM(GLuint width, GLuint height);
+GL_APICALL void GL_APIENTRY glResizeCHROMIUM(
+ GLuint width, GLuint height, GLfloat scale_factor);
#endif
typedef void (GL_APIENTRYP PFNGLRESIZECHROMIUMPROC) (
GLuint width, GLuint height);
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index f8a355d..435d13a 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1306,6 +1306,32 @@
'decoder_func': 'DoCopyTexSubImage2D',
'defer_reads': True,
},
+ 'CreateImageCHROMIUM': {
+ 'type': 'Manual',
+ 'cmd_args': 'GLsizei width, GLsizei height, GLenum internalformat',
+ 'result': ['GLuint'],
+ 'client_test': False,
+ 'gen_cmd': False,
+ 'expectation': False,
+ 'extension': True,
+ 'chromium': True,
+ },
+ 'DestroyImageCHROMIUM': {
+ 'type': 'Manual',
+ 'immediate': True,
+ 'client_test': False,
+ 'gen_cmd': False,
+ 'extension': True,
+ 'chromium': True,
+ },
+ 'GetImageParameterivCHROMIUM': {
+ 'type': 'Manual',
+ 'client_test': False,
+ 'gen_cmd': False,
+ 'expectation': False,
+ 'extension': True,
+ 'chromium': True,
+ },
'CreateProgram': {
'type': 'Create',
'client_test': False,
@@ -1780,7 +1806,6 @@
'extension': True,
'chromium': True,
'client_test': False,
- 'chromium': True,
},
'MapBufferSubDataCHROMIUM': {
'gen_cmd': False,
@@ -1789,6 +1814,12 @@
'client_test': False,
'pepper_interface': 'ChromiumMapSub',
},
+ 'MapImageCHROMIUM': {
+ 'gen_cmd': False,
+ 'extension': True,
+ 'chromium': True,
+ 'client_test': False,
+ },
'MapTexSubImage2DCHROMIUM': {
'gen_cmd': False,
'extension': True,
@@ -2015,7 +2046,6 @@
'extension': True,
'chromium': True,
'client_test': False,
- 'chromium': True,
},
'UnmapBufferSubDataCHROMIUM': {
'gen_cmd': False,
@@ -2024,6 +2054,12 @@
'client_test': False,
'pepper_interface': 'ChromiumMapSub',
},
+ 'UnmapImageCHROMIUM': {
+ 'gen_cmd': False,
+ 'extension': True,
+ 'chromium': True,
+ 'client_test': False,
+ },
'UnmapTexSubImage2DCHROMIUM': {
'gen_cmd': False,
'extension': True,
diff --git a/gpu/command_buffer/client/atomicops.cc b/gpu/command_buffer/client/atomicops.cc
index 318c337..c4d5cb1 100644
--- a/gpu/command_buffer/client/atomicops.cc
+++ b/gpu/command_buffer/client/atomicops.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "../client/atomicops.h"
-#include "../common/logging.h"
+#include "gpu/command_buffer/client/atomicops.h"
+#include "gpu/command_buffer/common/logging.h"
#if !defined(__native_client__)
#include "base/atomicops.h"
diff --git a/gpu/command_buffer/client/atomicops.h b/gpu/command_buffer/client/atomicops.h
index 8a6f979..9e1628e 100644
--- a/gpu/command_buffer/client/atomicops.h
+++ b/gpu/command_buffer/client/atomicops.h
@@ -6,8 +6,8 @@
#define GPU_COMMAND_BUFFER_CLIENT_ATOMICOPS_H_
#include "base/memory/scoped_ptr.h"
-#include "../../gpu_export.h"
-#include "../common/types.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/gpu_export.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/buffer_tracker.cc b/gpu/command_buffer/client/buffer_tracker.cc
index 59c7d1e..f5ead5a 100644
--- a/gpu/command_buffer/client/buffer_tracker.cc
+++ b/gpu/command_buffer/client/buffer_tracker.cc
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "../client/buffer_tracker.h"
+#include "gpu/command_buffer/client/buffer_tracker.h"
-#include "../client/atomicops.h"
-#include "../client/cmd_buffer_helper.h"
-#include "../client/mapped_memory.h"
+#include "gpu/command_buffer/client/atomicops.h"
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/client/mapped_memory.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/client/buffer_tracker.h b/gpu/command_buffer/client/buffer_tracker.h
index f8fc057..e61c501 100644
--- a/gpu/command_buffer/client/buffer_tracker.h
+++ b/gpu/command_buffer/client/buffer_tracker.h
@@ -8,9 +8,9 @@
#include <GLES2/gl2.h>
#include <queue>
-#include "../client/hash_tables.h"
-#include "../common/gles2_cmd_format.h"
#include "gles2_impl_export.h"
+#include "gpu/command_buffer/client/hash_tables.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/client_context_state.cc b/gpu/command_buffer/client/client_context_state.cc
index 84a262e..ecb33b6 100644
--- a/gpu/command_buffer/client/client_context_state.cc
+++ b/gpu/command_buffer/client/client_context_state.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "../client/client_context_state.h"
-#include "../common/logging.h"
+#include "gpu/command_buffer/client/client_context_state.h"
+#include "gpu/command_buffer/common/logging.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc
index b68c11f..2fa15aa 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.cc
+++ b/gpu/command_buffer/client/cmd_buffer_helper.cc
@@ -4,9 +4,9 @@
// This file contains the implementation of the command buffer helper class.
-#include "../client/cmd_buffer_helper.h"
-#include "../common/command_buffer.h"
-#include "../common/trace_event.h"
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/command_buffer/common/trace_event.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h
index 938dfdf..5ef8d0e 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.h
+++ b/gpu/command_buffer/client/cmd_buffer_helper.h
@@ -10,11 +10,11 @@
#include <string.h>
#include <time.h>
-#include "../../gpu_export.h"
-#include "../common/logging.h"
-#include "../common/constants.h"
-#include "../common/cmd_buffer_common.h"
-#include "../common/command_buffer.h"
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/logging.h"
+#include "gpu/gpu_export.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/fenced_allocator.cc b/gpu/command_buffer/client/fenced_allocator.cc
index 7e1ab2f..6eb9ab3 100644
--- a/gpu/command_buffer/client/fenced_allocator.cc
+++ b/gpu/command_buffer/client/fenced_allocator.cc
@@ -4,9 +4,9 @@
// This file contains the implementation of the FencedAllocator class.
-#include "../client/fenced_allocator.h"
+#include "gpu/command_buffer/client/fenced_allocator.h"
#include <algorithm>
-#include "../client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/fenced_allocator.h b/gpu/command_buffer/client/fenced_allocator.h
index 3ccad45..90288d9 100644
--- a/gpu/command_buffer/client/fenced_allocator.h
+++ b/gpu/command_buffer/client/fenced_allocator.h
@@ -9,9 +9,9 @@
#include <vector>
-#include "../../gpu_export.h"
-#include "../common/logging.h"
-#include "../common/types.h"
+#include "gpu/command_buffer/common/logging.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/gpu_export.h"
namespace gpu {
class CommandBufferHelper;
diff --git a/gpu/command_buffer/client/gles2_c_lib.cc b/gpu/command_buffer/client/gles2_c_lib.cc
index ea20739..fbe7b55 100644
--- a/gpu/command_buffer/client/gles2_c_lib.cc
+++ b/gpu/command_buffer/client/gles2_c_lib.cc
@@ -6,7 +6,7 @@
#include <assert.h>
#include <stdlib.h>
-#include "../client/gles2_lib.h"
+#include "gpu/command_buffer/client/gles2_lib.h"
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
@@ -18,7 +18,7 @@
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
-#include "../client/gles2_c_lib_autogen.h"
+#include "gpu/command_buffer/client/gles2_c_lib_autogen.h"
} // extern "C"
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index f1a5b08..f617163 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -595,6 +595,12 @@
GLboolean GLES2UnmapBufferCHROMIUM(GLuint target) {
return gles2::GetGLContext()->UnmapBufferCHROMIUM(target);
}
+void* GLES2MapImageCHROMIUM(GLuint image_id, GLenum access) {
+ return gles2::GetGLContext()->MapImageCHROMIUM(image_id, access);
+}
+void GLES2UnmapImageCHROMIUM(GLuint image_id) {
+ gles2::GetGLContext()->UnmapImageCHROMIUM(image_id);
+}
void* GLES2MapBufferSubDataCHROMIUM(
GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) {
return gles2::GetGLContext()->MapBufferSubDataCHROMIUM(
@@ -612,8 +618,8 @@
void GLES2UnmapTexSubImage2DCHROMIUM(const void* mem) {
gles2::GetGLContext()->UnmapTexSubImage2DCHROMIUM(mem);
}
-void GLES2ResizeCHROMIUM(GLuint width, GLuint height) {
- gles2::GetGLContext()->ResizeCHROMIUM(width, height);
+void GLES2ResizeCHROMIUM(GLuint width, GLuint height, GLfloat scale_factor) {
+ gles2::GetGLContext()->ResizeCHROMIUM(width, height, scale_factor);
}
const GLchar* GLES2GetRequestableExtensionsCHROMIUM() {
return gles2::GetGLContext()->GetRequestableExtensionsCHROMIUM();
@@ -639,6 +645,18 @@
void GLES2DestroyStreamTextureCHROMIUM(GLuint texture) {
gles2::GetGLContext()->DestroyStreamTextureCHROMIUM(texture);
}
+GLuint GLES2CreateImageCHROMIUM(
+ GLsizei width, GLsizei height, GLenum internalformat) {
+ return gles2::GetGLContext()->CreateImageCHROMIUM(
+ width, height, internalformat);
+}
+void GLES2DestroyImageCHROMIUM(GLuint image_id) {
+ gles2::GetGLContext()->DestroyImageCHROMIUM(image_id);
+}
+void GLES2GetImageParameterivCHROMIUM(
+ GLuint image_id, GLenum pname, GLint* params) {
+ gles2::GetGLContext()->GetImageParameterivCHROMIUM(image_id, pname, params);
+}
void GLES2GetTranslatedShaderSourceANGLE(
GLuint shader, GLsizei bufsize, GLsizei* length, char* source) {
gles2::GetGLContext()->GetTranslatedShaderSourceANGLE(
@@ -1006,6 +1024,10 @@
glMapBufferCHROMIUM), },
{ "glUnmapBufferCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
glUnmapBufferCHROMIUM), },
+ { "glMapImageCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
+ glMapImageCHROMIUM), },
+ { "glUnmapImageCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
+ glUnmapImageCHROMIUM), },
{ "glMapBufferSubDataCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
glMapBufferSubDataCHROMIUM), },
{ "glUnmapBufferSubDataCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
@@ -1028,6 +1050,12 @@
glCreateStreamTextureCHROMIUM), },
{ "glDestroyStreamTextureCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
glDestroyStreamTextureCHROMIUM), },
+ { "glCreateImageCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
+ glCreateImageCHROMIUM), },
+ { "glDestroyImageCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
+ glDestroyImageCHROMIUM), },
+ { "glGetImageParameterivCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
+ glGetImageParameterivCHROMIUM), },
{ "glGetTranslatedShaderSourceANGLE", reinterpret_cast<GLES2FunctionPointer>(
glGetTranslatedShaderSourceANGLE), },
{ "glPostSubBufferCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
diff --git a/gpu/command_buffer/client/gles2_cmd_helper.cc b/gpu/command_buffer/client/gles2_cmd_helper.cc
index 8264941..d52970a 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper.cc
+++ b/gpu/command_buffer/client/gles2_cmd_helper.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "../client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/client/gles2_cmd_helper.h b/gpu/command_buffer/client/gles2_cmd_helper.h
index 521d864..7361a9b 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper.h
@@ -5,9 +5,9 @@
#ifndef GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_H_
#define GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_H_
-#include "../../gpu_export.h"
-#include "../client/cmd_buffer_helper.h"
-#include "../common/gles2_cmd_format.h"
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
+#include "gpu/gpu_export.h"
namespace gpu {
namespace gles2 {
@@ -21,7 +21,7 @@
// Include the auto-generated part of this class. We split this because it
// means we can easily edit the non-auto generated parts right here in this
// file instead of having to edit some template or the code generator.
- #include "../client/gles2_cmd_helper_autogen.h"
+ #include "gpu/command_buffer/client/gles2_cmd_helper_autogen.h"
// Helpers that could not be auto-generated.
// TODO(gman): Auto generate these.
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index 1a99879..a290365 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -1777,11 +1777,11 @@
}
}
- void ResizeCHROMIUM(GLuint width, GLuint height) {
+ void ResizeCHROMIUM(GLuint width, GLuint height, GLfloat scale_factor) {
gles2::cmds::ResizeCHROMIUM* c =
GetCmdSpace<gles2::cmds::ResizeCHROMIUM>();
if (c) {
- c->Init(width, height);
+ c->Init(width, height, scale_factor);
}
}
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 0ce55a5..b64c67b 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -4,7 +4,7 @@
// A class to emulate GLES2 over command buffers.
-#include "../client/gles2_implementation.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
#include <algorithm>
#include <map>
@@ -15,14 +15,16 @@
#include <string.h>
#include <GLES2/gl2ext.h>
#include <GLES2/gl2extchromium.h>
-#include "../client/buffer_tracker.h"
-#include "../client/mapped_memory.h"
-#include "../client/program_info_manager.h"
-#include "../client/query_tracker.h"
-#include "../client/transfer_buffer.h"
-#include "../client/vertex_array_object_manager.h"
-#include "../common/gles2_cmd_utils.h"
-#include "../common/trace_event.h"
+#include "gpu/command_buffer/client/buffer_tracker.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_tracker.h"
+#include "gpu/command_buffer/client/mapped_memory.h"
+#include "gpu/command_buffer/client/program_info_manager.h"
+#include "gpu/command_buffer/client/query_tracker.h"
+#include "gpu/command_buffer/client/transfer_buffer.h"
+#include "gpu/command_buffer/client/vertex_array_object_manager.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/trace_event.h"
#if defined(__native_client__) && !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
#define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS
@@ -84,7 +86,8 @@
ShareGroup* share_group,
TransferBufferInterface* transfer_buffer,
bool share_resources,
- bool bind_generates_resource)
+ bool bind_generates_resource,
+ ImageFactory* image_factory)
: helper_(helper),
transfer_buffer_(transfer_buffer),
angle_pack_reverse_row_order_status_(kUnknownExtensionStatus),
@@ -108,7 +111,8 @@
debug_(false),
use_count_(0),
current_query_(NULL),
- error_message_callback_(NULL) {
+ error_message_callback_(NULL),
+ image_factory_(image_factory) {
GPU_DCHECK(helper);
GPU_DCHECK(transfer_buffer);
@@ -162,6 +166,7 @@
query_tracker_.reset(new QueryTracker(mapped_memory_.get()));
buffer_tracker_.reset(new BufferTracker(mapped_memory_.get()));
+ gpu_memory_buffer_tracker_.reset(new GpuMemoryBufferTracker(image_factory_));
#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
GetIdHandler(id_namespaces::kBuffers)->MakeIds(
@@ -2094,6 +2099,10 @@
"GL_CHROMIUM_map_sub "
"GL_CHROMIUM_shallow_flush "
"GL_EXT_unpack_subimage";
+ if (image_factory_ != NULL) {
+ // The first space character is intentional.
+ str += " GL_CHROMIUM_map_image";
+ }
break;
default:
break;
@@ -2227,7 +2236,7 @@
GLuint offset = ToGLuint(pixels);
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
bound_pixel_pack_transfer_buffer_id_,
- "glReadPixels", offset, temp_size);
+ "glReadPixels", offset, padded_row_size * height);
if (buffer && buffer->shm_id() != -1) {
helper_->ReadPixels(xoffset, yoffset, width, height, format, type,
buffer->shm_id(), buffer->shm_offset(),
@@ -2858,11 +2867,12 @@
CheckGLError();
}
-void GLES2Implementation::ResizeCHROMIUM(GLuint width, GLuint height) {
+void GLES2Implementation::ResizeCHROMIUM(GLuint width, GLuint height,
+ float scale_factor) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
- << width << ", " << height << ")");
- helper_->ResizeCHROMIUM(width, height);
+ << width << ", " << height << ", " << scale_factor << ")");
+ helper_->ResizeCHROMIUM(width, height, scale_factor);
CheckGLError();
}
@@ -3567,11 +3577,11 @@
}
BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
if (!buffer) {
- SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer");
+ SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "invalid buffer");
return false;
}
if (!buffer->mapped()) {
- SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "not mapped");
+ SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped");
return false;
}
buffer->set_mapped(false);
@@ -3687,10 +3697,172 @@
return helper_->InsertSyncPointCHROMIUM();
}
+GLuint GLES2Implementation::CreateImageCHROMIUMHelper(
+ GLsizei width, GLsizei height, GLenum internalformat) {
+ if (width <= 0) {
+ SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "width <= 0");
+ return 0;
+ }
+
+ if (height <= 0) {
+ SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "height <= 0");
+ return 0;
+ }
+ // Flush the command stream to ensure ordering in case the newly
+ // returned image_id has recently been in use with a different buffer.
+ helper_->CommandBufferHelper::Flush();
+
+ // Create new buffer.
+ GLuint buffer_id = gpu_memory_buffer_tracker_->CreateBuffer(
+ width, height, internalformat);
+ if (buffer_id == 0) {
+ SetGLError(GL_OUT_OF_MEMORY, "glCreateImageCHROMIUM", "out of GPU memory.");
+ return 0;
+ }
+ return buffer_id;
+}
+
+GLuint GLES2Implementation::CreateImageCHROMIUM(
+ GLsizei width, GLsizei height, GLenum internalformat) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM("
+ << width << ", "
+ << height << ", "
+ << GLES2Util::GetStringTextureInternalFormat(internalformat) << ")");
+ GLuint image_id = CreateImageCHROMIUMHelper(width, height, internalformat);
+ CheckGLError();
+ return image_id;
+}
+
+void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id) {
+ GpuMemoryBuffer* gpu_buffer =
+ gpu_memory_buffer_tracker_->GetBuffer(image_id);
+ if (!gpu_buffer) {
+ SetGLError(GL_INVALID_OPERATION, "glDestroyImageCHROMIUM",
+ "invalid image");
+ return;
+ }
+
+ // Flush the command stream to make sure all pending commands
+ // that may refer to the image_id are executed on the service side.
+ helper_->CommandBufferHelper::Flush();
+ gpu_memory_buffer_tracker_->RemoveBuffer(image_id);
+}
+
+void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
+ << image_id << ")");
+ DestroyImageCHROMIUMHelper(image_id);
+ CheckGLError();
+}
+
+void GLES2Implementation::UnmapImageCHROMIUMHelper(GLuint image_id) {
+ GpuMemoryBuffer* gpu_buffer =
+ gpu_memory_buffer_tracker_->GetBuffer(image_id);
+ if (!gpu_buffer) {
+ SetGLError(GL_INVALID_OPERATION, "glUnmapImageCHROMIUM", "invalid image");
+ return;
+ }
+
+ if (!gpu_buffer->IsMapped()) {
+ SetGLError(GL_INVALID_OPERATION, "glUnmapImageCHROMIUM", "not mapped");
+ return;
+ }
+ gpu_buffer->Unmap();
+}
+
+void GLES2Implementation::UnmapImageCHROMIUM(GLuint image_id) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapImageCHROMIUM("
+ << image_id << ")");
+
+ UnmapImageCHROMIUMHelper(image_id);
+ CheckGLError();
+}
+
+void* GLES2Implementation::MapImageCHROMIUMHelper(GLuint image_id,
+ GLenum access) {
+ GpuMemoryBuffer* gpu_buffer =
+ gpu_memory_buffer_tracker_->GetBuffer(image_id);
+ if (!gpu_buffer) {
+ SetGLError(GL_INVALID_OPERATION, "glMapImageCHROMIUM", "invalid image");
+ return NULL;
+ }
+ GpuMemoryBuffer::AccessMode mode;
+ switch(access) {
+ case GL_WRITE_ONLY:
+ mode = GpuMemoryBuffer::WRITE_ONLY;
+ break;
+ case GL_READ_ONLY:
+ mode = GpuMemoryBuffer::READ_ONLY;
+ break;
+ case GL_READ_WRITE:
+ mode = GpuMemoryBuffer::READ_WRITE;
+ break;
+ default:
+ SetGLError(GL_INVALID_ENUM, "glMapImageCHROMIUM",
+ "invalid GPU access mode");
+ return NULL;
+ }
+
+ if (gpu_buffer->IsMapped()) {
+ SetGLError(GL_INVALID_OPERATION, "glMapImageCHROMIUM", "already mapped");
+ return NULL;
+ }
+
+ void* mapped_buffer = NULL;
+ gpu_buffer->Map(mode, &mapped_buffer);
+ return mapped_buffer;
+}
+
+void* GLES2Implementation::MapImageCHROMIUM(
+ GLuint image_id, GLenum access) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapImageCHROMIUM("
+ << image_id << ", "
+ << GLES2Util::GetStringEnum(access) << ")");
+
+ void* mapped = MapImageCHROMIUMHelper(image_id, access);
+ CheckGLError();
+ return mapped;
+}
+
+void GLES2Implementation::GetImageParameterivCHROMIUMHelper(
+ GLuint image_id, GLenum pname, GLint* params) {
+ if (pname != GL_IMAGE_ROWBYTES_CHROMIUM) {
+ SetGLError(GL_INVALID_ENUM, "glGetImageParameterivCHROMIUM",
+ "invalid parameter");
+ return;
+ }
+
+ GpuMemoryBuffer* gpu_buffer =
+ gpu_memory_buffer_tracker_->GetBuffer(image_id);
+ if (!gpu_buffer) {
+ SetGLError(GL_INVALID_OPERATION, "glGetImageParameterivCHROMIUM",
+ "invalid image");
+ return;
+ }
+
+ *params = gpu_buffer->GetStride();
+}
+
+void GLES2Implementation::GetImageParameterivCHROMIUM(
+ GLuint image_id, GLenum pname, GLint* params) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, params);
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapImageCHROMIUM("
+ << image_id << ", "
+ << GLES2Util::GetStringBufferParameter(pname) << ", "
+ << static_cast<const void*>(params) << ")");
+ GetImageParameterivCHROMIUM(image_id, pname, params);
+ CheckGLError();
+}
+
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
-#include "../client/gles2_implementation_impl_autogen.h"
+#include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index a633dd6..c693383 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -14,18 +14,20 @@
#include <vector>
#include "base/memory/scoped_ptr.h"
-#include "../client/buffer_tracker.h"
-#include "../client/client_context_state.h"
-#include "../client/gles2_cmd_helper.h"
-#include "../client/gles2_interface.h"
-#include "../client/query_tracker.h"
-#include "../client/ref_counted.h"
-#include "../client/ring_buffer.h"
-#include "../client/share_group.h"
-#include "../common/compiler_specific.h"
-#include "../common/debug_marker_manager.h"
-#include "../common/gles2_cmd_utils.h"
#include "gles2_impl_export.h"
+#include "gpu/command_buffer/client/buffer_tracker.h"
+#include "gpu/command_buffer/client/client_context_state.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_tracker.h"
+#include "gpu/command_buffer/client/image_factory.h"
+#include "gpu/command_buffer/client/query_tracker.h"
+#include "gpu/command_buffer/client/ref_counted.h"
+#include "gpu/command_buffer/client/ring_buffer.h"
+#include "gpu/command_buffer/client/share_group.h"
+#include "gpu/command_buffer/common/compiler_specific.h"
+#include "gpu/command_buffer/common/debug_marker_manager.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#if !defined(NDEBUG) && !defined(__native_client__) && !defined(GLES2_CONFORMANCE_TESTS) // NOLINT
#if defined(GLES2_INLINE_OPTIMIZATION)
@@ -102,6 +104,7 @@
namespace gles2 {
+class ImageFactory;
class VertexArrayObjectManager;
// This class emulates GLES2 over command buffers. It can be used by a client
@@ -174,7 +177,8 @@
ShareGroup* share_group,
TransferBufferInterface* transfer_buffer,
bool share_resources,
- bool bind_generates_resource);
+ bool bind_generates_resource,
+ ImageFactory* image_factory);
virtual ~GLES2Implementation();
@@ -193,7 +197,7 @@
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
// this file instead of having to edit some template or the code generator.
- #include "../client/gles2_implementation_autogen.h"
+ #include "gpu/command_buffer/client/gles2_implementation_autogen.h"
virtual void DisableVertexAttribArray(GLuint index) OVERRIDE;
virtual void EnableVertexAttribArray(GLuint index) OVERRIDE;
@@ -496,6 +500,14 @@
GLenum target, GLintptr offset, GLsizeiptr size, const void* data,
ScopedTransferBufferPtr* buffer);
+ GLuint CreateImageCHROMIUMHelper(
+ GLsizei width, GLsizei height, GLenum internalformat);
+ void DestroyImageCHROMIUMHelper(GLuint image_id);
+ void* MapImageCHROMIUMHelper(GLuint image_id, GLenum access);
+ void UnmapImageCHROMIUMHelper(GLuint image_id);
+ void GetImageParameterivCHROMIUMHelper(
+ GLuint image_id, GLenum pname, GLint* params);
+
// Helper for GetVertexAttrib
bool GetVertexAttribHelper(GLuint index, GLenum pname, uint32* param);
@@ -654,10 +666,14 @@
scoped_ptr<BufferTracker> buffer_tracker_;
+ scoped_ptr<GpuMemoryBufferTracker> gpu_memory_buffer_tracker_;
+
ErrorMessageCallback* error_message_callback_;
scoped_ptr<std::string> current_trace_name_;
+ ImageFactory* image_factory_;
+
DISALLOW_COPY_AND_ASSIGN(GLES2Implementation);
};
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 3510bbf..b60730b 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -438,6 +438,10 @@
virtual GLboolean UnmapBufferCHROMIUM(GLuint target) OVERRIDE;
+virtual void* MapImageCHROMIUM(GLuint image_id, GLenum access) OVERRIDE;
+
+virtual void UnmapImageCHROMIUM(GLuint image_id) OVERRIDE;
+
virtual void* MapBufferSubDataCHROMIUM(
GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) OVERRIDE;
@@ -449,7 +453,8 @@
virtual void UnmapTexSubImage2DCHROMIUM(const void* mem) OVERRIDE;
-virtual void ResizeCHROMIUM(GLuint width, GLuint height) OVERRIDE;
+virtual void ResizeCHROMIUM(
+ GLuint width, GLuint height, GLfloat scale_factor) OVERRIDE;
virtual const GLchar* GetRequestableExtensionsCHROMIUM() OVERRIDE;
@@ -468,6 +473,14 @@
virtual void DestroyStreamTextureCHROMIUM(GLuint texture) OVERRIDE;
+virtual GLuint CreateImageCHROMIUM(
+ GLsizei width, GLsizei height, GLenum internalformat) OVERRIDE;
+
+virtual void DestroyImageCHROMIUM(GLuint image_id) OVERRIDE;
+
+virtual void GetImageParameterivCHROMIUM(
+ GLuint image_id, GLenum pname, GLint* params) OVERRIDE;
+
virtual void GetTranslatedShaderSourceANGLE(
GLuint shader, GLsizei bufsize, GLsizei* length, char* source) OVERRIDE;
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 4343ca8..7208425 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -401,7 +401,8 @@
NULL,
transfer_buffer_.get(),
shared_resources,
- bind_generates_resource));
+ bind_generates_resource,
+ NULL));
ASSERT_TRUE(gl_->Initialize(
kTransferBufferSize,
kTransferBufferSize,
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index d783468..a93f8eb 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -1643,9 +1643,9 @@
cmds::ResizeCHROMIUM cmd;
};
Cmds expected;
- expected.cmd.Init(1, 2);
+ expected.cmd.Init(1, 2, 3);
- gl_->ResizeCHROMIUM(1, 2);
+ gl_->ResizeCHROMIUM(1, 2, 3);
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
}
// TODO: Implement unit test for GetRequestableExtensionsCHROMIUM
diff --git a/gpu/command_buffer/client/gles2_interface.cc b/gpu/command_buffer/client/gles2_interface.cc
index b09e5f8..a94f167 100644
--- a/gpu/command_buffer/client/gles2_interface.cc
+++ b/gpu/command_buffer/client/gles2_interface.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "../client/gles2_interface.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/client/gles2_interface.h b/gpu/command_buffer/client/gles2_interface.h
index 9fe54a1..d1659bf 100644
--- a/gpu/command_buffer/client/gles2_interface.h
+++ b/gpu/command_buffer/client/gles2_interface.h
@@ -20,7 +20,7 @@
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
// this file instead of having to edit some template or the code generator.
- #include "../client/gles2_interface_autogen.h"
+ #include "gpu/command_buffer/client/gles2_interface_autogen.h"
};
} // namespace gles2
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index 865f7ed..a933b81 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -251,6 +251,8 @@
virtual GLboolean EnableFeatureCHROMIUM(const char* feature) = 0;
virtual void* MapBufferCHROMIUM(GLuint target, GLenum access) = 0;
virtual GLboolean UnmapBufferCHROMIUM(GLuint target) = 0;
+virtual void* MapImageCHROMIUM(GLuint image_id, GLenum access) = 0;
+virtual void UnmapImageCHROMIUM(GLuint image_id) = 0;
virtual void* MapBufferSubDataCHROMIUM(
GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) = 0;
virtual void UnmapBufferSubDataCHROMIUM(const void* mem) = 0;
@@ -258,7 +260,8 @@
GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
GLsizei height, GLenum format, GLenum type, GLenum access) = 0;
virtual void UnmapTexSubImage2DCHROMIUM(const void* mem) = 0;
-virtual void ResizeCHROMIUM(GLuint width, GLuint height) = 0;
+virtual void ResizeCHROMIUM(GLuint width, GLuint height, GLfloat scale_factor) =
+ 0;
virtual const GLchar* GetRequestableExtensionsCHROMIUM() = 0;
virtual void RequestExtensionCHROMIUM(const char* extension) = 0;
virtual void RateLimitOffscreenContextCHROMIUM() = 0;
@@ -268,6 +271,11 @@
GLuint program, GLsizei bufsize, GLsizei* size, void* info) = 0;
virtual GLuint CreateStreamTextureCHROMIUM(GLuint texture) = 0;
virtual void DestroyStreamTextureCHROMIUM(GLuint texture) = 0;
+virtual GLuint CreateImageCHROMIUM(
+ GLsizei width, GLsizei height, GLenum internalformat) = 0;
+virtual void DestroyImageCHROMIUM(GLuint image_id) = 0;
+virtual void GetImageParameterivCHROMIUM(
+ GLuint image_id, GLenum pname, GLint* params) = 0;
virtual void GetTranslatedShaderSourceANGLE(
GLuint shader, GLsizei bufsize, GLsizei* length, char* source) = 0;
virtual void PostSubBufferCHROMIUM(
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 769b260..a16fe5d 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -279,6 +279,8 @@
virtual GLboolean EnableFeatureCHROMIUM(const char* feature) OVERRIDE;
virtual void* MapBufferCHROMIUM(GLuint target, GLenum access) OVERRIDE;
virtual GLboolean UnmapBufferCHROMIUM(GLuint target) OVERRIDE;
+virtual void* MapImageCHROMIUM(GLuint image_id, GLenum access) OVERRIDE;
+virtual void UnmapImageCHROMIUM(GLuint image_id) OVERRIDE;
virtual void* MapBufferSubDataCHROMIUM(
GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) OVERRIDE;
virtual void UnmapBufferSubDataCHROMIUM(const void* mem) OVERRIDE;
@@ -286,7 +288,8 @@
GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
GLsizei height, GLenum format, GLenum type, GLenum access) OVERRIDE;
virtual void UnmapTexSubImage2DCHROMIUM(const void* mem) OVERRIDE;
-virtual void ResizeCHROMIUM(GLuint width, GLuint height) OVERRIDE;
+virtual void ResizeCHROMIUM(
+ GLuint width, GLuint height, GLfloat scale_factor) OVERRIDE;
virtual const GLchar* GetRequestableExtensionsCHROMIUM() OVERRIDE;
virtual void RequestExtensionCHROMIUM(const char* extension) OVERRIDE;
virtual void RateLimitOffscreenContextCHROMIUM() OVERRIDE;
@@ -297,6 +300,11 @@
GLuint program, GLsizei bufsize, GLsizei* size, void* info) OVERRIDE;
virtual GLuint CreateStreamTextureCHROMIUM(GLuint texture) OVERRIDE;
virtual void DestroyStreamTextureCHROMIUM(GLuint texture) OVERRIDE;
+virtual GLuint CreateImageCHROMIUM(
+ GLsizei width, GLsizei height, GLenum internalformat) OVERRIDE;
+virtual void DestroyImageCHROMIUM(GLuint image_id) OVERRIDE;
+virtual void GetImageParameterivCHROMIUM(
+ GLuint image_id, GLenum pname, GLint* params) OVERRIDE;
virtual void GetTranslatedShaderSourceANGLE(
GLuint shader, GLsizei bufsize, GLsizei* length, char* source) OVERRIDE;
virtual void PostSubBufferCHROMIUM(
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index b1c4ac5..ce4b53b 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -527,6 +527,12 @@
GLboolean GLES2InterfaceStub::UnmapBufferCHROMIUM(GLuint /* target */) {
return 0;
}
+void* GLES2InterfaceStub::MapImageCHROMIUM(
+ GLuint /* image_id */, GLenum /* access */) {
+ return 0;
+}
+void GLES2InterfaceStub::UnmapImageCHROMIUM(GLuint /* image_id */) {
+}
void* GLES2InterfaceStub::MapBufferSubDataCHROMIUM(
GLuint /* target */, GLintptr /* offset */, GLsizeiptr /* size */,
GLenum /* access */) {
@@ -543,7 +549,7 @@
void GLES2InterfaceStub::UnmapTexSubImage2DCHROMIUM(const void* /* mem */) {
}
void GLES2InterfaceStub::ResizeCHROMIUM(
- GLuint /* width */, GLuint /* height */) {
+ GLuint /* width */, GLuint /* height */, GLfloat /* scale_factor */) {
}
const GLchar* GLES2InterfaceStub::GetRequestableExtensionsCHROMIUM() {
return 0;
@@ -566,6 +572,15 @@
}
void GLES2InterfaceStub::DestroyStreamTextureCHROMIUM(GLuint /* texture */) {
}
+GLuint GLES2InterfaceStub::CreateImageCHROMIUM(
+ GLsizei /* width */, GLsizei /* height */, GLenum /* internalformat */) {
+ return 0;
+}
+void GLES2InterfaceStub::DestroyImageCHROMIUM(GLuint /* image_id */) {
+}
+void GLES2InterfaceStub::GetImageParameterivCHROMIUM(
+ GLuint /* image_id */, GLenum /* pname */, GLint* /* params */) {
+}
void GLES2InterfaceStub::GetTranslatedShaderSourceANGLE(
GLuint /* shader */, GLsizei /* bufsize */, GLsizei* /* length */,
char* /* source */) {
diff --git a/gpu/command_buffer/client/gles2_lib.cc b/gpu/command_buffer/client/gles2_lib.cc
index e7b11e8..6c8b0ea 100644
--- a/gpu/command_buffer/client/gles2_lib.cc
+++ b/gpu/command_buffer/client/gles2_lib.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "../client/gles2_lib.h"
+#include "gpu/command_buffer/client/gles2_lib.h"
#include <string.h>
-#include "../common/thread_local.h"
+#include "gpu/command_buffer/common/thread_local.h"
namespace gles2 {
diff --git a/gpu/command_buffer/client/gles2_lib.h b/gpu/command_buffer/client/gles2_lib.h
index 2cad3f1..b90a2d8 100644
--- a/gpu/command_buffer/client/gles2_lib.h
+++ b/gpu/command_buffer/client/gles2_lib.h
@@ -7,8 +7,8 @@
#ifndef GPU_COMMAND_BUFFER_CLIENT_GLES2_LIB_H_
#define GPU_COMMAND_BUFFER_CLIENT_GLES2_LIB_H_
-#include "../client/gles2_interface.h"
#include "gpu/command_buffer/client/gles2_c_lib_export.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
namespace gles2 {
diff --git a/gpu/command_buffer/client/gles2_trace_implementation.cc b/gpu/command_buffer/client/gles2_trace_implementation.cc
index 2497342..234f243 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation.cc
+++ b/gpu/command_buffer/client/gles2_trace_implementation.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "../client/gles2_trace_implementation.h"
-#include "../common/trace_event.h"
+#include "gpu/command_buffer/client/gles2_trace_implementation.h"
+#include "gpu/command_buffer/common/trace_event.h"
namespace gpu {
namespace gles2 {
@@ -18,7 +18,7 @@
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
-#include "../client/gles2_trace_implementation_impl_autogen.h"
+#include "gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h"
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/client/gles2_trace_implementation.h b/gpu/command_buffer/client/gles2_trace_implementation.h
index 0925e22..18e6a79 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation.h
@@ -5,9 +5,9 @@
#ifndef GPU_COMMAND_BUFFER_CLIENT_GLES2_TRACE_IMPLEMENTATION_H_
#define GPU_COMMAND_BUFFER_CLIENT_GLES2_TRACE_IMPLEMENTATION_H_
-#include "../client/gles2_interface.h"
-#include "../common/compiler_specific.h"
#include "gles2_impl_export.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/common/compiler_specific.h"
namespace gpu {
namespace gles2 {
@@ -21,7 +21,7 @@
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
// this file instead of having to edit some template or the code generator.
- #include "../client/gles2_trace_implementation_autogen.h"
+ #include "gpu/command_buffer/client/gles2_trace_implementation_autogen.h"
private:
GLES2Interface* gl_;
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index 7ec9eb6..bef6ce8 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -279,6 +279,8 @@
virtual GLboolean EnableFeatureCHROMIUM(const char* feature) OVERRIDE;
virtual void* MapBufferCHROMIUM(GLuint target, GLenum access) OVERRIDE;
virtual GLboolean UnmapBufferCHROMIUM(GLuint target) OVERRIDE;
+virtual void* MapImageCHROMIUM(GLuint image_id, GLenum access) OVERRIDE;
+virtual void UnmapImageCHROMIUM(GLuint image_id) OVERRIDE;
virtual void* MapBufferSubDataCHROMIUM(
GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) OVERRIDE;
virtual void UnmapBufferSubDataCHROMIUM(const void* mem) OVERRIDE;
@@ -286,7 +288,8 @@
GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
GLsizei height, GLenum format, GLenum type, GLenum access) OVERRIDE;
virtual void UnmapTexSubImage2DCHROMIUM(const void* mem) OVERRIDE;
-virtual void ResizeCHROMIUM(GLuint width, GLuint height) OVERRIDE;
+virtual void ResizeCHROMIUM(
+ GLuint width, GLuint height, GLfloat scale_factor) OVERRIDE;
virtual const GLchar* GetRequestableExtensionsCHROMIUM() OVERRIDE;
virtual void RequestExtensionCHROMIUM(const char* extension) OVERRIDE;
virtual void RateLimitOffscreenContextCHROMIUM() OVERRIDE;
@@ -297,6 +300,11 @@
GLuint program, GLsizei bufsize, GLsizei* size, void* info) OVERRIDE;
virtual GLuint CreateStreamTextureCHROMIUM(GLuint texture) OVERRIDE;
virtual void DestroyStreamTextureCHROMIUM(GLuint texture) OVERRIDE;
+virtual GLuint CreateImageCHROMIUM(
+ GLsizei width, GLsizei height, GLenum internalformat) OVERRIDE;
+virtual void DestroyImageCHROMIUM(GLuint image_id) OVERRIDE;
+virtual void GetImageParameterivCHROMIUM(
+ GLuint image_id, GLenum pname, GLint* params) OVERRIDE;
virtual void GetTranslatedShaderSourceANGLE(
GLuint shader, GLsizei bufsize, GLsizei* length, char* source) OVERRIDE;
virtual void PostSubBufferCHROMIUM(
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
index 0471880..a99a36a 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -978,6 +978,17 @@
return gl_->UnmapBufferCHROMIUM(target);
}
+void* GLES2TraceImplementation::MapImageCHROMIUM(
+ GLuint image_id, GLenum access) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::MapImageCHROMIUM");
+ return gl_->MapImageCHROMIUM(image_id, access);
+}
+
+void GLES2TraceImplementation::UnmapImageCHROMIUM(GLuint image_id) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::UnmapImageCHROMIUM");
+ gl_->UnmapImageCHROMIUM(image_id);
+}
+
void* GLES2TraceImplementation::MapBufferSubDataCHROMIUM(
GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::MapBufferSubDataCHROMIUM");
@@ -1002,9 +1013,10 @@
gl_->UnmapTexSubImage2DCHROMIUM(mem);
}
-void GLES2TraceImplementation::ResizeCHROMIUM(GLuint width, GLuint height) {
+void GLES2TraceImplementation::ResizeCHROMIUM(
+ GLuint width, GLuint height, GLfloat scale_factor) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::ResizeCHROMIUM");
- gl_->ResizeCHROMIUM(width, height);
+ gl_->ResizeCHROMIUM(width, height, scale_factor);
}
const GLchar* GLES2TraceImplementation::GetRequestableExtensionsCHROMIUM() {
@@ -1045,6 +1057,23 @@
gl_->DestroyStreamTextureCHROMIUM(texture);
}
+GLuint GLES2TraceImplementation::CreateImageCHROMIUM(
+ GLsizei width, GLsizei height, GLenum internalformat) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CreateImageCHROMIUM");
+ return gl_->CreateImageCHROMIUM(width, height, internalformat);
+}
+
+void GLES2TraceImplementation::DestroyImageCHROMIUM(GLuint image_id) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DestroyImageCHROMIUM");
+ gl_->DestroyImageCHROMIUM(image_id);
+}
+
+void GLES2TraceImplementation::GetImageParameterivCHROMIUM(
+ GLuint image_id, GLenum pname, GLint* params) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetImageParameterivCHROMIUM"); // NOLINT
+ gl_->GetImageParameterivCHROMIUM(image_id, pname, params);
+}
+
void GLES2TraceImplementation::GetTranslatedShaderSourceANGLE(
GLuint shader, GLsizei bufsize, GLsizei* length, char* source) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetTranslatedShaderSourceANGLE"); // NOLINT
diff --git a/gpu/command_buffer/client/gpu_memory_buffer.h b/gpu/command_buffer/client/gpu_memory_buffer.h
index 14e95ee..480eb89 100644
--- a/gpu/command_buffer/client/gpu_memory_buffer.h
+++ b/gpu/command_buffer/client/gpu_memory_buffer.h
@@ -6,7 +6,6 @@
#define GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_H_
#include "base/basictypes.h"
-#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "gles2_impl_export.h"
@@ -23,11 +22,10 @@
// behavior and is not allowed.
class GLES2_IMPL_EXPORT GpuMemoryBuffer {
public:
- typedef base::Callback<scoped_ptr<GpuMemoryBuffer>(int, int)> Creator;
enum AccessMode {
READ_ONLY,
WRITE_ONLY,
- READ_OR_WRITE,
+ READ_WRITE,
};
// Frees a previously allocated buffer. Freeing a buffer that is still
diff --git a/gpu/command_buffer/client/gpu_memory_buffer_factory.cc b/gpu/command_buffer/client/gpu_memory_buffer_factory.cc
deleted file mode 100644
index c0e5b9f..0000000
--- a/gpu/command_buffer/client/gpu_memory_buffer_factory.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gpu/command_buffer/client/gpu_memory_buffer_factory.h"
-
-#include "base/logging.h"
-
-namespace gpu {
-
-namespace {
-GpuMemoryBuffer::Creator* g_gpu_memory_buffer_factory_ = NULL;
-}
-
-const GpuMemoryBuffer::Creator& GetProcessDefaultGpuMemoryBufferFactory() {
- return *g_gpu_memory_buffer_factory_;
-}
-
-void SetProcessDefaultGpuMemoryBufferFactory(
- const GpuMemoryBuffer::Creator& factory) {
- DCHECK(g_gpu_memory_buffer_factory_ == NULL);
- g_gpu_memory_buffer_factory_ = new GpuMemoryBuffer::Creator(factory);
-}
-
-} // namespace gpu
diff --git a/gpu/command_buffer/client/gpu_memory_buffer_factory.h b/gpu/command_buffer/client/gpu_memory_buffer_factory.h
deleted file mode 100644
index dd10a7d..0000000
--- a/gpu/command_buffer/client/gpu_memory_buffer_factory.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_FACTORY_H_
-#define GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_FACTORY_H_
-
-#include "gles2_impl_export.h"
-#include "gpu/command_buffer/client/gpu_memory_buffer.h"
-
-namespace gpu {
-
-// Getter and setter for a GpuMemoryBuffer factory for the current process.
-// Currently it is only used for Android Webview where both browser and
-// renderer are within the same process.
-
-// It is not valid to call this method before the setter is called.
-GLES2_IMPL_EXPORT const GpuMemoryBuffer::Creator&
- GetProcessDefaultGpuMemoryBufferFactory();
-
-// It is illegal to call the setter more than once.
-GLES2_IMPL_EXPORT void SetProcessDefaultGpuMemoryBufferFactory(
- const GpuMemoryBuffer::Creator& factory);
-
-} // namespace gpu
-
-#endif // GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_FACTORY_H_
diff --git a/gpu/command_buffer/client/gpu_memory_buffer_mock.cc b/gpu/command_buffer/client/gpu_memory_buffer_mock.cc
new file mode 100644
index 0000000..289b0fe
--- /dev/null
+++ b/gpu/command_buffer/client/gpu_memory_buffer_mock.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/client/gpu_memory_buffer_mock.h"
+
+namespace gpu {
+
+GpuMemoryBufferMock::GpuMemoryBufferMock(int width, int height) {
+}
+
+GpuMemoryBufferMock::~GpuMemoryBufferMock() {
+ Die();
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/client/gpu_memory_buffer_mock.h b/gpu/command_buffer/client/gpu_memory_buffer_mock.h
new file mode 100644
index 0000000..6a4db89
--- /dev/null
+++ b/gpu/command_buffer/client/gpu_memory_buffer_mock.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_MOCK_H_
+#define GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_MOCK_H_
+
+#include "gpu/command_buffer/client/gpu_memory_buffer.h"
+#include "base/basictypes.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace gpu {
+
+class GpuMemoryBufferMock : public GpuMemoryBuffer {
+ public:
+ GpuMemoryBufferMock(int width, int height);
+ virtual ~GpuMemoryBufferMock();
+
+ MOCK_METHOD2(Map, void(GpuMemoryBuffer::AccessMode, void**));
+ MOCK_METHOD0(Unmap, void());
+ MOCK_METHOD0(IsMapped, bool());
+ MOCK_METHOD0(GetNativeBuffer, void*());
+ MOCK_METHOD0(GetStride, uint32());
+ MOCK_METHOD0(Die, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferMock);
+};
+
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_MOCK_H_
diff --git a/gpu/command_buffer/client/gpu_memory_buffer_tracker.cc b/gpu/command_buffer/client/gpu_memory_buffer_tracker.cc
new file mode 100644
index 0000000..894898b
--- /dev/null
+++ b/gpu/command_buffer/client/gpu_memory_buffer_tracker.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/client/gpu_memory_buffer_tracker.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer.h"
+#include "gpu/command_buffer/client/image_factory.h"
+
+namespace gpu {
+namespace gles2 {
+
+GpuMemoryBufferTracker::GpuMemoryBufferTracker(ImageFactory* factory)
+ : buffers_(),
+ factory_(factory) {
+}
+
+GpuMemoryBufferTracker::~GpuMemoryBufferTracker() {
+ while (!buffers_.empty()) {
+ RemoveBuffer(buffers_.begin()->first);
+ }
+}
+
+GLuint GpuMemoryBufferTracker::CreateBuffer(
+ GLsizei width, GLsizei height, GLenum internalformat) {
+ GLuint image_id = 0;
+ DCHECK(factory_);
+ scoped_ptr<GpuMemoryBuffer> buffer =
+ factory_->CreateGpuMemoryBuffer(width, height, internalformat, &image_id);
+
+ if (buffer.get() == NULL)
+ return 0;
+
+ std::pair<BufferMap::iterator, bool> result =
+ buffers_.insert(std::make_pair(image_id, buffer.release()));
+ GPU_DCHECK(result.second);
+
+ return image_id;
+}
+
+GpuMemoryBuffer* GpuMemoryBufferTracker::GetBuffer(GLuint image_id) {
+ BufferMap::iterator it = buffers_.find(image_id);
+ return (it != buffers_.end()) ? it->second : NULL;
+}
+
+void GpuMemoryBufferTracker::RemoveBuffer(GLuint image_id) {
+ BufferMap::iterator buffer_it = buffers_.find(image_id);
+ if (buffer_it != buffers_.end()) {
+ GpuMemoryBuffer* buffer = buffer_it->second;
+ buffers_.erase(buffer_it);
+ delete buffer;
+ }
+ DCHECK(factory_);
+ factory_->DeleteGpuMemoryBuffer(image_id);
+}
+
+} // namespace gles2
+} // namespace gpu
diff --git a/gpu/command_buffer/client/gpu_memory_buffer_tracker.h b/gpu/command_buffer/client/gpu_memory_buffer_tracker.h
new file mode 100644
index 0000000..f2f6e9f
--- /dev/null
+++ b/gpu/command_buffer/client/gpu_memory_buffer_tracker.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_TRACKER_H_
+#define GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_TRACKER_H_
+
+#include <GLES2/gl2.h>
+
+#include "base/basictypes.h"
+#include "gles2_impl_export.h"
+#include "gpu/command_buffer/client/hash_tables.h"
+
+namespace gpu {
+class GpuMemoryBuffer;
+
+namespace gles2 {
+class ImageFactory;
+
+// Tracks GPU memory buffer objects on the client side.
+class GLES2_IMPL_EXPORT GpuMemoryBufferTracker {
+ public:
+ // Ownership of |factory| remains with caller.
+ explicit GpuMemoryBufferTracker(ImageFactory* factory);
+ virtual ~GpuMemoryBufferTracker();
+
+ GLuint CreateBuffer(
+ GLsizei width, GLsizei height, GLenum internalformat);
+ GpuMemoryBuffer* GetBuffer(GLuint image_id);
+ void RemoveBuffer(GLuint image_id);
+
+ private:
+ typedef gpu::hash_map<GLuint, GpuMemoryBuffer*> BufferMap;
+ BufferMap buffers_;
+ ImageFactory* factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferTracker);
+};
+
+} // namespace gles2
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_TRACKER_H_
diff --git a/gpu/command_buffer/client/image_factory.h b/gpu/command_buffer/client/image_factory.h
new file mode 100644
index 0000000..b752cb1
--- /dev/null
+++ b/gpu/command_buffer/client/image_factory.h
@@ -0,0 +1,33 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_H_
+#define GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_H_
+
+#include <GLES2/gl2.h>
+
+#include "base/memory/scoped_ptr.h"
+#include "gles2_impl_export.h"
+
+namespace gpu {
+class GpuMemoryBuffer;
+
+namespace gles2 {
+
+class GLES2_IMPL_EXPORT ImageFactory {
+
+ public:
+ virtual ~ImageFactory() {}
+
+ // Create a GpuMemoryBuffer and makes it available to the
+ // service side by inserting it to the ImageManager.
+ virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer(
+ int width, int height, GLenum internalformat, unsigned* image_id) = 0;
+ virtual void DeleteGpuMemoryBuffer(unsigned image_id) = 0;
+};
+
+} // namespace gles2
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_H_
diff --git a/gpu/command_buffer/client/image_factory_mock.cc b/gpu/command_buffer/client/image_factory_mock.cc
new file mode 100644
index 0000000..d167cee
--- /dev/null
+++ b/gpu/command_buffer/client/image_factory_mock.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/client/image_factory_mock.h"
+
+namespace gpu {
+namespace gles2 {
+
+ImageFactoryMock::ImageFactoryMock(ImageManager* manager) {
+}
+
+ImageFactoryMock::~ImageFactoryMock() {
+}
+
+} // namespace gles2
+} // namespace gpu
diff --git a/gpu/command_buffer/client/image_factory_mock.h b/gpu/command_buffer/client/image_factory_mock.h
new file mode 100644
index 0000000..2516d69
--- /dev/null
+++ b/gpu/command_buffer/client/image_factory_mock.h
@@ -0,0 +1,41 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_MOCK_H_
+#define GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_MOCK_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer.h"
+#include "gpu/command_buffer/client/image_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace gpu {
+namespace gles2 {
+class ImageManager;
+
+// Mock implementation of ImageFactory
+class ImageFactoryMock : public ImageFactory {
+ public:
+ ImageFactoryMock(ImageManager* image_manager);
+ virtual ~ImageFactoryMock();
+
+ MOCK_METHOD4(CreateGpuMemoryBufferMock, GpuMemoryBuffer*(
+ int width, int height, GLenum internalformat, unsigned* image_id));
+ MOCK_METHOD1(DeleteGpuMemoryBuffer, void(unsigned));
+ // Workaround for mocking methods that return scoped_ptrs
+ virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer(
+ int width, int height, GLenum internalformat,
+ unsigned* image_id) OVERRIDE {
+ return scoped_ptr<GpuMemoryBuffer>(CreateGpuMemoryBufferMock(
+ width, height, internalformat, image_id));
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ImageFactoryMock);
+};
+
+} // namespace gles2
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_MOCK_H_
diff --git a/gpu/command_buffer/client/mapped_memory.cc b/gpu/command_buffer/client/mapped_memory.cc
index 8e51801..34a6c5c 100644
--- a/gpu/command_buffer/client/mapped_memory.cc
+++ b/gpu/command_buffer/client/mapped_memory.cc
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "gpu/command_buffer/client/mapped_memory.h"
+
#include <algorithm>
#include <functional>
-#include "../client/mapped_memory.h"
-#include "../client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/mapped_memory.h b/gpu/command_buffer/client/mapped_memory.h
index 93390a7..2dfef72 100644
--- a/gpu/command_buffer/client/mapped_memory.h
+++ b/gpu/command_buffer/client/mapped_memory.h
@@ -7,10 +7,10 @@
#include <vector>
-#include "../../gpu_export.h"
-#include "../common/types.h"
-#include "../client/fenced_allocator.h"
-#include "../common/buffer.h"
+#include "gpu/command_buffer/client/fenced_allocator.h"
+#include "gpu/command_buffer/common/buffer.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/gpu_export.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc
index 71014ca..fb0c1f3 100644
--- a/gpu/command_buffer/client/program_info_manager.cc
+++ b/gpu/command_buffer/client/program_info_manager.cc
@@ -5,10 +5,10 @@
#include <map>
#include "base/compiler_specific.h"
-#include "../client/program_info_manager.h"
-#include "../client/atomicops.h"
-#include "../client/gles2_implementation.h"
-#include "../common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/client/atomicops.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/program_info_manager.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/client/query_tracker.cc b/gpu/command_buffer/client/query_tracker.cc
index 5356ef5..76ebf72 100644
--- a/gpu/command_buffer/client/query_tracker.cc
+++ b/gpu/command_buffer/client/query_tracker.cc
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "gpu/command_buffer/client/query_tracker.h"
+
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES2/gl2extchromium.h>
-#include "../client/query_tracker.h"
-
-#include "../client/atomicops.h"
-#include "../client/gles2_cmd_helper.h"
-#include "../client/gles2_implementation.h"
-#include "../client/mapped_memory.h"
-#include "../common/time.h"
+#include "gpu/command_buffer/client/atomicops.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/mapped_memory.h"
+#include "gpu/command_buffer/common/time.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/client/query_tracker.h b/gpu/command_buffer/client/query_tracker.h
index 5341ae9..144ae92 100644
--- a/gpu/command_buffer/client/query_tracker.h
+++ b/gpu/command_buffer/client/query_tracker.h
@@ -8,9 +8,9 @@
#include <GLES2/gl2.h>
#include <deque>
-#include "../client/hash_tables.h"
-#include "../common/gles2_cmd_format.h"
#include "gles2_impl_export.h"
+#include "gpu/command_buffer/client/hash_tables.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/ring_buffer.cc b/gpu/command_buffer/client/ring_buffer.cc
index 762f834..46a86a2 100644
--- a/gpu/command_buffer/client/ring_buffer.cc
+++ b/gpu/command_buffer/client/ring_buffer.cc
@@ -4,9 +4,9 @@
// This file contains the implementation of the RingBuffer class.
-#include "../client/ring_buffer.h"
+#include "gpu/command_buffer/client/ring_buffer.h"
#include <algorithm>
-#include "../client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/ring_buffer.h b/gpu/command_buffer/client/ring_buffer.h
index c08cccd..d1f70a2 100644
--- a/gpu/command_buffer/client/ring_buffer.h
+++ b/gpu/command_buffer/client/ring_buffer.h
@@ -9,9 +9,9 @@
#include <deque>
-#include "../../gpu_export.h"
-#include "../common/logging.h"
-#include "../common/types.h"
+#include "gpu/command_buffer/common/logging.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/gpu_export.h"
namespace gpu {
class CommandBufferHelper;
diff --git a/gpu/command_buffer/client/share_group.cc b/gpu/command_buffer/client/share_group.cc
index 041d79d..7ac53f0 100644
--- a/gpu/command_buffer/client/share_group.cc
+++ b/gpu/command_buffer/client/share_group.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "../client/atomicops.h"
-#include "../client/share_group.h"
-#include "../client/gles2_implementation.h"
-#include "../client/program_info_manager.h"
-#include "../common/id_allocator.h"
-#include "../common/logging.h"
+#include "gpu/command_buffer/client/atomicops.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/program_info_manager.h"
+#include "gpu/command_buffer/client/share_group.h"
+#include "gpu/command_buffer/common/id_allocator.h"
+#include "gpu/command_buffer/common/logging.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/client/share_group.h b/gpu/command_buffer/client/share_group.h
index c9e3469..15d141c 100644
--- a/gpu/command_buffer/client/share_group.h
+++ b/gpu/command_buffer/client/share_group.h
@@ -7,9 +7,9 @@
#include <GLES2/gl2.h>
#include "base/memory/scoped_ptr.h"
-#include "../client/ref_counted.h"
-#include "../common/gles2_cmd_format.h"
#include "gles2_impl_export.h"
+#include "gpu/command_buffer/client/ref_counted.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/client/transfer_buffer.cc b/gpu/command_buffer/client/transfer_buffer.cc
index 8348622..f4fe66c 100644
--- a/gpu/command_buffer/client/transfer_buffer.cc
+++ b/gpu/command_buffer/client/transfer_buffer.cc
@@ -4,8 +4,8 @@
// A class to Manage a growing transfer buffer.
-#include "../client/transfer_buffer.h"
-#include "../client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/client/transfer_buffer.h"
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/transfer_buffer.h b/gpu/command_buffer/client/transfer_buffer.h
index 71c09bf..273f017 100644
--- a/gpu/command_buffer/client/transfer_buffer.h
+++ b/gpu/command_buffer/client/transfer_buffer.h
@@ -6,11 +6,11 @@
#define GPU_COMMAND_BUFFER_CLIENT_TRANSFER_BUFFER_H_
#include "base/memory/scoped_ptr.h"
-#include "../../gpu_export.h"
-#include "../common/buffer.h"
-#include "../common/compiler_specific.h"
-#include "../common/gles2_cmd_utils.h"
-#include "../client/ring_buffer.h"
+#include "gpu/command_buffer/client/ring_buffer.h"
+#include "gpu/command_buffer/common/buffer.h"
+#include "gpu/command_buffer/common/compiler_specific.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/gpu_export.h"
namespace gpu {
diff --git a/gpu/command_buffer/client/vertex_array_object_manager.cc b/gpu/command_buffer/client/vertex_array_object_manager.cc
index 4209d06..f2a156e 100644
--- a/gpu/command_buffer/client/vertex_array_object_manager.cc
+++ b/gpu/command_buffer/client/vertex_array_object_manager.cc
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "../client/vertex_array_object_manager.h"
+#include "gpu/command_buffer/client/vertex_array_object_manager.h"
-#include "../client/gles2_cmd_helper.h"
-#include "../client/gles2_implementation.h"
-#include "../common/logging.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/common/logging.h"
#if defined(__native_client__) && !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
#define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS
diff --git a/gpu/command_buffer/client/vertex_array_object_manager.h b/gpu/command_buffer/client/vertex_array_object_manager.h
index dff2131..254b15d 100644
--- a/gpu/command_buffer/client/vertex_array_object_manager.h
+++ b/gpu/command_buffer/client/vertex_array_object_manager.h
@@ -7,9 +7,9 @@
#include <GLES2/gl2.h>
#include "base/memory/scoped_ptr.h"
-#include "../client/hash_tables.h"
-#include "../common/types.h"
#include "gles2_impl_export.h"
+#include "gpu/command_buffer/client/hash_tables.h"
+#include "gpu/command_buffer/common/types.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index 1a9268b..ef56e5a 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -175,12 +175,14 @@
GL_APICALL GLboolean GL_APIENTRY glEnableFeatureCHROMIUM (const char* feature);
GL_APICALL void* GL_APIENTRY glMapBufferCHROMIUM (GLuint target, GLenum access);
GL_APICALL GLboolean GL_APIENTRY glUnmapBufferCHROMIUM (GLuint target);
+GL_APICALL void* GL_APIENTRY glMapImageCHROMIUM (GLuint image_id, GLenum access);
+GL_APICALL void GL_APIENTRY glUnmapImageCHROMIUM (GLuint image_id);
GL_APICALL void* GL_APIENTRY glMapBufferSubDataCHROMIUM (GLuint target, GLintptrNotNegative offset, GLsizeiptr size, GLenum access);
GL_APICALL void GL_APIENTRY glUnmapBufferSubDataCHROMIUM (const void* mem);
GL_APICALL void* GL_APIENTRY glMapTexSubImage2DCHROMIUM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLenum access);
GL_APICALL void GL_APIENTRY glUnmapTexSubImage2DCHROMIUM (const void* mem);
-GL_APICALL void GL_APIENTRY glResizeCHROMIUM (GLuint width, GLuint height);
+GL_APICALL void GL_APIENTRY glResizeCHROMIUM (GLuint width, GLuint height, GLfloat scale_factor);
GL_APICALL const GLchar* GL_APIENTRY glGetRequestableExtensionsCHROMIUM (void);
GL_APICALL void GL_APIENTRY glRequestExtensionCHROMIUM (const char* extension);
GL_APICALL void GL_APIENTRY glRateLimitOffscreenContextCHROMIUM (void);
@@ -188,6 +190,9 @@
GL_APICALL void GL_APIENTRY glGetProgramInfoCHROMIUM (GLidProgram program, GLsizeiNotNegative bufsize, GLsizei* size, void* info);
GL_APICALL GLuint GL_APIENTRY glCreateStreamTextureCHROMIUM (GLuint texture);
GL_APICALL void GL_APIENTRY glDestroyStreamTextureCHROMIUM (GLuint texture);
+GL_APICALL GLuint GL_APIENTRY glCreateImageCHROMIUM (GLsizei width, GLsizei height, GLenum internalformat);
+GL_APICALL void GL_APIENTRY glDestroyImageCHROMIUM (GLuint image_id);
+GL_APICALL void GL_APIENTRY glGetImageParameterivCHROMIUM (GLuint image_id, GLenum pname, GLint* params);
GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLidShader shader, GLsizeiNotNegative bufsize, GLsizeiOptional* length, char* source);
GL_APICALL void GL_APIENTRY glPostSubBufferCHROMIUM (GLint x, GLint y, GLint width, GLint height);
GL_APICALL void GL_APIENTRY glTexImageIOSurface2DCHROMIUM (GLenumTextureBindTarget target, GLsizei width, GLsizei height, GLuint ioSurfaceId, GLuint plane);
diff --git a/gpu/command_buffer/common/buffer.h b/gpu/command_buffer/common/buffer.h
index 730053a..a2721a8 100644
--- a/gpu/command_buffer/common/buffer.h
+++ b/gpu/command_buffer/common/buffer.h
@@ -5,7 +5,7 @@
#ifndef GPU_COMMAND_BUFFER_COMMON_BUFFER_H_
#define GPU_COMMAND_BUFFER_COMMON_BUFFER_H_
-#include "../common/types.h"
+#include "gpu/command_buffer/common/types.h"
namespace base {
class SharedMemory;
diff --git a/gpu/command_buffer/common/cmd_buffer_common.cc b/gpu/command_buffer/common/cmd_buffer_common.cc
index 235cc5d..bfa625c 100644
--- a/gpu/command_buffer/common/cmd_buffer_common.cc
+++ b/gpu/command_buffer/common/cmd_buffer_common.cc
@@ -5,9 +5,9 @@
// This file contains the binary format definition of the command buffer and
// command buffer commands.
-#include "../common/cmd_buffer_common.h"
-#include "../common/command_buffer.h"
-#include "../common/logging.h"
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/command_buffer/common/logging.h"
namespace gpu {
#if !defined(_WIN32)
diff --git a/gpu/command_buffer/common/cmd_buffer_common.h b/gpu/command_buffer/common/cmd_buffer_common.h
index 5a87c40..0908198 100644
--- a/gpu/command_buffer/common/cmd_buffer_common.h
+++ b/gpu/command_buffer/common/cmd_buffer_common.h
@@ -9,10 +9,10 @@
#include <stddef.h>
-#include "../../gpu_export.h"
-#include "../common/types.h"
-#include "../common/bitfield_helpers.h"
-#include "../common/logging.h"
+#include "gpu/command_buffer/common/bitfield_helpers.h"
+#include "gpu/command_buffer/common/logging.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/gpu_export.h"
namespace gpu {
diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h
index 8c202ed..3078bca 100644
--- a/gpu/command_buffer/common/command_buffer.h
+++ b/gpu/command_buffer/common/command_buffer.h
@@ -5,9 +5,9 @@
#ifndef GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_H_
#define GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_H_
-#include "../../gpu_export.h"
-#include "../common/buffer.h"
-#include "../common/constants.h"
+#include "gpu/command_buffer/common/buffer.h"
+#include "gpu/command_buffer/common/constants.h"
+#include "gpu/gpu_export.h"
namespace base {
class SharedMemory;
@@ -18,10 +18,6 @@
// Common interface for CommandBuffer implementations.
class GPU_EXPORT CommandBuffer {
public:
- enum {
- kMaxCommandBufferSize = 4 * 1024 * 1024
- };
-
struct State {
State()
: num_entries(0),
diff --git a/gpu/command_buffer/common/command_buffer_mock.h b/gpu/command_buffer/common/command_buffer_mock.h
index d02da47..0e78b7b 100644
--- a/gpu/command_buffer/common/command_buffer_mock.h
+++ b/gpu/command_buffer/common/command_buffer_mock.h
@@ -5,7 +5,7 @@
#ifndef GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_MOCK_H_
#define GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_MOCK_H_
-#include "../common/command_buffer.h"
+#include "gpu/command_buffer/common/command_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace base {
diff --git a/gpu/command_buffer/common/constants.h b/gpu/command_buffer/common/constants.h
index 491f443..ab25987 100644
--- a/gpu/command_buffer/common/constants.h
+++ b/gpu/command_buffer/common/constants.h
@@ -5,7 +5,7 @@
#ifndef GPU_COMMAND_BUFFER_COMMON_CONSTANTS_H_
#define GPU_COMMAND_BUFFER_COMMON_CONSTANTS_H_
-#include "../common/types.h"
+#include "gpu/command_buffer/common/types.h"
namespace gpu {
diff --git a/gpu/command_buffer/common/debug_marker_manager.h b/gpu/command_buffer/common/debug_marker_manager.h
index d7f8389..65e0cd0 100644
--- a/gpu/command_buffer/common/debug_marker_manager.h
+++ b/gpu/command_buffer/common/debug_marker_manager.h
@@ -7,7 +7,7 @@
#include <stack>
#include <string>
-#include "../../gpu_export.h"
+#include "gpu/gpu_export.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/common/gles2_cmd_format.cc b/gpu/command_buffer/common/gles2_cmd_format.cc
index fabdf79..5b437a5 100644
--- a/gpu/command_buffer/common/gles2_cmd_format.cc
+++ b/gpu/command_buffer/common/gles2_cmd_format.cc
@@ -7,12 +7,12 @@
// We explicitly do NOT include gles2_cmd_format.h here because client side
// and service side have different requirements.
-#include "../common/cmd_buffer_common.h"
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
namespace gpu {
namespace gles2 {
-#include "../common/gles2_cmd_ids_autogen.h"
+#include "gpu/command_buffer/common/gles2_cmd_ids_autogen.h"
const char* GetCommandName(CommandId id) {
static const char* const names[] = {
diff --git a/gpu/command_buffer/common/gles2_cmd_format.h b/gpu/command_buffer/common/gles2_cmd_format.h
index 9491d98..76bb3fe 100644
--- a/gpu/command_buffer/common/gles2_cmd_format.h
+++ b/gpu/command_buffer/common/gles2_cmd_format.h
@@ -13,10 +13,10 @@
#include <string.h>
#include "base/safe_numerics.h"
-#include "../common/types.h"
-#include "../common/bitfield_helpers.h"
-#include "../common/cmd_buffer_common.h"
-#include "../common/gles2_cmd_ids.h"
+#include "gpu/command_buffer/common/bitfield_helpers.h"
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
+#include "gpu/command_buffer/common/gles2_cmd_ids.h"
+#include "gpu/command_buffer/common/types.h"
// GL types are forward declared to avoid including the GL headers. The problem
// is determining which GL headers to include from code that is common to the
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 2e2b736..12fc743 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -9449,30 +9449,34 @@
header.SetCmd<ValueType>();
}
- void Init(GLuint _width, GLuint _height) {
+ void Init(GLuint _width, GLuint _height, GLfloat _scale_factor) {
SetHeader();
width = _width;
height = _height;
+ scale_factor = _scale_factor;
}
- void* Set(void* cmd, GLuint _width, GLuint _height) {
- static_cast<ValueType*>(cmd)->Init(_width, _height);
+ void* Set(void* cmd, GLuint _width, GLuint _height, GLfloat _scale_factor) {
+ static_cast<ValueType*>(cmd)->Init(_width, _height, _scale_factor);
return NextCmdAddress<ValueType>(cmd);
}
gpu::CommandHeader header;
uint32 width;
uint32 height;
+ float scale_factor;
};
-COMPILE_ASSERT(sizeof(ResizeCHROMIUM) == 12,
- Sizeof_ResizeCHROMIUM_is_not_12);
+COMPILE_ASSERT(sizeof(ResizeCHROMIUM) == 16,
+ Sizeof_ResizeCHROMIUM_is_not_16);
COMPILE_ASSERT(offsetof(ResizeCHROMIUM, header) == 0,
OffsetOf_ResizeCHROMIUM_header_not_0);
COMPILE_ASSERT(offsetof(ResizeCHROMIUM, width) == 4,
OffsetOf_ResizeCHROMIUM_width_not_4);
COMPILE_ASSERT(offsetof(ResizeCHROMIUM, height) == 8,
OffsetOf_ResizeCHROMIUM_height_not_8);
+COMPILE_ASSERT(offsetof(ResizeCHROMIUM, scale_factor) == 12,
+ OffsetOf_ResizeCHROMIUM_scale_factor_not_12);
struct GetRequestableExtensionsCHROMIUM {
typedef GetRequestableExtensionsCHROMIUM ValueType;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index e11bc47..b23b569 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -3706,12 +3706,14 @@
void* next_cmd = cmd.Set(
&cmd,
static_cast<GLuint>(11),
- static_cast<GLuint>(12));
+ static_cast<GLuint>(12),
+ static_cast<GLfloat>(13));
EXPECT_EQ(static_cast<uint32>(cmds::ResizeCHROMIUM::kCmdId),
cmd.header.command);
EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
EXPECT_EQ(static_cast<GLuint>(11), cmd.width);
EXPECT_EQ(static_cast<GLuint>(12), cmd.height);
+ EXPECT_EQ(static_cast<GLfloat>(13), cmd.scale_factor);
CheckBytesWrittenMatchesExpectedSize(
next_cmd, sizeof(cmd));
}
diff --git a/gpu/command_buffer/common/gles2_cmd_ids.h b/gpu/command_buffer/common/gles2_cmd_ids.h
index f5dfae3..b701c91 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids.h
@@ -7,12 +7,12 @@
#ifndef GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_IDS_H_
#define GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_IDS_H_
-#include "../common/cmd_buffer_common.h"
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
namespace gpu {
namespace gles2 {
-#include "../common/gles2_cmd_ids_autogen.h"
+#include "gpu/command_buffer/common/gles2_cmd_ids_autogen.h"
const char* GetCommandName(CommandId command_id);
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index 7bbed41..ef0f3ea 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -10,8 +10,8 @@
#include <GLES2/gl2ext.h>
#include <GLES2/gl2extchromium.h>
-#include "../common/gles2_cmd_utils.h"
-#include "../common/gles2_cmd_format.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
namespace gpu {
namespace gles2 {
@@ -798,7 +798,7 @@
return true;
}
-#include "../common/gles2_cmd_utils_implementation_autogen.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h"
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index 525a560..b821600 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -12,8 +12,8 @@
#include <string>
#include <vector>
-#include "../common/types.h"
#include "gpu/command_buffer/common/gles2_utils_export.h"
+#include "gpu/command_buffer/common/types.h"
namespace gpu {
namespace gles2 {
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
index e78db86..1db8acf 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -41,6 +41,7 @@
{ 0x0003, "GL_LINE_STRIP", },
{ 0x0000, "GL_POINTS", },
{ 0x0001, "GL_LINES", },
+ { 0x78F0, "GL_IMAGE_ROWBYTES_CHROMIUM", },
{ 0x88B8, "GL_READ_ONLY", },
{ 0x88B9, "GL_WRITE_ONLY_OES", },
{ 0x8211, "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT", },
diff --git a/gpu/command_buffer/common/id_allocator.cc b/gpu/command_buffer/common/id_allocator.cc
index e3fbdd5..b881e05 100644
--- a/gpu/command_buffer/common/id_allocator.cc
+++ b/gpu/command_buffer/common/id_allocator.cc
@@ -4,8 +4,8 @@
// This file contains the implementation of IdAllocator.
-#include "../common/id_allocator.h"
-#include "../common/logging.h"
+#include "gpu/command_buffer/common/id_allocator.h"
+#include "gpu/command_buffer/common/logging.h"
namespace gpu {
diff --git a/gpu/command_buffer/common/id_allocator.h b/gpu/command_buffer/common/id_allocator.h
index 7e25dbb..46fcd1a 100644
--- a/gpu/command_buffer/common/id_allocator.h
+++ b/gpu/command_buffer/common/id_allocator.h
@@ -11,9 +11,8 @@
#include <utility>
#include "base/compiler_specific.h"
-
-#include "../../gpu_export.h"
-#include "../common/types.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/gpu_export.h"
namespace gpu {
diff --git a/gpu/command_buffer/common/mailbox.cc b/gpu/command_buffer/common/mailbox.cc
index c47a9fd..653d1d6 100644
--- a/gpu/command_buffer/common/mailbox.cc
+++ b/gpu/command_buffer/common/mailbox.cc
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "../common/mailbox.h"
+#include "gpu/command_buffer/common/mailbox.h"
#include <string.h>
-#include "../common/logging.h"
+#include "gpu/command_buffer/common/logging.h"
namespace gpu {
diff --git a/gpu/command_buffer/common/mailbox.h b/gpu/command_buffer/common/mailbox.h
index c0ae06f..ca24a71 100644
--- a/gpu/command_buffer/common/mailbox.h
+++ b/gpu/command_buffer/common/mailbox.h
@@ -5,8 +5,8 @@
#ifndef GPU_COMMAND_BUFFER_MAILBOX_H_
#define GPU_COMMAND_BUFFER_MAILBOX_H_
-#include "../../gpu_export.h"
-#include "../common/types.h"
+#include "gpu/command_buffer/common/types.h"
+#include "gpu/gpu_export.h"
namespace gpu {
diff --git a/gpu/command_buffer/gles2_utils.target.darwin-arm.mk b/gpu/command_buffer/gles2_utils.target.darwin-arm.mk
index 525cd2f..c23333a 100644
--- a/gpu/command_buffer/gles2_utils.target.darwin-arm.mk
+++ b/gpu/command_buffer/gles2_utils.target.darwin-arm.mk
@@ -69,6 +69,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -95,9 +96,9 @@
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
$(LOCAL_PATH) \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer/gles2_utils.target.darwin-x86.mk b/gpu/command_buffer/gles2_utils.target.darwin-x86.mk
index ac8efd1..97863b8 100644
--- a/gpu/command_buffer/gles2_utils.target.darwin-x86.mk
+++ b/gpu/command_buffer/gles2_utils.target.darwin-x86.mk
@@ -71,6 +71,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -97,9 +98,9 @@
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
$(LOCAL_PATH) \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer/gles2_utils.target.linux-arm.mk b/gpu/command_buffer/gles2_utils.target.linux-arm.mk
index 525cd2f..c23333a 100644
--- a/gpu/command_buffer/gles2_utils.target.linux-arm.mk
+++ b/gpu/command_buffer/gles2_utils.target.linux-arm.mk
@@ -69,6 +69,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -95,9 +96,9 @@
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
$(LOCAL_PATH) \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer/gles2_utils.target.linux-x86.mk b/gpu/command_buffer/gles2_utils.target.linux-x86.mk
index ac8efd1..97863b8 100644
--- a/gpu/command_buffer/gles2_utils.target.linux-x86.mk
+++ b/gpu/command_buffer/gles2_utils.target.linux-x86.mk
@@ -71,6 +71,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -97,9 +98,9 @@
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
$(LOCAL_PATH) \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate.cc
index fb63e21..9df9c60 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate.cc
@@ -25,6 +25,25 @@
} // namespace
+AsyncPixelTransferUploadStats::AsyncPixelTransferUploadStats()
+ : texture_upload_count_(0) {}
+
+AsyncPixelTransferUploadStats::~AsyncPixelTransferUploadStats() {}
+
+void AsyncPixelTransferUploadStats::AddUpload(base::TimeDelta transfer_time) {
+ base::AutoLock scoped_lock(lock_);
+ texture_upload_count_++;
+ total_texture_upload_time_ += transfer_time;
+}
+
+int AsyncPixelTransferUploadStats::GetStats(
+ base::TimeDelta* total_texture_upload_time) {
+ base::AutoLock scoped_lock(lock_);
+ if (total_texture_upload_time)
+ *total_texture_upload_time = total_texture_upload_time_;
+ return texture_upload_count_;
+}
+
AsyncPixelTransferState::AsyncPixelTransferState(){}
AsyncPixelTransferState::~AsyncPixelTransferState(){}
@@ -52,4 +71,4 @@
mem_params.shm_data_size);
}
-}// namespace gpu
+} // namespace gpu
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate.h b/gpu/command_buffer/service/async_pixel_transfer_delegate.h
index 75f3ad2..b21a63b 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate.h
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate.h
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
#include "base/time.h"
#include "gpu/gpu_export.h"
#include "ui/gl/gl_bindings.h"
@@ -50,6 +51,26 @@
uint32 shm_data_size;
};
+class AsyncPixelTransferUploadStats
+ : public base::RefCountedThreadSafe<AsyncPixelTransferUploadStats> {
+ public:
+ AsyncPixelTransferUploadStats();
+
+ void AddUpload(base::TimeDelta transfer_time);
+ int GetStats(base::TimeDelta* total_texture_upload_time);
+
+ private:
+ friend class base::RefCountedThreadSafe<AsyncPixelTransferUploadStats>;
+
+ ~AsyncPixelTransferUploadStats();
+
+ int texture_upload_count_;
+ base::TimeDelta total_texture_upload_time_;
+ base::Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferUploadStats);
+};
+
// AsyncPixelTransferState holds the resources required to do async
// transfers on one texture. It should stay alive for the lifetime
// of the texture to allow multiple transfers.
@@ -62,7 +83,6 @@
virtual bool TransferIsInProgress() = 0;
protected:
- friend class base::RefCounted<AsyncPixelTransferState>;
AsyncPixelTransferState();
private:
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_android.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate_android.cc
index 2d834c9..fa29cf6 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_android.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_android.cc
@@ -12,6 +12,16 @@
#include "ui/gl/gl_implementation.h"
namespace gpu {
+namespace {
+
+bool IsBroadcom() {
+ const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
+ if (vendor)
+ return std::string(vendor).find("Broadcom") != std::string::npos;
+ return false;
+}
+
+}
// We only used threaded uploads when we can:
// - Create EGLImages out of OpenGL textures (EGL_KHR_gl_texture_2D_image)
@@ -27,7 +37,8 @@
context->HasExtension("EGL_KHR_image") &&
context->HasExtension("EGL_KHR_image_base") &&
context->HasExtension("EGL_KHR_gl_texture_2D_image") &&
- context->HasExtension("GL_OES_EGL_image")) {
+ context->HasExtension("GL_OES_EGL_image") &&
+ !IsBroadcom()) {
return new AsyncPixelTransferDelegateEGL;
}
LOG(INFO) << "Async pixel transfers not supported";
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.cc
index 6839dda..c56f72a 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.cc
@@ -18,11 +18,6 @@
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/scoped_binders.h"
-#if defined(OS_ANDROID)
-// TODO(epenner): Move thread priorities to base. (crbug.com/170549)
-#include <sys/resource.h>
-#endif
-
namespace gpu {
namespace {
@@ -72,10 +67,22 @@
tex_params.format, tex_params.type, data);
}
+void SetGlParametersForEglImageTexture() {
+ // These params are needed for EGLImage creation to succeed on several
+ // Android devices. I couldn't find this requirement in the EGLImage
+ // extension spec, but several devices fail without it.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
class TransferThread : public base::Thread {
public:
TransferThread() : base::Thread(kAsyncTransferThreadName) {
Start();
+#if defined(OS_ANDROID) || defined(OS_LINUX)
+ SetPriority(base::kThreadPriority_Background);
+#endif
}
virtual ~TransferThread() {
Stop();
@@ -91,13 +98,6 @@
gfx::PreferDiscreteGpu);
bool is_current = context_->MakeCurrent(surface_);
DCHECK(is_current);
-
-#if defined(OS_ANDROID)
- // TODO(epenner): Move thread priorities to base. (crbug.com/170549)
- int nice_value = 10; // Idle priority.
- setpriority(PRIO_PROCESS, base::PlatformThread::CurrentId(), nice_value);
-#endif
-
}
virtual void CleanUp() OVERRIDE {
@@ -130,8 +130,6 @@
return g_transfer_thread.Pointer()->safe_shared_memory_pool();
}
-} // namespace
-
// Class which holds async pixel transfers state (EGLImage).
// The EGLImage is accessed by either thread, but everything
// else accessed only on the main thread.
@@ -164,7 +162,7 @@
DCHECK(texture_id_);
DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_);
- gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_);
+ glBindTexture(GL_TEXTURE_2D, texture_id_);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_);
bind_callback_.Run();
@@ -232,12 +230,110 @@
}
void WaitForTransferCompletion() {
+ TRACE_EVENT0("gpu", "WaitForTransferCompletion");
+ // TODO(backer): Deschedule the channel rather than blocking the main GPU
+ // thread (crbug.com/240265).
transfer_completion_.Wait();
}
+ void PerformAsyncTexImage2D(AsyncTexImage2DParams tex_params,
+ AsyncMemoryParams mem_params,
+ ScopedSafeSharedMemory* safe_shared_memory) {
+ TRACE_EVENT2("gpu",
+ "PerformAsyncTexImage",
+ "width",
+ tex_params.width,
+ "height",
+ tex_params.height);
+ DCHECK(!thread_texture_id_);
+ DCHECK_EQ(0, tex_params.level);
+ DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_);
+
+ void* data =
+ AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params);
+ {
+ TRACE_EVENT0("gpu", "glTexImage2D no data");
+ glGenTextures(1, &thread_texture_id_);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, thread_texture_id_);
+
+ SetGlParametersForEglImageTexture();
+
+ // If we need to use image_preserved, we pass the data with
+ // the allocation. Otherwise we use a NULL allocation to
+ // try to avoid any costs associated with creating the EGLImage.
+ if (use_image_preserved_)
+ DoTexImage2D(tex_params, data);
+ else
+ DoTexImage2D(tex_params, NULL);
+ }
+
+ CreateEglImageOnUploadThread();
+
+ {
+ TRACE_EVENT0("gpu", "glTexSubImage2D with data");
+
+ // If we didn't use image_preserved, we haven't uploaded
+ // the data yet, so we do this with a full texSubImage.
+ if (!use_image_preserved_)
+ DoFullTexSubImage2D(tex_params, data);
+ }
+
+ WaitForLastUpload();
+ MarkAsCompleted();
+
+ DCHECK(CHECK_GL());
+ }
+
+ void PerformAsyncTexSubImage2D(
+ AsyncTexSubImage2DParams tex_params,
+ AsyncMemoryParams mem_params,
+ ScopedSafeSharedMemory* safe_shared_memory,
+ scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) {
+ TRACE_EVENT2("gpu",
+ "PerformAsyncTexSubImage2D",
+ "width",
+ tex_params.width,
+ "height",
+ tex_params.height);
+
+ DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_);
+ DCHECK_EQ(0, tex_params.level);
+
+ void* data =
+ AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params);
+
+ base::TimeTicks begin_time;
+ if (texture_upload_stats)
+ begin_time = base::TimeTicks::HighResNow();
+
+ if (!thread_texture_id_) {
+ TRACE_EVENT0("gpu", "glEGLImageTargetTexture2DOES");
+ glGenTextures(1, &thread_texture_id_);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, thread_texture_id_);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_);
+ } else {
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, thread_texture_id_);
+ }
+ {
+ TRACE_EVENT0("gpu", "glTexSubImage2D");
+ DoTexSubImage2D(tex_params, data);
+ }
+ WaitForLastUpload();
+ MarkAsCompleted();
+
+ DCHECK(CHECK_GL());
+ if (texture_upload_stats) {
+ texture_upload_stats->AddUpload(base::TimeTicks::HighResNow() -
+ begin_time);
+ }
+ }
+
protected:
friend class base::RefCountedThreadSafe<TransferStateInternal>;
- friend class AsyncPixelTransferDelegateEGL;
+ friend class gpu::AsyncPixelTransferDelegateEGL;
static void DeleteTexture(GLuint id) {
glDeleteTextures(1, &id);
@@ -282,38 +378,6 @@
bool use_image_preserved_;
};
-class TextureUploadStats
- : public base::RefCountedThreadSafe<TextureUploadStats> {
- public:
- TextureUploadStats() : texture_upload_count_(0) {}
-
- void AddUpload(base::TimeDelta transfer_time) {
- base::AutoLock scoped_lock(lock_);
- texture_upload_count_++;
- total_texture_upload_time_ += transfer_time;
- }
-
- int GetStats(base::TimeDelta* total_texture_upload_time) {
- base::AutoLock scoped_lock(lock_);
- if (total_texture_upload_time)
- *total_texture_upload_time = total_texture_upload_time_;
- return texture_upload_count_;
- }
-
- private:
- friend class base::RefCountedThreadSafe<TextureUploadStats>;
-
- ~TextureUploadStats() {}
-
- int texture_upload_count_;
- base::TimeDelta total_texture_upload_time_;
- base::Lock lock_;
-
- DISALLOW_COPY_AND_ASSIGN(TextureUploadStats);
-};
-
-namespace {
-
// EGL needs thread-safe ref-counting, so this just wraps
// an internal thread-safe ref-counted state object.
class AsyncTransferStateImpl : public AsyncPixelTransferState {
@@ -350,7 +414,7 @@
is_imagination_ = vendor.find("Imagination") != std::string::npos;
is_qualcomm_ = vendor.find("Qualcomm") != std::string::npos;
// TODO(reveman): Skip this if --enable-gpu-benchmarking is not present.
- texture_upload_stats_ = make_scoped_refptr(new TextureUploadStats);
+ texture_upload_stats_ = make_scoped_refptr(new AsyncPixelTransferUploadStats);
}
AsyncPixelTransferDelegateEGL::~AsyncPixelTransferDelegateEGL() {}
@@ -382,6 +446,8 @@
}
void AsyncPixelTransferDelegateEGL::BindCompletedAsyncTransfers() {
+ scoped_ptr<gfx::ScopedTextureBinder> texture_binder;
+
while(!pending_allocations_.empty()) {
if (!pending_allocations_.front().get()) {
pending_allocations_.pop_front();
@@ -393,6 +459,10 @@
// Terminate early, as all transfers finish in order, currently.
if (state->TransferIsInProgress())
break;
+
+ if (!texture_binder)
+ texture_binder.reset(new gfx::ScopedTextureBinder(GL_TEXTURE_2D, 0));
+
// If the transfer is finished, bind it to the texture
// and remove it from pending list.
state->BindTransfer();
@@ -421,30 +491,21 @@
void AsyncPixelTransferDelegateEGL::WaitForTransferCompletion(
AsyncPixelTransferState* transfer_state) {
- TRACE_EVENT0("gpu", "WaitForTransferCompletion");
scoped_refptr<TransferStateInternal> state =
static_cast<AsyncTransferStateImpl*>(transfer_state)->internal_.get();
DCHECK(state);
DCHECK(state->texture_id_);
if (state->TransferIsInProgress()) {
-#if defined(OS_ANDROID)
- // TODO(epenner): Move thread priorities to base. (crbug.com/170549)
- int default_nice_value = 0; // Default priority.
- int idle_nice_value = 10; // Idle priority.
- setpriority(PRIO_PROCESS,
- g_transfer_thread.Pointer()->thread_id(),
- default_nice_value);
+#if defined(OS_ANDROID) || defined(OS_LINUX)
+ g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Display);
#endif
state->WaitForTransferCompletion();
DCHECK(!state->TransferIsInProgress());
-#if defined(OS_ANDROID)
- // TODO(epenner): Move thread priorities to base. (crbug.com/170549)
- setpriority(PRIO_PROCESS,
- g_transfer_thread.Pointer()->thread_id(),
- idle_nice_value);
+#if defined(OS_ANDROID) || defined(OS_LINUX)
+ g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Background);
#endif
}
}
@@ -482,7 +543,7 @@
// a use-after-free of the raw pixels.
transfer_message_loop_proxy()->PostTask(FROM_HERE,
base::Bind(
- &AsyncPixelTransferDelegateEGL::PerformAsyncTexImage2D,
+ &TransferStateInternal::PerformAsyncTexImage2D,
state,
tex_params,
mem_params,
@@ -525,7 +586,7 @@
// a use-after-free of the raw pixels.
transfer_message_loop_proxy()->PostTask(FROM_HERE,
base::Bind(
- &AsyncPixelTransferDelegateEGL::PerformAsyncTexSubImage2D,
+ &TransferStateInternal::PerformAsyncTexSubImage2D,
state,
tex_params,
mem_params,
@@ -556,17 +617,6 @@
return false;
}
-namespace {
-void SetGlParametersForEglImageTexture() {
- // These params are needed for EGLImage creation to succeed on several
- // Android devices. I couldn't find this requirement in the EGLImage
- // extension spec, but several devices fail without it.
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-}
-} // namespace
-
void AsyncPixelTransferDelegateEGL::PerformNotifyCompletion(
AsyncMemoryParams mem_params,
ScopedSafeSharedMemory* safe_shared_memory,
@@ -577,98 +627,6 @@
callback.Run(safe_mem_params);
}
-void AsyncPixelTransferDelegateEGL::PerformAsyncTexImage2D(
- TransferStateInternal* state,
- AsyncTexImage2DParams tex_params,
- AsyncMemoryParams mem_params,
- ScopedSafeSharedMemory* safe_shared_memory) {
- TRACE_EVENT2("gpu", "PerformAsyncTexImage",
- "width", tex_params.width,
- "height", tex_params.height);
- DCHECK(state);
- DCHECK(!state->thread_texture_id_);
- DCHECK_EQ(0, tex_params.level);
- DCHECK_EQ(EGL_NO_IMAGE_KHR, state->egl_image_);
-
- void* data = GetAddress(safe_shared_memory, mem_params);
- {
- TRACE_EVENT0("gpu", "glTexImage2D no data");
- glGenTextures(1, &state->thread_texture_id_);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, state->thread_texture_id_);
-
- SetGlParametersForEglImageTexture();
-
- // If we need to use image_preserved, we pass the data with
- // the allocation. Otherwise we use a NULL allocation to
- // try to avoid any costs associated with creating the EGLImage.
- if (state->use_image_preserved_)
- DoTexImage2D(tex_params, data);
- else
- DoTexImage2D(tex_params, NULL);
- }
-
- state->CreateEglImageOnUploadThread();
-
- {
- TRACE_EVENT0("gpu", "glTexSubImage2D with data");
-
- // If we didn't use image_preserved, we haven't uploaded
- // the data yet, so we do this with a full texSubImage.
- if (!state->use_image_preserved_)
- DoFullTexSubImage2D(tex_params, data);
- }
-
- state->WaitForLastUpload();
- state->MarkAsCompleted();
-
- DCHECK(CHECK_GL());
-}
-
-void AsyncPixelTransferDelegateEGL::PerformAsyncTexSubImage2D(
- TransferStateInternal* state,
- AsyncTexSubImage2DParams tex_params,
- AsyncMemoryParams mem_params,
- ScopedSafeSharedMemory* safe_shared_memory,
- scoped_refptr<TextureUploadStats> texture_upload_stats) {
- TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D",
- "width", tex_params.width,
- "height", tex_params.height);
-
- DCHECK(state);
- DCHECK_NE(EGL_NO_IMAGE_KHR, state->egl_image_);
- DCHECK_EQ(0, tex_params.level);
-
- void* data = GetAddress(safe_shared_memory, mem_params);
-
- base::TimeTicks begin_time;
- if (texture_upload_stats)
- begin_time = base::TimeTicks::HighResNow();
-
- if (!state->thread_texture_id_) {
- TRACE_EVENT0("gpu", "glEGLImageTargetTexture2DOES");
- glGenTextures(1, &state->thread_texture_id_);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, state->thread_texture_id_);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, state->egl_image_);
- } else {
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, state->thread_texture_id_);
- }
- {
- TRACE_EVENT0("gpu", "glTexSubImage2D");
- DoTexSubImage2D(tex_params, data);
- }
- state->WaitForLastUpload();
- state->MarkAsCompleted();
-
- DCHECK(CHECK_GL());
- if (texture_upload_stats) {
- texture_upload_stats->AddUpload(
- base::TimeTicks::HighResNow() - begin_time);
- }
-}
-
namespace {
bool IsPowerOfTwo (unsigned int x) {
return ((x != 0) && !(x & (x - 1)));
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.h b/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.h
index 39a63cd..67cd971 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.h
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.h
@@ -11,8 +11,6 @@
namespace gpu {
class ScopedSafeSharedMemory;
-class TextureUploadStats;
-class TransferStateInternal;
// Class which handles async pixel transfers using EGLImageKHR and another
// upload thread
@@ -52,17 +50,6 @@
AsyncMemoryParams mem_params,
ScopedSafeSharedMemory* safe_shared_memory,
const CompletionCallback& callback);
- static void PerformAsyncTexImage2D(
- TransferStateInternal* state,
- AsyncTexImage2DParams tex_params,
- AsyncMemoryParams mem_params,
- ScopedSafeSharedMemory* safe_shared_memory);
- static void PerformAsyncTexSubImage2D(
- TransferStateInternal* state,
- AsyncTexSubImage2DParams tex_params,
- AsyncMemoryParams mem_params,
- ScopedSafeSharedMemory* safe_shared_memory,
- scoped_refptr<TextureUploadStats> texture_upload_stats);
// Returns true if a work-around was used.
bool WorkAroundAsyncTexImage2D(
@@ -78,7 +65,7 @@
typedef std::list<base::WeakPtr<AsyncPixelTransferState> > TransferQueue;
TransferQueue pending_allocations_;
- scoped_refptr<TextureUploadStats> texture_upload_stats_;
+ scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats_;
bool is_imagination_;
bool is_qualcomm_;
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_linux.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate_linux.cc
index 76a3e4b..470ac1d 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_linux.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_linux.cc
@@ -4,15 +4,25 @@
#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
+#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "gpu/command_buffer/service/async_pixel_transfer_delegate_idle.h"
+#include "gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.h"
#include "gpu/command_buffer/service/async_pixel_transfer_delegate_stub.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
#include "ui/gl/gl_implementation.h"
namespace gpu {
AsyncPixelTransferDelegate* AsyncPixelTransferDelegate::Create(
gfx::GLContext* context) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableShareGroupAsyncTextureUpload)) {
+ DCHECK(context);
+ return static_cast<AsyncPixelTransferDelegate*> (
+ new AsyncPixelTransferDelegateShareGroup(context));
+ }
+
TRACE_EVENT0("gpu", "AsyncPixelTransferDelegate::Create");
switch (gfx::GetGLImplementation()) {
case gfx::kGLImplementationOSMesaGL:
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc
new file mode 100644
index 0000000..a71bd66
--- /dev/null
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc
@@ -0,0 +1,504 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.h"
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/synchronization/cancellation_flag.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
+#include "gpu/command_buffer/service/safe_shared_memory_pool.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/gpu_preference.h"
+#include "ui/gl/scoped_binders.h"
+
+namespace gpu {
+
+namespace {
+
+const char kAsyncTransferThreadName[] = "AsyncTransferThread";
+
+// TODO(backer): Factor out common thread scheduling logic from the EGL and
+// ShareGroup implementations. http://crbug.com/239889
+class TransferThread : public base::Thread {
+ public:
+ TransferThread()
+ : base::Thread(kAsyncTransferThreadName),
+ initialized_(false) {
+ Start();
+#if defined(OS_ANDROID) || defined(OS_LINUX)
+ SetPriority(base::kThreadPriority_Background);
+#endif
+ }
+
+ virtual ~TransferThread() {
+ // The only instance of this class was declared leaky.
+ NOTREACHED();
+ }
+
+ void InitializeOnMainThread(gfx::GLContext* parent_context) {
+ TRACE_EVENT0("gpu", "TransferThread::InitializeOnMainThread");
+ if (initialized_)
+ return;
+
+ base::WaitableEvent wait_for_init(true, false);
+ message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&TransferThread::InitializeOnTransferThread,
+ base::Unretained(this),
+ base::Unretained(parent_context),
+ &wait_for_init));
+ wait_for_init.Wait();
+ }
+
+ virtual void CleanUp() OVERRIDE {
+ surface_ = NULL;
+ context_ = NULL;
+ }
+
+ SafeSharedMemoryPool* safe_shared_memory_pool() {
+ return &safe_shared_memory_pool_;
+ }
+
+ private:
+ bool initialized_;
+
+ scoped_refptr<gfx::GLSurface> surface_;
+ scoped_refptr<gfx::GLContext> context_;
+ SafeSharedMemoryPool safe_shared_memory_pool_;
+
+ void InitializeOnTransferThread(gfx::GLContext* parent_context,
+ base::WaitableEvent* caller_wait) {
+ TRACE_EVENT0("gpu", "InitializeOnTransferThread");
+
+ if (!parent_context) {
+ LOG(ERROR) << "No parent context provided.";
+ caller_wait->Signal();
+ return;
+ }
+
+ surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1));
+ if (!surface_) {
+ LOG(ERROR) << "Unable to create GLSurface";
+ caller_wait->Signal();
+ return;
+ }
+
+ // TODO(backer): This is coded for integrated GPUs. For discrete GPUs
+ // we would probably want to use a PBO texture upload for a true async
+ // upload (that would hopefully be optimized as a DMA transfer by the
+ // driver).
+ context_ = gfx::GLContext::CreateGLContext(parent_context->share_group(),
+ surface_,
+ gfx::PreferIntegratedGpu);
+ if (!context_) {
+ LOG(ERROR) << "Unable to create GLContext.";
+ caller_wait->Signal();
+ return;
+ }
+
+ context_->MakeCurrent(surface_);
+ initialized_ = true;
+ caller_wait->Signal();
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(TransferThread);
+};
+
+base::LazyInstance<TransferThread>::Leaky
+ g_transfer_thread = LAZY_INSTANCE_INITIALIZER;
+
+base::MessageLoopProxy* transfer_message_loop_proxy() {
+ return g_transfer_thread.Pointer()->message_loop_proxy();
+}
+
+SafeSharedMemoryPool* safe_shared_memory_pool() {
+ return g_transfer_thread.Pointer()->safe_shared_memory_pool();
+}
+
+// Class which holds async pixel transfers state.
+// The texture_id is accessed by either thread, but everything
+// else accessed only on the main thread.
+class TransferStateInternal
+ : public base::RefCountedThreadSafe<TransferStateInternal> {
+ public:
+ TransferStateInternal(GLuint texture_id,
+ const AsyncTexImage2DParams& define_params)
+ : texture_id_(texture_id),
+ transfer_completion_(true, true) {
+ define_params_ = define_params;
+ }
+
+ // Implement AsyncPixelTransferState:
+ bool TransferIsInProgress() {
+ return !transfer_completion_.IsSignaled();
+ }
+
+ void BindTransfer() {
+ TRACE_EVENT2("gpu", "BindAsyncTransfer",
+ "width", define_params_.width,
+ "height", define_params_.height);
+ DCHECK(texture_id_);
+
+ glBindTexture(GL_TEXTURE_2D, texture_id_);
+ bind_callback_.Run();
+ }
+
+ void MarkAsTransferIsInProgress() {
+ transfer_completion_.Reset();
+ }
+
+ void MarkAsCompleted() {
+ TRACE_EVENT0("gpu", "MarkAsCompleted");
+ glFlush();
+ transfer_completion_.Signal();
+ }
+
+ void WaitForTransferCompletion() {
+ TRACE_EVENT0("gpu", "WaitForTransferCompletion");
+ // TODO(backer): Deschedule the channel rather than blocking the main GPU
+ // thread (crbug.com/240265).
+ transfer_completion_.Wait();
+ }
+
+ GLuint texture_id() { return texture_id_; }
+
+ void SetBindCallback(base::Closure bind_callback) {
+ bind_callback_ = bind_callback;
+ }
+
+ void PerformAsyncTexImage2D(AsyncTexImage2DParams tex_params,
+ AsyncMemoryParams mem_params,
+ ScopedSafeSharedMemory* safe_shared_memory) {
+ base::AutoLock locked(upload_lock_);
+ if (cancel_upload_flag_.IsSet())
+ return;
+
+ TRACE_EVENT2("gpu",
+ "PerformAsyncTexImage",
+ "width",
+ tex_params.width,
+ "height",
+ tex_params.height);
+ DCHECK_EQ(0, tex_params.level);
+
+ void* data =
+ AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params);
+
+ {
+ TRACE_EVENT0("gpu", "glTexImage2D");
+ glBindTexture(GL_TEXTURE_2D, texture_id_);
+ glTexImage2D(GL_TEXTURE_2D,
+ tex_params.level,
+ tex_params.internal_format,
+ tex_params.width,
+ tex_params.height,
+ tex_params.border,
+ tex_params.format,
+ tex_params.type,
+ data);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ MarkAsCompleted();
+ }
+
+ void PerformAsyncTexSubImage2D(
+ AsyncTexSubImage2DParams tex_params,
+ AsyncMemoryParams mem_params,
+ ScopedSafeSharedMemory* safe_shared_memory,
+ scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) {
+ base::AutoLock locked(upload_lock_);
+ if (cancel_upload_flag_.IsSet())
+ return;
+
+ TRACE_EVENT2("gpu",
+ "PerformAsyncTexSubImage2D",
+ "width",
+ tex_params.width,
+ "height",
+ tex_params.height);
+ DCHECK_EQ(0, tex_params.level);
+
+ base::TimeTicks begin_time;
+ if (texture_upload_stats)
+ begin_time = base::TimeTicks::HighResNow();
+
+ void* data =
+ AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params);
+
+ {
+ TRACE_EVENT0("gpu", "glTexSubImage2D");
+ glBindTexture(GL_TEXTURE_2D, texture_id_);
+ glTexSubImage2D(GL_TEXTURE_2D,
+ tex_params.level,
+ tex_params.xoffset,
+ tex_params.yoffset,
+ tex_params.width,
+ tex_params.height,
+ tex_params.format,
+ tex_params.type,
+ data);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ MarkAsCompleted();
+
+ if (texture_upload_stats) {
+ texture_upload_stats->AddUpload(base::TimeTicks::HighResNow() -
+ begin_time);
+ }
+ }
+
+ base::CancellationFlag* cancel_upload_flag() { return &cancel_upload_flag_; }
+ base::Lock* upload_lock() { return &upload_lock_; }
+
+ private:
+ friend class base::RefCountedThreadSafe<TransferStateInternal>;
+
+ virtual ~TransferStateInternal() {
+ }
+
+ // Used to cancel pending uploads.
+ base::CancellationFlag cancel_upload_flag_;
+ base::Lock upload_lock_;
+
+ GLuint texture_id_;
+
+ // Definition params for texture that needs binding.
+ AsyncTexImage2DParams define_params_;
+
+ // Indicates that an async transfer is in progress.
+ base::WaitableEvent transfer_completion_;
+
+ // Callback to invoke when AsyncTexImage2D is complete
+ // and the client can safely use the texture. This occurs
+ // during BindCompletedAsyncTransfers().
+ base::Closure bind_callback_;
+};
+
+void PerformNotifyCompletion(
+ AsyncMemoryParams mem_params,
+ ScopedSafeSharedMemory* safe_shared_memory,
+ const AsyncPixelTransferDelegate::CompletionCallback& callback) {
+ TRACE_EVENT0("gpu", "PerformNotifyCompletion");
+ AsyncMemoryParams safe_mem_params = mem_params;
+ safe_mem_params.shared_memory = safe_shared_memory->shared_memory();
+ callback.Run(safe_mem_params);
+}
+
+} // namespace
+
+// ShareGroup needs thread-safe ref-counting, so this just wraps
+// an internal thread-safe ref-counted state object.
+class AsyncTransferStateImpl : public AsyncPixelTransferState {
+ public:
+ AsyncTransferStateImpl(GLuint texture_id,
+ const AsyncTexImage2DParams& define_params)
+ : internal_(new TransferStateInternal(texture_id, define_params)) {}
+
+ virtual ~AsyncTransferStateImpl() {
+ TRACE_EVENT0("gpu", " ~AsyncTransferStateImpl");
+ base::AutoLock locked(*internal_->upload_lock());
+ internal_->cancel_upload_flag()->Set();
+ }
+
+ virtual bool TransferIsInProgress() OVERRIDE {
+ return internal_->TransferIsInProgress();
+ }
+
+ TransferStateInternal* internal() { return internal_.get(); }
+
+ private:
+ scoped_refptr<TransferStateInternal> internal_;
+};
+
+AsyncPixelTransferDelegateShareGroup::AsyncPixelTransferDelegateShareGroup(
+ gfx::GLContext* context) {
+ g_transfer_thread.Pointer()->InitializeOnMainThread(context);
+
+ // TODO(reveman): Skip this if --enable-gpu-benchmarking is not present.
+ texture_upload_stats_ = make_scoped_refptr(new AsyncPixelTransferUploadStats);
+}
+
+AsyncPixelTransferDelegateShareGroup::~AsyncPixelTransferDelegateShareGroup() {
+}
+
+AsyncPixelTransferState*
+ AsyncPixelTransferDelegateShareGroup::
+ CreatePixelTransferState(
+ GLuint texture_id,
+ const AsyncTexImage2DParams& define_params) {
+ return static_cast<AsyncPixelTransferState*>(
+ new AsyncTransferStateImpl(texture_id, define_params));
+}
+
+void AsyncPixelTransferDelegateShareGroup::BindCompletedAsyncTransfers() {
+ scoped_ptr<gfx::ScopedTextureBinder> texture_binder;
+
+ while (!pending_allocations_.empty()) {
+ if (!pending_allocations_.front().get()) {
+ pending_allocations_.pop_front();
+ continue;
+ }
+ scoped_refptr<TransferStateInternal> state =
+ static_cast<AsyncTransferStateImpl*>
+ (pending_allocations_.front().get())->internal();
+ // Terminate early, as all transfers finish in order, currently.
+ if (state->TransferIsInProgress())
+ break;
+
+ if (!texture_binder)
+ texture_binder.reset(new gfx::ScopedTextureBinder(GL_TEXTURE_2D, 0));
+
+ // Used to set tex info from the gles2 cmd decoder once upload has
+ // finished (it'll bind the texture and call a callback).
+ state->BindTransfer();
+
+ pending_allocations_.pop_front();
+ }
+}
+
+void AsyncPixelTransferDelegateShareGroup::AsyncNotifyCompletion(
+ const AsyncMemoryParams& mem_params,
+ const CompletionCallback& callback) {
+ DCHECK(mem_params.shared_memory);
+ DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
+ mem_params.shm_size);
+ // Post a PerformNotifyCompletion task to the upload thread. This task
+ // will run after all async transfers are complete.
+ transfer_message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&PerformNotifyCompletion,
+ mem_params,
+ base::Owned(
+ new ScopedSafeSharedMemory(safe_shared_memory_pool(),
+ mem_params.shared_memory,
+ mem_params.shm_size)),
+ callback));
+}
+
+void AsyncPixelTransferDelegateShareGroup::WaitForTransferCompletion(
+ AsyncPixelTransferState* transfer_state) {
+ scoped_refptr<TransferStateInternal> state =
+ static_cast<AsyncTransferStateImpl*>(transfer_state)->internal();
+ DCHECK(state);
+ DCHECK(state->texture_id());
+
+ if (state->TransferIsInProgress()) {
+#if defined(OS_ANDROID) || defined(OS_LINUX)
+ g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Display);
+#endif
+
+ state->WaitForTransferCompletion();
+ DCHECK(!state->TransferIsInProgress());
+
+#if defined(OS_ANDROID) || defined(OS_LINUX)
+ g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Background);
+#endif
+ }
+}
+
+void AsyncPixelTransferDelegateShareGroup::AsyncTexImage2D(
+ AsyncPixelTransferState* transfer_state,
+ const AsyncTexImage2DParams& tex_params,
+ const AsyncMemoryParams& mem_params,
+ const base::Closure& bind_callback) {
+ scoped_refptr<TransferStateInternal> state =
+ static_cast<AsyncTransferStateImpl*>(transfer_state)->internal();
+ DCHECK(mem_params.shared_memory);
+ DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
+ mem_params.shm_size);
+ DCHECK(state);
+ DCHECK(state->texture_id());
+ DCHECK(!state->TransferIsInProgress());
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
+ DCHECK_EQ(tex_params.level, 0);
+
+ // Mark the transfer in progress and save the late bind
+ // callback, so we can notify the client when it is bound.
+ pending_allocations_.push_back(transfer_state->AsWeakPtr());
+ state->SetBindCallback(bind_callback);
+
+ // Mark the transfer in progress.
+ state->MarkAsTransferIsInProgress();
+
+ // Duplicate the shared memory so there is no way we can get
+ // a use-after-free of the raw pixels.
+ transfer_message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &TransferStateInternal::PerformAsyncTexImage2D,
+ state,
+ tex_params,
+ mem_params,
+ base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
+ mem_params.shared_memory,
+ mem_params.shm_size))));
+}
+
+void AsyncPixelTransferDelegateShareGroup::AsyncTexSubImage2D(
+ AsyncPixelTransferState* transfer_state,
+ const AsyncTexSubImage2DParams& tex_params,
+ const AsyncMemoryParams& mem_params) {
+ TRACE_EVENT2("gpu", "AsyncTexSubImage2D",
+ "width", tex_params.width,
+ "height", tex_params.height);
+ scoped_refptr<TransferStateInternal> state =
+ static_cast<AsyncTransferStateImpl*>(transfer_state)->internal();
+
+ DCHECK(state->texture_id());
+ DCHECK(!state->TransferIsInProgress());
+ DCHECK(mem_params.shared_memory);
+ DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
+ mem_params.shm_size);
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
+ DCHECK_EQ(tex_params.level, 0);
+
+ // Mark the transfer in progress.
+ state->MarkAsTransferIsInProgress();
+
+ // Duplicate the shared memory so there are no way we can get
+ // a use-after-free of the raw pixels.
+ transfer_message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &TransferStateInternal::PerformAsyncTexSubImage2D,
+ state,
+ tex_params,
+ mem_params,
+ base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
+ mem_params.shared_memory,
+ mem_params.shm_size)),
+ texture_upload_stats_));
+}
+
+uint32 AsyncPixelTransferDelegateShareGroup::GetTextureUploadCount() {
+ DCHECK(texture_upload_stats_);
+ return texture_upload_stats_->GetStats(NULL);
+}
+
+base::TimeDelta
+ AsyncPixelTransferDelegateShareGroup::GetTotalTextureUploadTime() {
+ DCHECK(texture_upload_stats_);
+ base::TimeDelta total_texture_upload_time;
+ texture_upload_stats_->GetStats(&total_texture_upload_time);
+ return total_texture_upload_time;
+}
+
+void AsyncPixelTransferDelegateShareGroup::ProcessMorePendingTransfers() {
+}
+
+bool AsyncPixelTransferDelegateShareGroup::NeedsProcessMorePendingTransfers() {
+ return false;
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.h b/gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.h
new file mode 100644
index 0000000..f0887a9
--- /dev/null
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_ASYNC_PIXEL_TRANSFER_DELEGATE_SHARE_GROUP_H_
+#define GPU_COMMAND_BUFFER_SERVICE_ASYNC_PIXEL_TRANSFER_DELEGATE_SHARE_GROUP_H_
+
+#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
+
+#include <list>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+
+namespace gpu {
+
+class AsyncPixelTransferDelegateShareGroup : public AsyncPixelTransferDelegate {
+ public:
+ explicit AsyncPixelTransferDelegateShareGroup(gfx::GLContext* context);
+ virtual ~AsyncPixelTransferDelegateShareGroup();
+
+ // Implement AsyncPixelTransferDelegate:
+ virtual AsyncPixelTransferState* CreatePixelTransferState(
+ GLuint texture_id,
+ const AsyncTexImage2DParams& define_params) OVERRIDE;
+ virtual void BindCompletedAsyncTransfers() OVERRIDE;
+ virtual void AsyncNotifyCompletion(
+ const AsyncMemoryParams& mem_params,
+ const CompletionCallback& callback) OVERRIDE;
+ virtual void AsyncTexImage2D(
+ AsyncPixelTransferState* state,
+ const AsyncTexImage2DParams& tex_params,
+ const AsyncMemoryParams& mem_params,
+ const base::Closure& bind_callback) OVERRIDE;
+ virtual void AsyncTexSubImage2D(
+ AsyncPixelTransferState* state,
+ const AsyncTexSubImage2DParams& tex_params,
+ const AsyncMemoryParams& mem_params) OVERRIDE;
+ virtual void WaitForTransferCompletion(
+ AsyncPixelTransferState* state) OVERRIDE;
+ virtual uint32 GetTextureUploadCount() OVERRIDE;
+ virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
+ virtual void ProcessMorePendingTransfers() OVERRIDE;
+ virtual bool NeedsProcessMorePendingTransfers() OVERRIDE;
+
+ private:
+ typedef std::list<base::WeakPtr<AsyncPixelTransferState> > TransferQueue;
+ TransferQueue pending_allocations_;
+
+ scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateShareGroup);
+};
+
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_ASYNC_PIXEL_TRANSFER_DELEGATE_SHARE_GROUP_H_
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index d1821d7..2a3809d 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -170,6 +170,7 @@
feature_info_.get(),
max_texture_size,
max_cube_map_texture_size));
+ texture_manager_->set_framebuffer_manager(framebuffer_manager_.get());
const GLint kMinTextureImageUnits = 8;
const GLint kMinVertexTextureImageUnits = 0;
@@ -212,6 +213,20 @@
return false;
}
+ // TODO(gman): Use workarounds similar to max_texture_size above to implement.
+ if (gfx::GetGLImplementation() == gfx::kGLImplementationOSMesaGL) {
+ // Some shaders in Skia needed more than the min.
+ max_fragment_uniform_vectors_ =
+ std::min(static_cast<uint32>(kMinFragmentUniformVectors * 2),
+ max_fragment_uniform_vectors_);
+ max_varying_vectors_ =
+ std::min(static_cast<uint32>(kMinVaryingVectors * 2),
+ max_varying_vectors_);
+ max_vertex_uniform_vectors_ =
+ std::min(static_cast<uint32>(kMinVertexUniformVectors * 2),
+ max_vertex_uniform_vectors_);
+ }
+
if (!texture_manager_->Initialize()) {
LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
<< "failed to initialize.";
@@ -251,6 +266,8 @@
if (framebuffer_manager_ != NULL) {
framebuffer_manager_->Destroy(have_context);
+ if (texture_manager_)
+ texture_manager_->set_framebuffer_manager(NULL);
framebuffer_manager_.reset();
}
diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h
index af43eac..e2bc012 100644
--- a/gpu/command_buffer/service/context_state.h
+++ b/gpu/command_buffer/service/context_state.h
@@ -36,21 +36,21 @@
GLenum bind_target;
// texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
- scoped_refptr<Texture> bound_texture_2d;
+ scoped_refptr<TextureRef> bound_texture_2d;
// texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
// glBindTexture
- scoped_refptr<Texture> bound_texture_cube_map;
+ scoped_refptr<TextureRef> bound_texture_cube_map;
// texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
// glBindTexture
- scoped_refptr<Texture> bound_texture_external_oes;
+ scoped_refptr<TextureRef> bound_texture_external_oes;
// texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with
// glBindTexture
- scoped_refptr<Texture> bound_texture_rectangle_arb;
+ scoped_refptr<TextureRef> bound_texture_rectangle_arb;
- scoped_refptr<Texture> GetInfoForSamplerType(
+ scoped_refptr<TextureRef> GetInfoForSamplerType(
GLenum type) {
DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
@@ -69,7 +69,7 @@
return NULL;
}
- void Unbind(Texture* texture) {
+ void Unbind(TextureRef* texture) {
if (bound_texture_2d == texture) {
bound_texture_2d = NULL;
}
diff --git a/gpu/command_buffer/service/error_state.cc b/gpu/command_buffer/service/error_state.cc
index 1e9148c..23fba49 100644
--- a/gpu/command_buffer/service/error_state.cc
+++ b/gpu/command_buffer/service/error_state.cc
@@ -113,7 +113,7 @@
last_error_ = msg;
logger_->LogMessage(
filename, line,
- logger_->GetLogPrefix() + ": " + std::string("GL ERROR :") +
+ std::string("GL ERROR :") +
GLES2Util::GetStringEnum(error) + " : " +
function_name + ": " + msg);
}
@@ -170,7 +170,7 @@
// GL_OUT_OF_MEMORY can legally happen on lost device.
logger_->LogMessage(
filename, line,
- logger_->GetLogPrefix() + ": " + std::string("GL ERROR :") +
+ std::string("GL ERROR :") +
GLES2Util::GetStringEnum(error) + " : " +
function_name + ": was unhandled");
NOTREACHED() << "GL error " << error << " was unhandled.";
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index fa8abdd..8b828e1 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -180,78 +180,6 @@
StringSet extensions(
reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
- // This is a temporary fix to turn gl_tests green on Linux and Android bots.
- // Once we migrate blacklisting stuff from src/content to src/gpu, we can
- // get the workarounds from json file. Then we should remove this block.
- // See crbug.com/228979.
- bool is_intel = false;
- bool is_nvidia = false;
- bool is_amd = false;
- bool is_mesa = false;
- bool is_qualcomm = false;
- bool is_imagination = false;
- bool is_arm = false;
- bool is_vivante = false;
- const char* gl_strings[2];
- gl_strings[0] = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
- gl_strings[1] = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
- if (!command_line.HasSwitch(switches::kGpuDriverBugWorkarounds) &&
- !command_line.HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
- for (size_t ii = 0; ii < arraysize(gl_strings); ++ii) {
- const char* str = gl_strings[ii];
- if (str) {
- std::string lstr(StringToLowerASCII(std::string(str)));
- StringSet string_set(lstr);
- is_intel |= string_set.Contains("intel");
- is_nvidia |= string_set.Contains("nvidia");
- is_amd |= string_set.Contains("amd") || string_set.Contains("ati");
- is_mesa |= string_set.Contains("mesa");
- is_qualcomm |= string_set.Contains("qualcomm");
- is_imagination |= string_set.Contains("imagination");
- is_arm |= string_set.Contains("arm");
- }
- }
- if (extensions.Contains("GL_VIV_shader_binary"))
- is_vivante = true;
-
- workarounds_.set_texture_filter_before_generating_mipmap = true;
- workarounds_.clear_alpha_in_readpixels = true;
- if (is_nvidia) {
- workarounds_.use_current_program_after_successful_link = true;
- }
- if (is_qualcomm) {
- workarounds_.restore_scissor_on_fbo_change = true;
- workarounds_.flush_on_context_switch = true;
- workarounds_.delete_instead_of_resize_fbo = true;
- }
- if (is_vivante || is_imagination) {
- workarounds_.unbind_fbo_on_context_switch = true;
- }
-#if defined(OS_MACOSX)
- workarounds_.needs_offscreen_buffer_workaround = is_nvidia;
- workarounds_.needs_glsl_built_in_function_emulation = is_amd;
- if ((is_amd || is_intel) &&
- gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) {
- workarounds_.reverse_point_sprite_coord_origin = true;
- }
- if (is_intel) {
- workarounds_.max_texture_size = 4096;
- workarounds_.max_cube_map_texture_size = 1024;
- int32 major = 0;
- int32 minor = 0;
- int32 bugfix = 0;
- base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
- if (major < 10 ||
- (major == 10 && ((minor == 7 && bugfix < 3) || (minor < 7))))
- workarounds_.max_cube_map_texture_size = 512;
- }
- if (is_amd) {
- workarounds_.max_texture_size = 4096;
- workarounds_.max_cube_map_texture_size = 4096;
- }
-#endif
- }
-
if (command_line.HasSwitch(switches::kGpuDriverBugWorkarounds)) {
std::string types = command_line.GetSwitchValueASCII(
switches::kGpuDriverBugWorkarounds);
@@ -282,8 +210,7 @@
AddExtensionString("GL_CHROMIUM_texture_mailbox");
AddExtensionString("GL_EXT_debug_marker");
- if (workarounds_.enable_chromium_fast_npot_mo8_textures ||
- is_imagination)
+ if (workarounds_.enable_chromium_fast_npot_mo8_textures)
AddExtensionString("GL_CHROMIUM_fast_NPOT_MO8_textures");
feature_flags_.chromium_stream_texture = true;
@@ -368,7 +295,7 @@
// get rid of it.
//
bool enable_depth_texture = false;
- if ((!workarounds_.disable_depth_texture && !is_qualcomm) &&
+ if (!workarounds_.disable_depth_texture &&
(extensions.Contains("GL_ARB_depth_texture") ||
extensions.Contains("GL_OES_depth_texture") ||
extensions.Contains("GL_ANGLE_depth_texture"))) {
@@ -405,10 +332,6 @@
feature_flags_.native_vertex_array_object = true;
}
- if (is_arm || is_imagination) {
- workarounds_.use_client_side_arrays_for_stream_buffers = true;
- }
-
// If we're using client_side_arrays we have to emulate
// vertex array objects since vertex array objects do not work
// with client side arrays.
@@ -529,7 +452,7 @@
// Check for multisample support
bool ext_has_multisample =
extensions.Contains("GL_EXT_framebuffer_multisample");
- if (!is_qualcomm && !workarounds_.disable_angle_framebuffer_multisample) {
+ if (!workarounds_.disable_angle_framebuffer_multisample) {
ext_has_multisample |=
extensions.Contains("GL_ANGLE_framebuffer_multisample");
}
@@ -548,8 +471,9 @@
validators_.render_buffer_format.AddValue(GL_DEPTH_COMPONENT24);
}
- if (extensions.Contains("GL_OES_standard_derivatives") ||
- gfx::HasDesktopGLFeatures()) {
+ if (!workarounds_.disable_oes_standard_derivatives &&
+ (extensions.Contains("GL_OES_standard_derivatives") ||
+ gfx::HasDesktopGLFeatures())) {
AddExtensionString("GL_OES_standard_derivatives");
feature_flags_.oes_standard_derivatives = true;
validators_.hint_target.AddValue(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
@@ -647,9 +571,6 @@
extensions.Contains("GL_ARB_occlusion_query");
if (!workarounds_.disable_ext_occlusion_query &&
-#if defined(OS_LINUX)
- !is_intel &&
-#endif
(have_ext_occlusion_query_boolean ||
have_arb_occlusion_query2 ||
have_arb_occlusion_query)) {
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index 3605976..ed0ec25 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -12,7 +12,7 @@
#include "base/sys_info.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/gles2_cmd_validation.h"
-#include "gpu/command_buffer/service/gpu_driver_bug_workaround_type.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/gpu_export.h"
class CommandLine;
diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc
index 0fcc3a7..ac10e8d 100644
--- a/gpu/command_buffer/service/feature_info_unittest.cc
+++ b/gpu/command_buffer/service/feature_info_unittest.cc
@@ -7,10 +7,10 @@
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
-#include "gpu/command_buffer/service/gpu_driver_bug_workaround_type.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/test_helper.h"
#include "gpu/command_buffer/service/texture_manager.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_mock.h"
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index 1ffd0fd..29fd55d 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -67,7 +67,7 @@
}
virtual bool IsTexture(
- Texture* /* texture */) const OVERRIDE {
+ TextureRef* /* texture */) const OVERRIDE {
return false;
}
@@ -115,8 +115,8 @@
: public Framebuffer::Attachment {
public:
TextureAttachment(
- Texture* texture, GLenum target, GLint level)
- : texture_(texture),
+ TextureRef* texture_ref, GLenum target, GLint level)
+ : texture_ref_(texture_ref),
target_(target),
level_(level) {
}
@@ -124,21 +124,24 @@
virtual GLsizei width() const OVERRIDE {
GLsizei temp_width = 0;
GLsizei temp_height = 0;
- texture_->GetLevelSize(target_, level_, &temp_width, &temp_height);
+ texture_ref_->texture()->GetLevelSize(
+ target_, level_, &temp_width, &temp_height);
return temp_width;
}
virtual GLsizei height() const OVERRIDE {
GLsizei temp_width = 0;
GLsizei temp_height = 0;
- texture_->GetLevelSize(target_, level_, &temp_width, &temp_height);
+ texture_ref_->texture()->GetLevelSize(
+ target_, level_, &temp_width, &temp_height);
return temp_height;
}
virtual GLenum internal_format() const OVERRIDE {
GLenum temp_type = 0;
GLenum temp_internal_format = 0;
- texture_->GetLevelType(target_, level_, &temp_type, &temp_internal_format);
+ texture_ref_->texture()->GetLevelType(
+ target_, level_, &temp_type, &temp_internal_format);
return temp_internal_format;
}
@@ -147,18 +150,18 @@
}
virtual bool cleared() const OVERRIDE {
- return texture_->IsLevelCleared(target_, level_);
+ return texture_ref_->texture()->IsLevelCleared(target_, level_);
}
virtual void SetCleared(
RenderbufferManager* /* renderbuffer_manager */,
TextureManager* texture_manager,
bool cleared) OVERRIDE {
- texture_manager->SetLevelCleared(texture_, target_, level_, cleared);
+ texture_manager->SetLevelCleared(texture_ref_, target_, level_, cleared);
}
- virtual bool IsTexture(Texture* texture) const OVERRIDE {
- return texture == texture_.get();
+ virtual bool IsTexture(TextureRef* texture) const OVERRIDE {
+ return texture == texture_ref_.get();
}
virtual bool IsRenderbuffer(
@@ -167,23 +170,24 @@
return false;
}
- Texture* texture() const {
- return texture_.get();
+ TextureRef* texture() const {
+ return texture_ref_.get();
}
virtual bool CanRenderTo() const OVERRIDE {
- return texture_->CanRenderTo();
+ return texture_ref_->texture()->CanRenderTo();
}
virtual void DetachFromFramebuffer() const OVERRIDE {
- texture_->DetachFromFramebuffer();
+ texture_ref_->texture()->DetachFromFramebuffer();
}
virtual bool ValidForAttachmentType(
GLenum attachment_type, uint32 max_color_attachments) OVERRIDE {
GLenum type = 0;
GLenum internal_format = 0;
- if (!texture_->GetLevelType(target_, level_, &type, &internal_format)) {
+ if (!texture_ref_->texture()->GetLevelType(
+ target_, level_, &type, &internal_format)) {
return false;
}
uint32 need = GLES2Util::GetChannelsNeededForAttachmentType(
@@ -195,14 +199,14 @@
virtual void AddToSignature(
TextureManager* texture_manager, std::string* signature) const OVERRIDE {
DCHECK(signature);
- texture_manager->AddToSignature(texture_, target_, level_, signature);
+ texture_manager->AddToSignature(texture_ref_, target_, level_, signature);
}
protected:
virtual ~TextureAttachment() {}
private:
- scoped_refptr<Texture> texture_;
+ scoped_refptr<TextureRef> texture_ref_;
GLenum target_;
GLint level_;
@@ -466,14 +470,14 @@
}
void Framebuffer::UnbindTexture(
- GLenum target, Texture* texture) {
+ GLenum target, TextureRef* texture_ref) {
bool done;
do {
done = true;
for (AttachmentMap::const_iterator it = attachments_.begin();
it != attachments_.end(); ++it) {
Attachment* attachment = it->second;
- if (attachment->IsTexture(texture)) {
+ if (attachment->IsTexture(texture_ref)) {
// TODO(gman): manually detach texture.
// glFramebufferTexture2DEXT(target, it->first, GL_TEXTURE_2D, 0, 0);
AttachTexture(it->first, NULL, GL_TEXTURE_2D, 0);
@@ -513,15 +517,15 @@
}
void Framebuffer::AttachTexture(
- GLenum attachment, Texture* texture, GLenum target,
+ GLenum attachment, TextureRef* texture_ref, GLenum target,
GLint level) {
const Attachment* a = GetAttachment(attachment);
if (a)
a->DetachFromFramebuffer();
- if (texture) {
+ if (texture_ref) {
attachments_[attachment] = scoped_refptr<Attachment>(
- new TextureAttachment(texture, target, level));
- texture->AttachToFramebuffer();
+ new TextureAttachment(texture_ref, target, level));
+ texture_ref->texture()->AttachToFramebuffer();
} else {
attachments_.erase(attachment);
}
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index a5bdb3b..9b7b131 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -19,6 +19,7 @@
class Renderbuffer;
class RenderbufferManager;
class Texture;
+class TextureRef;
class TextureManager;
// Info about a particular Framebuffer.
@@ -35,7 +36,7 @@
RenderbufferManager* renderbuffer_manager,
TextureManager* texture_manager,
bool cleared) = 0;
- virtual bool IsTexture(Texture* texture) const = 0;
+ virtual bool IsTexture(TextureRef* texture) const = 0;
virtual bool IsRenderbuffer(
Renderbuffer* renderbuffer) const = 0;
virtual bool CanRenderTo() const = 0;
@@ -71,7 +72,7 @@
// Attaches a texture to a particlar attachment. Pass null to detach.
void AttachTexture(
- GLenum attachment, Texture* texture, GLenum target,
+ GLenum attachment, TextureRef* texture_ref, GLenum target,
GLint level);
// Unbinds the given renderbuffer if it is bound.
@@ -80,7 +81,7 @@
// Unbinds the given texture if it is bound.
void UnbindTexture(
- GLenum target, Texture* texture);
+ GLenum target, TextureRef* texture_ref);
const Attachment* GetAttachment(GLenum attachment) const;
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index b73a776..9a7f15b 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -429,7 +429,7 @@
framebuffer_->IsPossiblyComplete());
texture_manager_.CreateTexture(kTextureClient1Id, kTextureService1Id);
- scoped_refptr<Texture> texture1(
+ scoped_refptr<TextureRef> texture1(
texture_manager_.GetTexture(kTextureClient1Id));
ASSERT_TRUE(texture1 != NULL);
@@ -478,7 +478,7 @@
// Check replacing an attachment
texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
- scoped_refptr<Texture> texture2(
+ scoped_refptr<TextureRef> texture2(
texture_manager_.GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2 != NULL);
texture_manager_.SetTarget(texture2, GL_TEXTURE_2D);
@@ -580,11 +580,11 @@
const GLint kLevel1 = 0;
texture_manager_.CreateTexture(kTextureClient1Id, kTextureService1Id);
- scoped_refptr<Texture> texture1(
+ scoped_refptr<TextureRef> texture1(
texture_manager_.GetTexture(kTextureClient1Id));
ASSERT_TRUE(texture1 != NULL);
texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
- scoped_refptr<Texture> texture2(
+ scoped_refptr<TextureRef> texture2(
texture_manager_.GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2 != NULL);
@@ -622,7 +622,7 @@
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id);
ASSERT_TRUE(renderbuffer1 != NULL);
texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
- scoped_refptr<Texture> texture2(
+ scoped_refptr<TextureRef> texture2(
texture_manager_.GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2 != NULL);
@@ -667,7 +667,7 @@
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id);
ASSERT_TRUE(renderbuffer1 != NULL);
texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
- scoped_refptr<Texture> texture2(
+ scoped_refptr<TextureRef> texture2(
texture_manager_.GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2 != NULL);
texture_manager_.SetTarget(texture2, GL_TEXTURE_2D);
diff --git a/gpu/command_buffer/service/gl_context_virtual.cc b/gpu/command_buffer/service/gl_context_virtual.cc
index d142e01..8051e06 100644
--- a/gpu/command_buffer/service/gl_context_virtual.cc
+++ b/gpu/command_buffer/service/gl_context_virtual.cc
@@ -43,6 +43,7 @@
}
shared_context_->SetupForVirtualization();
+ shared_context_->MakeVirtuallyCurrent(this, compatible_surface);
return true;
}
@@ -53,9 +54,12 @@
}
bool GLContextVirtual::MakeCurrent(gfx::GLSurface* surface) {
- if (decoder_.get() && decoder_->initialized())
+ // TODO(epenner): We should avoid bypassing MakeVirtuallyCurrent() below
+ // (return false or DCHECK when !decoder). To do this we must reorder
+ // tear-down in GpuCommandBufferStub::Destroy().
+ if (decoder_.get())
shared_context_->MakeVirtuallyCurrent(this, surface);
- else
+ else if (!IsCurrent(surface))
shared_context_->MakeCurrent(surface);
return true;
}
diff --git a/gpu/command_buffer/service/gl_state_restorer_impl.cc b/gpu/command_buffer/service/gl_state_restorer_impl.cc
index d39b805..7b3c5ed 100644
--- a/gpu/command_buffer/service/gl_state_restorer_impl.cc
+++ b/gpu/command_buffer/service/gl_state_restorer_impl.cc
@@ -16,6 +16,11 @@
GLStateRestorerImpl::~GLStateRestorerImpl() {
}
+bool GLStateRestorerImpl::IsInitialized() {
+ DCHECK(decoder_.get());
+ return decoder_->initialized();
+}
+
void GLStateRestorerImpl::RestoreState() {
DCHECK(decoder_.get());
decoder_->RestoreState();
diff --git a/gpu/command_buffer/service/gl_state_restorer_impl.h b/gpu/command_buffer/service/gl_state_restorer_impl.h
index aba3b1d..032bf72 100644
--- a/gpu/command_buffer/service/gl_state_restorer_impl.h
+++ b/gpu/command_buffer/service/gl_state_restorer_impl.h
@@ -23,6 +23,7 @@
explicit GLStateRestorerImpl(base::WeakPtr<gles2::GLES2Decoder> decoder);
virtual ~GLStateRestorerImpl();
+ virtual bool IsInitialized() OVERRIDE;
virtual void RestoreState() OVERRIDE;
virtual void RestoreAllTextureUnitBindings() OVERRIDE;
virtual void RestoreFramebufferBindings() OVERRIDE;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 1637a0b..2fad005 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -561,7 +561,7 @@
virtual void PerformIdleWork() OVERRIDE;
virtual void SetResizeCallback(
- const base::Callback<void(gfx::Size)>& callback) OVERRIDE;
+ const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
virtual Logger* GetLogger() OVERRIDE;
virtual ErrorState* GetErrorState() OVERRIDE;
@@ -693,13 +693,13 @@
}
// Creates a Texture for the given texture.
- Texture* CreateTexture(
+ TextureRef* CreateTexture(
GLuint client_id, GLuint service_id) {
return texture_manager()->CreateTexture(client_id, service_id);
}
// Gets the texture info for the given texture. Returns NULL if none exists.
- Texture* GetTexture(GLuint client_id) const {
+ TextureRef* GetTexture(GLuint client_id) const {
return texture_manager()->GetTexture(client_id);
}
@@ -1376,9 +1376,9 @@
}
// Gets the texture id for a given target.
- Texture* GetTextureInfoForTarget(GLenum target) {
+ TextureRef* GetTextureInfoForTarget(GLenum target) {
TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
- Texture* texture = NULL;
+ TextureRef* texture = NULL;
switch (target) {
case GL_TEXTURE_2D:
texture = unit.bound_texture_2d;
@@ -1405,9 +1405,9 @@
return texture;
}
- Texture* GetTextureInfoForTargetUnlessDefault(
+ TextureRef* GetTextureInfoForTargetUnlessDefault(
GLenum target) {
- Texture* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture = GetTextureInfoForTarget(target);
if (!texture)
return NULL;
if (texture == texture_manager()->GetDefaultTextureInfo(target))
@@ -1614,7 +1614,7 @@
// The copy that is saved when SwapBuffers is called.
scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
scoped_ptr<BackTexture> offscreen_saved_color_texture_;
- scoped_refptr<Texture>
+ scoped_refptr<TextureRef>
offscreen_saved_color_texture_info_;
// The copy that is used as the destination for multi-sample resolves.
@@ -1626,7 +1626,7 @@
scoped_ptr<VertexArrayManager> vertex_array_manager_;
- base::Callback<void(gfx::Size)> resize_callback_;
+ base::Callback<void(gfx::Size, float)> resize_callback_;
WaitSyncPointCallback wait_sync_point_callback_;
@@ -2234,25 +2234,25 @@
for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
glActiveTexture(GL_TEXTURE0 + tt);
// We want the last bind to be 2D.
- Texture* texture;
+ TextureRef* ref;
if (features().oes_egl_image_external) {
- texture = texture_manager()->GetDefaultTextureInfo(
+ ref = texture_manager()->GetDefaultTextureInfo(
GL_TEXTURE_EXTERNAL_OES);
- state_.texture_units[tt].bound_texture_external_oes = texture;
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->service_id());
+ state_.texture_units[tt].bound_texture_external_oes = ref;
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
}
if (features().arb_texture_rectangle) {
- texture = texture_manager()->GetDefaultTextureInfo(
+ ref = texture_manager()->GetDefaultTextureInfo(
GL_TEXTURE_RECTANGLE_ARB);
- state_.texture_units[tt].bound_texture_rectangle_arb = texture;
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture->service_id());
+ state_.texture_units[tt].bound_texture_rectangle_arb = ref;
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
}
- texture = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
- state_.texture_units[tt].bound_texture_cube_map = texture;
- glBindTexture(GL_TEXTURE_CUBE_MAP, texture->service_id());
- texture = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
- state_.texture_units[tt].bound_texture_2d = texture;
- glBindTexture(GL_TEXTURE_2D, texture->service_id());
+ ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
+ state_.texture_units[tt].bound_texture_cube_map = ref;
+ glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
+ ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
+ state_.texture_units[tt].bound_texture_2d = ref;
+ glBindTexture(GL_TEXTURE_2D, ref->service_id());
}
glActiveTexture(GL_TEXTURE0);
CHECK_GL_ERROR();
@@ -2504,9 +2504,11 @@
resources.MaxFragmentUniformVectors =
group_->max_fragment_uniform_vectors();
resources.MaxDrawBuffers = group_->max_draw_buffers();
+ resources.MaxExpressionComplexity = 256;
+ resources.MaxCallStackDepth = 256;
#if (ANGLE_SH_VERSION >= 110)
- GLint range[2];
+ GLint range[2] = { 0, 0 };
GLint precision = 0;
GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
range, &precision);
@@ -2705,28 +2707,30 @@
bool supports_separate_framebuffer_binds =
features().chromium_framebuffer_multisample;
for (GLsizei ii = 0; ii < n; ++ii) {
- Texture* texture = GetTexture(client_ids[ii]);
- if (texture && !texture->IsDeleted()) {
+ TextureRef* texture_ref = GetTexture(client_ids[ii]);
+ if (texture_ref) {
+ Texture* texture = texture_ref->texture();
if (texture->IsAttachedToFramebuffer()) {
clear_state_dirty_ = true;
}
- // Unbind texture from texture units.
+ // Unbind texture_ref from texture_ref units.
for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
- state_.texture_units[jj].Unbind(texture);
+ state_.texture_units[jj].Unbind(texture_ref);
}
// Unbind from current framebuffers.
if (supports_separate_framebuffer_binds) {
if (state_.bound_read_framebuffer) {
state_.bound_read_framebuffer->UnbindTexture(
- GL_READ_FRAMEBUFFER_EXT, texture);
+ GL_READ_FRAMEBUFFER_EXT, texture_ref);
}
if (state_.bound_draw_framebuffer) {
state_.bound_draw_framebuffer->UnbindTexture(
- GL_DRAW_FRAMEBUFFER_EXT, texture);
+ GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
}
} else {
if (state_.bound_draw_framebuffer) {
- state_.bound_draw_framebuffer->UnbindTexture(GL_FRAMEBUFFER, texture);
+ state_.bound_draw_framebuffer->UnbindTexture(GL_FRAMEBUFFER,
+ texture_ref);
}
}
GLuint service_id = texture->service_id();
@@ -2771,6 +2775,8 @@
if (workarounds().unbind_fbo_on_context_switch)
RestoreFramebufferBindings();
+ clear_state_dirty_ = true;
+
return true;
}
@@ -2972,9 +2978,9 @@
// Update the info about the offscreen saved color texture in the parent.
// The reference to the parent is a weak pointer and will become null if the
// parent is later destroyed.
+ GLenum target = offscreen_saved_color_texture_info_->texture()->target();
TextureManager* parent_texture_manager = parent_->texture_manager();
- glBindTexture(offscreen_saved_color_texture_info_->target(),
- offscreen_saved_color_texture_info_->service_id());
+ glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
parent_texture_manager->SetLevelInfo(
offscreen_saved_color_texture_info_,
GL_TEXTURE_2D,
@@ -3011,16 +3017,15 @@
offscreen_saved_color_texture_info_,
GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
- Texture* texture = GetTextureInfoForTarget(
- offscreen_saved_color_texture_info_->target());
- glBindTexture(texture->target(), texture->service_id());
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
} else {
offscreen_saved_color_texture_info_ = NULL;
}
}
void GLES2DecoderImpl::SetResizeCallback(
- const base::Callback<void(gfx::Size)>& callback) {
+ const base::Callback<void(gfx::Size, float)>& callback) {
resize_callback_ = callback;
}
@@ -3058,9 +3063,9 @@
bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
uint32* service_texture_id) {
- Texture* texture = texture_manager()->GetTexture(client_texture_id);
- if (texture) {
- *service_texture_id = texture->service_id();
+ TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
+ if (texture_ref) {
+ *service_texture_id = texture_ref->service_id();
return true;
}
return false;
@@ -3259,7 +3264,7 @@
offscreen_saved_color_texture_info_ =
new_parent_impl->CreateTexture(new_parent_texture_id, service_id);
- offscreen_saved_color_texture_info_->SetNotOwned();
+ offscreen_saved_color_texture_info_->texture()->SetNotOwned();
new_parent_impl->texture_manager()->
SetTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
@@ -3425,6 +3430,7 @@
GLuint width = static_cast<GLuint>(c.width);
GLuint height = static_cast<GLuint>(c.height);
+ GLfloat scale_factor = c.scale_factor;
TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
width = std::max(1U, width);
@@ -3445,7 +3451,7 @@
}
if (!resize_callback_.is_null()) {
- resize_callback_.Run(gfx::Size(width, height));
+ resize_callback_.Run(gfx::Size(width, height), scale_factor);
DCHECK(context_->IsCurrent(surface_.get()));
if (!context_->IsCurrent(surface_.get())) {
LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
@@ -3672,6 +3678,8 @@
}
void GLES2DecoderImpl::RestoreState() const {
+ TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
+ "context", logger_.GetLogPrefix());
// Restore the Framebuffer first because of bugs in Intel drivers.
// Intel drivers incorrectly clip the viewport settings to
// the size of the current framebuffer object.
@@ -3698,7 +3706,7 @@
void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
GLuint client_id = 0;
if (texture_manager()->GetClientId(service_id, &client_id)) {
- Texture* texture = GetTexture(client_id);
+ Texture* texture = GetTexture(client_id)->texture();
GLenum target = texture->target();
glBindTexture(target, service_id);
glTexParameteri(
@@ -3811,11 +3819,11 @@
}
void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
- Texture* texture = NULL;
+ TextureRef* texture_ref = NULL;
GLuint service_id = 0;
if (client_id != 0) {
- texture = GetTexture(client_id);
- if (!texture) {
+ texture_ref = GetTexture(client_id);
+ if (!texture_ref) {
if (!group_->bind_generates_resource()) {
LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
current_decoder_error_ = error::kGenericError;
@@ -3826,14 +3834,15 @@
glGenTextures(1, &service_id);
DCHECK_NE(0u, service_id);
CreateTexture(client_id, service_id);
- texture = GetTexture(client_id);
+ texture_ref = GetTexture(client_id);
IdAllocatorInterface* id_allocator =
group_->GetIdAllocator(id_namespaces::kTextures);
id_allocator->MarkAsUsed(client_id);
}
} else {
- texture = texture_manager()->GetDefaultTextureInfo(target);
+ texture_ref = texture_manager()->GetDefaultTextureInfo(target);
}
+ Texture* texture = texture_ref->texture();
// Check the texture exists
// Check that we are not trying to bind it to a different target.
@@ -3851,7 +3860,7 @@
}
LogClientServiceForInfo(texture, client_id, "glBindTexture");
if (texture->target() == 0) {
- texture_manager()->SetTarget(texture, target);
+ texture_manager()->SetTarget(texture_ref, target);
}
glBindTexture(target, texture->service_id());
@@ -3859,13 +3868,13 @@
unit.bind_target = target;
switch (target) {
case GL_TEXTURE_2D:
- unit.bound_texture_2d = texture;
+ unit.bound_texture_2d = texture_ref;
break;
case GL_TEXTURE_CUBE_MAP:
- unit.bound_texture_cube_map = texture;
+ unit.bound_texture_cube_map = texture_ref;
break;
case GL_TEXTURE_EXTERNAL_OES:
- unit.bound_texture_external_oes = texture;
+ unit.bound_texture_external_oes = texture_ref;
if (texture->IsStreamTexture()) {
DCHECK(stream_texture_manager_);
StreamTexture* stream_tex =
@@ -3875,7 +3884,7 @@
}
break;
case GL_TEXTURE_RECTANGLE_ARB:
- unit.bound_texture_rectangle_arb = texture;
+ unit.bound_texture_rectangle_arb = texture_ref;
break;
default:
NOTREACHED(); // Validation should prevent us getting here.
@@ -3952,9 +3961,9 @@
}
void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture ||
- !texture_manager()->CanGenerateMipmaps(texture)) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref ||
+ !texture_manager()->CanGenerateMipmaps(texture_ref)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
return;
@@ -3963,14 +3972,14 @@
if (target == GL_TEXTURE_CUBE_MAP) {
for (int i = 0; i < 6; ++i) {
GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
- if (!texture_manager()->ClearTextureLevel(this, texture, face, 0)) {
+ if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
return;
}
}
} else {
- if (!texture_manager()->ClearTextureLevel(this, texture, target, 0)) {
+ if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
return;
@@ -3989,11 +3998,12 @@
}
glGenerateMipmapEXT(target);
if (workarounds().set_texture_filter_before_generating_mipmap) {
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
+ texture_ref->texture()->min_filter());
}
GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
if (error == GL_NO_ERROR) {
- texture_manager()->MarkMipmapsGenerated(texture);
+ texture_manager()->MarkMipmapsGenerated(texture_ref);
}
}
@@ -4882,16 +4892,16 @@
return;
}
GLuint service_id = 0;
- Texture* texture = NULL;
+ TextureRef* texture_ref = NULL;
if (client_texture_id) {
- texture = GetTexture(client_texture_id);
- if (!texture) {
+ texture_ref = GetTexture(client_texture_id);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
- "glFramebufferTexture2D", "unknown texture");
+ "glFramebufferTexture2D", "unknown texture_ref");
return;
}
- service_id = texture->service_id();
+ service_id = texture_ref->service_id();
}
if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
@@ -4905,7 +4915,7 @@
glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferTexture2D");
if (error == GL_NO_ERROR) {
- framebuffer->AttachTexture(attachment, texture, textarget, level);
+ framebuffer->AttachTexture(attachment, texture_ref, textarget, level);
}
if (framebuffer == state_.bound_draw_framebuffer) {
clear_state_dirty_ = true;
@@ -5146,7 +5156,7 @@
void GLES2DecoderImpl::DoTexParameterf(
GLenum target, GLenum pname, GLfloat param) {
- Texture* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture = GetTextureInfoForTarget(target);
if (!texture) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
return;
@@ -5159,7 +5169,7 @@
void GLES2DecoderImpl::DoTexParameteri(
GLenum target, GLenum pname, GLint param) {
- Texture* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture = GetTextureInfoForTarget(target);
if (!texture) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
return;
@@ -5171,7 +5181,7 @@
void GLES2DecoderImpl::DoTexParameterfv(
GLenum target, GLenum pname, const GLfloat* params) {
- Texture* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture = GetTextureInfoForTarget(target);
if (!texture) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
return;
@@ -5184,7 +5194,7 @@
void GLES2DecoderImpl::DoTexParameteriv(
GLenum target, GLenum pname, const GLint* params) {
- Texture* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture = GetTextureInfoForTarget(target);
if (!texture) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
@@ -5637,6 +5647,7 @@
if (!texture_manager()->HaveUnrenderableTextures()) {
return false;
}
+ LOCAL_PERFORMANCE_WARNING("Some textures are unrenderable.");
bool textures_set = false;
const Program::SamplerIndices& sampler_indices =
state_.current_program->sampler_indices();
@@ -5648,7 +5659,7 @@
GLuint texture_unit_index = uniform_info->texture_units[jj];
if (texture_unit_index < state_.texture_units.size()) {
TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
- Texture* texture =
+ TextureRef* texture =
texture_unit.GetInfoForSamplerType(uniform_info->type);
if (!texture || !texture_manager()->CanRender(texture)) {
textures_set = true;
@@ -5682,17 +5693,17 @@
GLuint texture_unit_index = uniform_info->texture_units[jj];
if (texture_unit_index < state_.texture_units.size()) {
TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
- Texture* texture = uniform_info->type == GL_SAMPLER_2D ?
+ TextureRef* texture_ref = uniform_info->type == GL_SAMPLER_2D ?
texture_unit.bound_texture_2d :
texture_unit.bound_texture_cube_map;
- if (!texture || !texture_manager()->CanRender(texture)) {
+ if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
glActiveTexture(GL_TEXTURE0 + texture_unit_index);
- // Get the texture info that was previously bound here.
- texture = texture_unit.bind_target == GL_TEXTURE_2D ?
+ // Get the texture_ref info that was previously bound here.
+ texture_ref = texture_unit.bind_target == GL_TEXTURE_2D ?
texture_unit.bound_texture_2d :
texture_unit.bound_texture_cube_map;
glBindTexture(texture_unit.bind_target,
- texture ? texture->service_id() : 0);
+ texture_ref ? texture_ref->service_id() : 0);
}
}
}
@@ -5719,10 +5730,10 @@
GLuint texture_unit_index = uniform_info->texture_units[jj];
if (texture_unit_index < state_.texture_units.size()) {
TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
- Texture* texture =
+ TextureRef* texture_ref =
texture_unit.GetInfoForSamplerType(uniform_info->type);
- if (texture && !texture->SafeToRenderFrom()) {
- if (!texture_manager()->ClearRenderableLevels(this, texture)) {
+ if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
+ if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
return false;
}
}
@@ -6418,8 +6429,8 @@
}
bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
- const Texture* texture = GetTexture(client_id);
- return texture && texture->IsValid() && !texture->IsDeleted();
+ const TextureRef* texture_ref = GetTexture(client_id);
+ return texture_ref && texture_ref->texture()->IsValid();
}
void GLES2DecoderImpl::DoAttachShader(
@@ -7336,7 +7347,7 @@
}
y += tile_height;
}
- Texture* texture = GetTextureInfoForTarget(bind_target);
+ TextureRef* texture = GetTextureInfoForTarget(bind_target);
glBindTexture(bind_target, texture ? texture->service_id() : 0);
return true;
}
@@ -7511,13 +7522,14 @@
"glCompressedTexImage2D", "dimensions out of range");
return error::kNoError;
}
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE,
"glCompressedTexImage2D", "unknown texture target");
return error::kNoError;
}
+ Texture* texture = texture_ref->texture();
if (texture->IsImmutable()) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -7540,9 +7552,6 @@
if (texture->IsAttachedToFramebuffer()) {
clear_state_dirty_ = true;
- // TODO(gman): If textures tracked which framebuffers they were attached to
- // we could just mark those framebuffers as not complete.
- framebuffer_manager()->IncFramebufferStateChangeCount();
}
scoped_ptr<int8[]> zero;
@@ -7557,8 +7566,8 @@
GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
if (error == GL_NO_ERROR) {
texture_manager()->SetLevelInfo(
- texture, target, level, internal_format, width, height, 1, border, 0, 0,
- true);
+ texture_ref, target, level, internal_format,
+ width, height, 1, border, 0, 0, true);
}
return error::kNoError;
}
@@ -7751,13 +7760,13 @@
function_name, "can not supply data for depth or stencil textures");
return false;
}
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, function_name, "unknown texture for target");
return false;
}
- if (texture->IsImmutable()) {
+ if (texture_ref->texture()->IsImmutable()) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, function_name, "texture is immutable");
return false;
@@ -7786,7 +7795,8 @@
return;
}
- Texture* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ Texture* texture = texture_ref->texture();
GLsizei tex_width = 0;
GLsizei tex_height = 0;
GLenum tex_type = 0;
@@ -7800,7 +7810,7 @@
if (level_is_same && !pixels) {
// Just set the level texture but mark the texture as uncleared.
texture_manager()->SetLevelInfo(
- texture,
+ texture_ref,
target, level, internal_format, width, height, 1, border, format, type,
false);
tex_image_2d_failed_ = false;
@@ -7809,14 +7819,11 @@
if (texture->IsAttachedToFramebuffer()) {
clear_state_dirty_ = true;
- // TODO(gman): If textures tracked which framebuffers they were attached to
- // we could just mark those framebuffers as not complete.
- framebuffer_manager()->IncFramebufferStateChangeCount();
}
if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
- texture_manager()->SetLevelCleared(texture, target, level, true);
+ texture_manager()->SetLevelCleared(texture_ref, target, level, true);
tex_image_2d_failed_ = false;
return;
}
@@ -7828,7 +7835,7 @@
GLenum error = LOCAL_PEEK_GL_ERROR("glTexImage2D");
if (error == GL_NO_ERROR) {
texture_manager()->SetLevelInfo(
- texture,
+ texture_ref,
target, level, internal_format, width, height, 1, border, format, type,
pixels != NULL);
tex_image_2d_failed_ = false;
@@ -7908,13 +7915,14 @@
GLenum format,
GLsizei image_size,
const void * data) {
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glCompressedTexSubImage2D", "unknown texture for target");
return;
}
+ Texture* texture = texture_ref->texture();
GLenum type = 0;
GLenum internal_format = 0;
if (!texture->GetLevelType(target, level, &type, &internal_format)) {
@@ -7980,13 +7988,14 @@
GLsizei height,
GLint border) {
DCHECK(!ShouldDeferReads());
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glCopyTexImage2D", "unknown texture for target");
return;
}
+ Texture* texture = texture_ref->texture();
if (texture->IsImmutable()) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
@@ -8044,9 +8053,6 @@
if (texture->IsAttachedToFramebuffer()) {
clear_state_dirty_ = true;
- // TODO(gman): If textures tracked which framebuffers they were attached to
- // we could just mark those framebuffers as not complete.
- framebuffer_manager()->IncFramebufferStateChangeCount();
}
// Clip to size to source dimensions
@@ -8086,7 +8092,7 @@
GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
if (error == GL_NO_ERROR) {
texture_manager()->SetLevelInfo(
- texture, target, level, internal_format, width, height, 1,
+ texture_ref, target, level, internal_format, width, height, 1,
border, internal_format, GL_UNSIGNED_BYTE, true);
}
}
@@ -8101,13 +8107,14 @@
GLsizei width,
GLsizei height) {
DCHECK(!ShouldDeferReads());
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glCopyTexSubImage2D", "unknown texture for target");
return;
}
+ Texture* texture = texture_ref->texture();
GLenum type = 0;
GLenum format = 0;
if (!texture->GetLevelType(target, level, &type, &format) ||
@@ -8156,7 +8163,7 @@
Clip(x, width, size.width(), ©X, ©Width);
Clip(y, height, size.height(), ©Y, ©Height);
- if (!texture_manager()->ClearTextureLevel(this, texture, target, level)) {
+ if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
return;
@@ -8226,13 +8233,14 @@
LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
return false;
}
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
function_name, "unknown texture for target");
return false;
}
+ Texture* texture = texture_ref->texture();
GLenum current_type = 0;
GLenum internal_format = 0;
if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
@@ -8292,14 +8300,16 @@
xoffset, yoffset, width, height, format, type, data)) {
return error;
}
- Texture* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ Texture* texture = texture_ref->texture();
GLsizei tex_width = 0;
GLsizei tex_height = 0;
bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
DCHECK(ok);
if (xoffset != 0 || yoffset != 0 ||
width != tex_width || height != tex_height) {
- if (!texture_manager()->ClearTextureLevel(this, texture, target, level)) {
+ if (!texture_manager()->ClearTextureLevel(this, texture_ref,
+ target, level)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
return error::kNoError;
@@ -8321,7 +8331,7 @@
glTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, type, data);
}
- texture_manager()->SetLevelCleared(texture, target, level, true);
+ texture_manager()->SetLevelCleared(texture_ref, target, level, true);
return error::kNoError;
}
@@ -8544,7 +8554,7 @@
result->success = 1; // true
- GLint range[2] = {0, 0};
+ GLint range[2] = { 0, 0 };
GLint precision = 0;
GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
@@ -8780,7 +8790,7 @@
} else {
// Flip the textures in the parent context via the texture manager.
if (!!offscreen_saved_color_texture_info_.get())
- offscreen_saved_color_texture_info_->
+ offscreen_saved_color_texture_info_->texture()->
SetServiceId(offscreen_target_color_texture_->id());
offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
@@ -9337,14 +9347,15 @@
if (!result)
return error::kOutOfBounds;
*result = GL_ZERO;
- Texture* texture = texture_manager()->GetTexture(client_id);
- if (!texture) {
+ TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE,
"glCreateStreamTextureCHROMIUM", "bad texture id.");
return error::kNoError;
}
+ Texture* texture = texture_ref->texture();
if (texture->IsStreamTexture()) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -9367,7 +9378,7 @@
texture->service_id(), client_id);
if (object_id) {
- texture->SetStreamTexture(true);
+ texture_manager()->SetStreamTexture(texture_ref, true);
} else {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY,
@@ -9382,13 +9393,13 @@
uint32 immediate_data_size,
const cmds::DestroyStreamTextureCHROMIUM& c) {
GLuint client_id = c.texture;
- Texture* texture = texture_manager()->GetTexture(client_id);
- if (texture && texture->IsStreamTexture()) {
+ TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
+ if (texture_ref && texture_ref->texture()->IsStreamTexture()) {
if (!stream_texture_manager_)
return error::kInvalidArguments;
- stream_texture_manager_->DestroyStreamTexture(texture->service_id());
- texture->SetStreamTexture(false);
+ stream_texture_manager_->DestroyStreamTexture(texture_ref->service_id());
+ texture_manager()->SetStreamTexture(texture_ref, false);
} else {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE,
@@ -9444,8 +9455,8 @@
// Default target might be conceptually valid, but disallow it to avoid
// accidents.
- Texture* texture = GetTextureInfoForTargetUnlessDefault(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
@@ -9466,11 +9477,11 @@
}
// Release any IOSurface previously bound to this texture.
- ReleaseIOSurfaceForTexture(texture->service_id());
+ ReleaseIOSurfaceForTexture(texture_ref->service_id());
// Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
texture_to_io_surface_map_.insert(
- std::make_pair(texture->service_id(), surface));
+ std::make_pair(texture_ref->service_id(), surface));
CGLContextObj context =
static_cast<CGLContextObj>(context_->GetHandle());
@@ -9494,7 +9505,7 @@
}
texture_manager()->SetLevelInfo(
- texture, target, 0, GL_RGBA, width, height, 1, 0,
+ texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
#else
@@ -9551,10 +9562,10 @@
void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
GLenum target, GLuint source_id, GLuint dest_id, GLint level,
GLenum internal_format, GLenum dest_type) {
- Texture* dest_texture = GetTexture(dest_id);
- Texture* source_texture = GetTexture(source_id);
+ TextureRef* dest_texture_ref = GetTexture(dest_id);
+ TextureRef* source_texture_ref = GetTexture(source_id);
- if (!source_texture || !dest_texture) {
+ if (!source_texture_ref || !dest_texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
return;
@@ -9566,6 +9577,8 @@
return;
}
+ Texture* source_texture = source_texture_ref->texture();
+ Texture* dest_texture = dest_texture_ref->texture();
if (dest_texture->target() != GL_TEXTURE_2D ||
(source_texture->target() != GL_TEXTURE_2D &&
source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
@@ -9657,11 +9670,11 @@
}
texture_manager()->SetLevelInfo(
- dest_texture, GL_TEXTURE_2D, level, internal_format, source_width,
+ dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
source_height, 1, 0, internal_format, dest_type, true);
} else {
texture_manager()->SetLevelCleared(
- dest_texture, GL_TEXTURE_2D, level, true);
+ dest_texture_ref, GL_TEXTURE_2D, level, true);
}
// GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
@@ -9756,13 +9769,14 @@
GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
return;
}
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glTexStorage2DEXT", "unknown texture for target");
return;
}
+ Texture* texture = texture_ref->texture();
if (texture->IsAttachedToFramebuffer()) {
clear_state_dirty_ = true;
}
@@ -9808,8 +9822,8 @@
GLsizei level_height = height;
for (int ii = 0; ii < levels; ++ii) {
texture_manager()->SetLevelInfo(
- texture, target, ii, format, level_width, level_height, 1, 0, format,
- type, false);
+ texture_ref, target, ii, format,
+ level_width, level_height, 1, 0, format, type, false);
level_width = std::max(1, level_width >> 1);
level_height = std::max(1, level_height >> 1);
}
@@ -9836,15 +9850,15 @@
"context", logger_.GetLogPrefix(),
"mailbox[0]", static_cast<unsigned char>(mailbox[0]));
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glProduceTextureCHROMIUM", "unknown texture for target");
return;
}
- TextureDefinition* definition = texture_manager()->Save(texture);
+ TextureDefinition* definition = texture_manager()->Save(texture_ref);
if (!definition) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -9858,7 +9872,7 @@
definition,
texture_manager())) {
bool success = texture_manager()->Restore(
- "glProductTextureCHROMIUM", this, texture, definition);
+ "glProductTextureCHROMIUM", this, texture_ref, definition);
DCHECK(success);
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -9866,7 +9880,7 @@
return;
}
- glBindTexture(texture->target(), texture->service_id());
+ glBindTexture(texture_ref->texture()->target(), texture_ref->service_id());
}
void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
@@ -9875,8 +9889,8 @@
"context", logger_.GetLogPrefix(),
"mailbox[0]", static_cast<unsigned char>(mailbox[0]));
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glConsumeTextureCHROMIUM", "unknown texture for target");
@@ -9895,7 +9909,7 @@
}
if (!texture_manager()->Restore(
- "glConsumeTextureCHROMIUM", this, texture, definition.release())) {
+ "glConsumeTextureCHROMIUM", this, texture_ref, definition.release())) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glConsumeTextureCHROMIUM", "invalid texture");
@@ -9938,8 +9952,8 @@
// Default target might be conceptually valid, but disallow it to avoid
// accidents.
- Texture* texture = GetTextureInfoForTargetUnlessDefault(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glBindTexImage2DCHROMIUM", "no texture bound");
@@ -9967,9 +9981,9 @@
gfx::Size size = gl_image->GetSize();
texture_manager()->SetLevelInfo(
- texture, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
+ texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
GL_RGBA, GL_UNSIGNED_BYTE, true);
- texture_manager()->SetLevelImage(texture, target, 0, gl_image);
+ texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
}
void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
@@ -9985,8 +9999,8 @@
// Default target might be conceptually valid, but disallow it to avoid
// accidents.
- Texture* texture = GetTextureInfoForTargetUnlessDefault(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glReleaseTexImage2DCHROMIUM", "no texture bound");
@@ -10002,7 +10016,7 @@
}
// Do nothing when image is not currently bound.
- if (texture->GetLevelImage(target, 0) != gl_image)
+ if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
return;
{
@@ -10012,7 +10026,7 @@
}
texture_manager()->SetLevelInfo(
- texture, target, 0, GL_RGBA, 0, 0, 1, 0,
+ texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
GL_RGBA, GL_UNSIGNED_BYTE, false);
}
@@ -10159,7 +10173,8 @@
}
// Extra async validation.
- Texture* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ Texture* texture = texture_ref->texture();
if (!ValidateAsyncTransfer(
"glAsyncTexImage2DCHROMIUM", texture, target, level, pixels))
return error::kNoError;
@@ -10172,15 +10187,6 @@
return error::kNoError;
}
- // Since we don't allow async redefinition, this is the only
- // time the size of this texture can change while bound
- // as a frame-buffer.
- if (texture->IsAttachedToFramebuffer()) {
- // TODO(gman): If textures tracked which framebuffers they were attached to
- // we could just mark those framebuffers as not complete.
- framebuffer_manager()->IncFramebufferStateChangeCount();
- }
-
if (!EnsureGPUMemoryAvailable(pixels_size)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
@@ -10206,7 +10212,7 @@
// immutable so the async state stays valid. The level info
// is set up lazily when the transfer completes.
DCHECK(!texture->GetAsyncTransferState());
- texture->SetAsyncTransferState(
+ texture_ref->SetAsyncTransferState(
make_scoped_ptr(
async_pixel_transfer_delegate_->CreatePixelTransferState(
texture->service_id(),
@@ -10218,11 +10224,11 @@
tex_params,
mem_params,
base::Bind(&TextureManager::SetLevelInfoFromParams,
- // The callback is only invoked if the transfer state
- // still exists, which implies through manager->info->state
+ // The callback is only invoked if the transfer delegate still
+ // exists, which implies through manager->texture_ref->state
// ownership that both of these pointers are valid.
base::Unretained(texture_manager()),
- base::Unretained(texture),
+ base::Unretained(texture_ref),
tex_params));
return error::kNoError;
}
@@ -10258,7 +10264,8 @@
}
// Extra async validation.
- Texture* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ Texture* texture = texture_ref->texture();
if (!ValidateAsyncTransfer(
"glAsyncTexSubImage2DCHROMIUM", texture, target, level, pixels))
return error::kNoError;
@@ -10270,7 +10277,8 @@
// - Textures become immutable after an async call.
// This way we know in all cases that an async texture is always clear.
if (!texture->SafeToRenderFrom()) {
- if (!texture_manager()->ClearTextureLevel(this, texture, target, level)) {
+ if (!texture_manager()->ClearTextureLevel(this, texture_ref,
+ target, level)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY,
"glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
@@ -10291,7 +10299,8 @@
width, height, format, type};
AsyncMemoryParams mem_params = {shared_memory, shm_size,
shm_data_offset, shm_data_size};
- if (!texture->GetAsyncTransferState()) {
+ AsyncPixelTransferState* state = texture->GetAsyncTransferState();
+ if (!state) {
// TODO(epenner): We may want to enforce exclusive use
// of async APIs in which case this should become an error,
// (the texture should have been async defined).
@@ -10303,16 +10312,15 @@
&define_params.internal_format);
// Set up the async state if needed, and make the texture
// immutable so the async state stays valid.
- texture->SetAsyncTransferState(
- make_scoped_ptr(
- async_pixel_transfer_delegate_->CreatePixelTransferState(
- texture->service_id(),
- define_params)));
+ state = async_pixel_transfer_delegate_->CreatePixelTransferState(
+ texture->service_id(),
+ define_params);
+ texture_ref->SetAsyncTransferState(make_scoped_ptr(state));
texture->SetImmutable(true);
}
async_pixel_transfer_delegate_->AsyncTexSubImage2D(
- texture->GetAsyncTransferState(), tex_params, mem_params);
+ state, tex_params, mem_params);
return error::kNoError;
}
@@ -10326,15 +10334,22 @@
GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
return error::kNoError;
}
- Texture* texture = GetTextureInfoForTarget(target);
- if (!texture) {
+ TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
return error::kNoError;
}
- async_pixel_transfer_delegate_->WaitForTransferCompletion(
- texture->GetAsyncTransferState());
+ AsyncPixelTransferState* state =
+ texture_ref->texture()->GetAsyncTransferState();
+ if (!state) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION,
+ "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
+ return error::kNoError;
+ }
+ async_pixel_transfer_delegate_->WaitForTransferCompletion(state);
ProcessFinishedAsyncTransfers();
return error::kNoError;
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 14c82f0..86d4801 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -173,7 +173,7 @@
// Sets a callback which is called when a glResizeCHROMIUM command
// is processed.
virtual void SetResizeCallback(
- const base::Callback<void(gfx::Size)>& callback) = 0;
+ const base::Callback<void(gfx::Size, float)>& callback) = 0;
virtual void SetStreamTextureManager(StreamTextureManager* manager) = 0;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 12d1cbd..3f714bd 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -68,7 +68,8 @@
MOCK_CONST_METHOD1(RestoreTextureUnitBindings, void(unsigned unit));
MOCK_METHOD0(GetQueryManager, gpu::gles2::QueryManager*());
MOCK_METHOD0(GetVertexArrayManager, gpu::gles2::VertexArrayManager*());
- MOCK_METHOD1(SetResizeCallback, void(const base::Callback<void(gfx::Size)>&));
+ MOCK_METHOD1(
+ SetResizeCallback, void(const base::Callback<void(gfx::Size, float)>&));
MOCK_METHOD1(SetStreamTextureManager, void(StreamTextureManager*));
MOCK_METHOD0(GetAsyncPixelTransferDelegate,
AsyncPixelTransferDelegate*());
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 2292b8b..cd62780 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -1822,8 +1822,9 @@
TEST_F(GLES2DecoderTest, GenerateMipmapHandlesOutOfMemory) {
DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
TextureManager* manager = group().texture_manager();
- Texture* texture = manager->GetTexture(client_texture_id_);
- ASSERT_TRUE(texture != NULL);
+ TextureRef* texture_ref = manager->GetTexture(client_texture_id_);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
GLint width = 0;
GLint height = 0;
EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 2, &width, &height));
@@ -4726,8 +4727,9 @@
GLenum type = GL_UNSIGNED_BYTE;
DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
TextureManager* manager = group().texture_manager();
- Texture* texture = manager->GetTexture(client_texture_id_);
- ASSERT_TRUE(texture != NULL);
+ TextureRef* texture_ref = manager->GetTexture(client_texture_id_);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, level, &width, &height));
EXPECT_CALL(*gl_, GetError())
.WillOnce(Return(GL_NO_ERROR))
@@ -4776,8 +4778,9 @@
GLint border = 0;
DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
TextureManager* manager = group().texture_manager();
- Texture* texture = manager->GetTexture(client_texture_id_);
- ASSERT_TRUE(texture != NULL);
+ TextureRef* texture_ref = manager->GetTexture(client_texture_id_);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, level, &width, &height));
EXPECT_CALL(*gl_, GetError())
.WillOnce(Return(GL_NO_ERROR))
@@ -5307,8 +5310,9 @@
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
// Test TexSubImage not allowed for ETC1 compressed texture
- Texture* texture = GetTexture(client_texture_id_);
- ASSERT_TRUE(texture != NULL);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
GLenum type, internal_format;
EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format));
EXPECT_EQ(kFormat, internal_format);
@@ -5417,9 +5421,9 @@
cmd.Init(GL_TEXTURE_EXTERNAL_OES, kNewClientId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- Texture* texture = GetTexture(kNewClientId);
- EXPECT_TRUE(texture != NULL);
- EXPECT_TRUE(texture->target() == GL_TEXTURE_EXTERNAL_OES);
+ TextureRef* texture_ref = GetTexture(kNewClientId);
+ EXPECT_TRUE(texture_ref != NULL);
+ EXPECT_TRUE(texture_ref->texture()->target() == GL_TEXTURE_EXTERNAL_OES);
}
TEST_F(GLES2DecoderManualInitTest, EGLImageExternalGetBinding) {
@@ -5467,8 +5471,9 @@
true); // bind generates resource
DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId);
- Texture* texture = GetTexture(client_texture_id_);
- EXPECT_TRUE(texture != NULL);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ EXPECT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
EXPECT_TRUE(texture->target() == GL_TEXTURE_EXTERNAL_OES);
EXPECT_TRUE(texture->min_filter() == GL_LINEAR);
EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE);
@@ -5525,8 +5530,9 @@
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- Texture* texture = GetTexture(client_texture_id_);
- EXPECT_TRUE(texture != NULL);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ EXPECT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
EXPECT_TRUE(texture->target() == GL_TEXTURE_EXTERNAL_OES);
EXPECT_TRUE(texture->min_filter() == GL_LINEAR);
EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE);
@@ -5565,8 +5571,9 @@
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
- Texture* texture = GetTexture(client_texture_id_);
- EXPECT_TRUE(texture != NULL);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ EXPECT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
EXPECT_TRUE(texture->target() == GL_TEXTURE_EXTERNAL_OES);
EXPECT_TRUE(texture->min_filter() == GL_LINEAR);
EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE);
@@ -5658,9 +5665,9 @@
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(kObjectId, *result);
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- Texture* texture = GetTexture(client_texture_id_);
- EXPECT_TRUE(texture != NULL);
- EXPECT_TRUE(texture->IsStreamTexture());
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ EXPECT_TRUE(texture_ref != NULL);
+ EXPECT_TRUE(texture_ref->texture()->IsStreamTexture());
}
TEST_F(GLES2DecoderManualInitTest, CreateStreamTextureCHROMIUMBadId) {
@@ -5715,8 +5722,8 @@
false, // request stencil
true); // bind generates resource
- Texture* texture = GetTexture(client_texture_id_);
- texture->SetStreamTexture(true);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ group().texture_manager()->SetStreamTexture(texture_ref, true);
CreateStreamTextureCHROMIUM cmd;
cmd.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_);
@@ -5739,8 +5746,8 @@
StrictMock<MockStreamTexture> stream_texture;
decoder_->SetStreamTextureManager(&manager);
- Texture* texture = GetTexture(client_texture_id_);
- texture->SetStreamTexture(true);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ group().texture_manager()->SetStreamTexture(texture_ref, true);
EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_EXTERNAL_OES, kServiceTextureId))
.Times(1)
@@ -5769,8 +5776,8 @@
false, // request stencil
true); // bind generates resource
- Texture* texture = GetTexture(client_texture_id_);
- texture->SetStreamTexture(true);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ group().texture_manager()->SetStreamTexture(texture_ref, true);
BindTexture cmd;
cmd.Init(GL_TEXTURE_2D, client_texture_id_);
@@ -5797,8 +5804,8 @@
StrictMock<MockStreamTextureManager> manager;
decoder_->SetStreamTextureManager(&manager);
- Texture* texture = GetTexture(client_texture_id_);
- texture->SetStreamTexture(true);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ group().texture_manager()->SetStreamTexture(texture_ref, true);
EXPECT_CALL(manager, DestroyStreamTexture(kServiceTextureId))
.Times(1)
@@ -5808,8 +5815,8 @@
cmd.Init(client_texture_id_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- EXPECT_FALSE(texture->IsStreamTexture());
- EXPECT_EQ(0U, texture->target());
+ EXPECT_FALSE(texture_ref->texture()->IsStreamTexture());
+ EXPECT_EQ(0U, texture_ref->texture()->target());
}
TEST_F(GLES2DecoderManualInitTest, DestroyStreamTextureCHROMIUMInvalid) {
@@ -5823,8 +5830,8 @@
false, // request stencil
true); // bind generates resource
- Texture* texture = GetTexture(client_texture_id_);
- texture->SetStreamTexture(false);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ group().texture_manager()->SetStreamTexture(texture_ref, false);
DestroyStreamTextureCHROMIUM cmd;
cmd.Init(client_texture_id_);
@@ -5865,8 +5872,8 @@
EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd));
GetGLError(); // ignore internal error
- Texture* texture = GetTexture(client_texture_id_);
- texture->SetStreamTexture(true);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ group().texture_manager()->SetStreamTexture(texture_ref, true);
DestroyStreamTextureCHROMIUM cmd2;
cmd2.Init(client_texture_id_);
@@ -5904,8 +5911,8 @@
.WillOnce(Return(kObjectId))
.RetiresOnSaturation();
- Texture* texture = GetTexture(client_texture_id_);
- texture->SetStreamTexture(true);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ group().texture_manager()->SetStreamTexture(texture_ref, true);
DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId);
EXPECT_EQ(GL_NO_ERROR, GetGLError());
@@ -5914,13 +5921,13 @@
cmd.Init(client_texture_id_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- EXPECT_FALSE(texture->IsStreamTexture());
+ EXPECT_FALSE(texture_ref->texture()->IsStreamTexture());
CreateStreamTextureCHROMIUM cmd2;
cmd2.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- EXPECT_TRUE(texture->IsStreamTexture());
+ EXPECT_TRUE(texture_ref->texture()->IsStreamTexture());
}
TEST_F(GLES2DecoderManualInitTest, ProduceAndConsumeStreamTextureCHROMIUM) {
@@ -5938,8 +5945,8 @@
StrictMock<MockStreamTexture> stream_texture;
decoder_->SetStreamTextureManager(&manager);
- Texture* texture = GetTexture(client_texture_id_);
- texture->SetStreamTexture(true);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ group().texture_manager()->SetStreamTexture(texture_ref, true);
EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_EXTERNAL_OES, kServiceTextureId))
.Times(1)
@@ -5962,7 +5969,7 @@
memcpy(shared_memory_address_, mailbox, sizeof(mailbox));
- EXPECT_EQ(kServiceTextureId, texture->service_id());
+ EXPECT_EQ(kServiceTextureId, texture_ref->service_id());
// Assigns and binds new service side texture ID.
EXPECT_CALL(*gl_, GenTextures(1, _))
@@ -6019,7 +6026,7 @@
EXPECT_EQ(GL_NO_ERROR, GetGLError());
// Service ID is restored.
- EXPECT_EQ(kServiceTextureId, texture->service_id());
+ EXPECT_EQ(kServiceTextureId, texture_ref->service_id());
}
TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleBindTexture) {
@@ -6039,7 +6046,7 @@
cmd.Init(GL_TEXTURE_RECTANGLE_ARB, kNewClientId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- Texture* texture = GetTexture(kNewClientId);
+ Texture* texture = GetTexture(kNewClientId)->texture();
EXPECT_TRUE(texture != NULL);
EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB);
}
@@ -6091,7 +6098,7 @@
DoBindTexture(
GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId);
- Texture* texture = GetTexture(client_texture_id_);
+ Texture* texture = GetTexture(client_texture_id_)->texture();
EXPECT_TRUE(texture != NULL);
EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB);
EXPECT_TRUE(texture->min_filter() == GL_LINEAR);
@@ -6150,7 +6157,7 @@
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- Texture* texture = GetTexture(client_texture_id_);
+ Texture* texture = GetTexture(client_texture_id_)->texture();
EXPECT_TRUE(texture != NULL);
EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB);
EXPECT_TRUE(texture->min_filter() == GL_LINEAR);
@@ -6191,7 +6198,7 @@
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
- Texture* texture = GetTexture(client_texture_id_);
+ Texture* texture = GetTexture(client_texture_id_)->texture();
EXPECT_TRUE(texture != NULL);
EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB);
EXPECT_TRUE(texture->min_filter() == GL_LINEAR);
@@ -6522,7 +6529,9 @@
DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
TextureManager* manager = group().texture_manager();
- Texture* texture = manager->GetTexture(client_texture_id_);
+ TextureRef* texture_ref = manager->GetTexture(client_texture_id_);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
EXPECT_CALL(*gl_, GetError())
.WillOnce(Return(GL_NO_ERROR))
@@ -6583,8 +6592,8 @@
8, kSharedMemoryId, kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
TextureManager* manager = group().texture_manager();
- Texture* texture = manager->GetTexture(client_texture_id_);
- EXPECT_TRUE(texture->SafeToRenderFrom());
+ TextureRef* texture_ref = manager->GetTexture(client_texture_id_);
+ EXPECT_TRUE(texture_ref->texture()->SafeToRenderFrom());
}
TEST_F(GLES2DecoderWithShaderTest, UnClearedAttachmentsGetClearedOnClear) {
@@ -7390,7 +7399,10 @@
0, 0);
DoTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
0, 0);
- Texture* texture = group().texture_manager()->GetTexture(client_texture_id_);
+ TextureRef* texture_ref = group().texture_manager()->GetTexture(
+ client_texture_id_);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
EXPECT_EQ(kServiceTextureId, texture->service_id());
// Assigns and binds new service side texture ID.
@@ -7992,7 +8004,10 @@
DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
0, 0);
- Texture* texture = group().texture_manager()->GetTexture(client_texture_id_);
+ TextureRef* texture_ref = group().texture_manager()->GetTexture(
+ client_texture_id_);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
EXPECT_EQ(kServiceTextureId, texture->service_id());
group().image_manager()->AddImage(gfx::GLImage::CreateGLImage(0), 1);
@@ -8036,7 +8051,10 @@
DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
0, 0);
- Texture* texture = group().texture_manager()->GetTexture(client_texture_id_);
+ TextureRef* texture_ref = group().texture_manager()->GetTexture(
+ client_texture_id_);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
EXPECT_EQ(kServiceTextureId, texture->service_id());
group().image_manager()->AddImage(gfx::GLImage::CreateGLImage(0), 1);
@@ -8093,7 +8111,7 @@
false, // request stencil
true); // bind generates resource
- Texture* texture = GetTexture(client_texture_id_);
+ Texture* texture = GetTexture(client_texture_id_)->texture();
EXPECT_TRUE(texture != NULL);
EXPECT_TRUE(texture->pool() == GL_TEXTURE_POOL_UNMANAGED_CHROMIUM);
@@ -8131,7 +8149,8 @@
// Set up the texture.
DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
- Texture* texture = GetTexture(client_texture_id_);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+ Texture* texture = texture_ref->texture();
// Set a mock Async delegate
StrictMock<gpu::MockAsyncPixelTransferDelegate>* delegate =
@@ -8203,7 +8222,7 @@
}
// AsyncTexSubImage2D
- texture->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
+ texture_ref->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
texture->SetImmutable(false);
{
// Create transfer state since it doesn't exist.
@@ -8254,11 +8273,12 @@
// asynchronously and AsyncTexSubImage2D does not involved binding.
EXPECT_CALL(*gl_, GenTextures(1, _))
.WillOnce(SetArgumentPointee<1>(kServiceTextureId));
- texture->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
+ texture_ref->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
DoDeleteTexture(client_texture_id_, kServiceTextureId);
DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
- texture = GetTexture(client_texture_id_);
- texture->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
+ texture_ref = GetTexture(client_texture_id_);
+ texture = texture_ref->texture();
+ texture_ref->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
texture->SetImmutable(false);
// Create transfer state since it doesn't exist.
EXPECT_CALL(*delegate, CreatePixelTransferState(kServiceTextureId, _))
@@ -8280,7 +8300,7 @@
}
decoder_->SetAsyncPixelTransferDelegate(NULL);
- texture->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
+ texture_ref->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
}
namespace {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index c4db9f2..55dc7e4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -111,7 +111,7 @@
return group_->renderbuffer_manager()->GetRenderbuffer(service_id);
}
- Texture* GetTexture(GLuint client_id) {
+ TextureRef* GetTexture(GLuint client_id) {
return group_->texture_manager()->GetTexture(client_id);
}
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc
index 82f22c5..24de4d2 100644
--- a/gpu/command_buffer/service/gpu_scheduler.cc
+++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -45,7 +45,9 @@
}
void GpuScheduler::PutChanged() {
- TRACE_EVENT1("gpu", "GpuScheduler:PutChanged", "this", this);
+ TRACE_EVENT1(
+ "gpu", "GpuScheduler:PutChanged",
+ "decoder", decoder_ ? decoder_->GetLogger()->GetLogPrefix() : "None");
CommandBuffer::State state = command_buffer_->GetState();
diff --git a/gpu/command_buffer/service/gpu_switches.cc b/gpu/command_buffer/service/gpu_switches.cc
index 6d699ad..221dd60 100644
--- a/gpu/command_buffer/service/gpu_switches.cc
+++ b/gpu/command_buffer/service/gpu_switches.cc
@@ -62,6 +62,10 @@
// Disables the GPU shader on disk cache.
const char kDisableGpuShaderDiskCache[] = "disable-gpu-shader-disk-cache";
+// Allows async texture uploads (off main thread) via GL context sharing.
+const char kEnableShareGroupAsyncTextureUpload[] =
+ "enable-share-group-async-texture-upload";
+
const char* kGpuSwitches[] = {
kCompileShaderAlwaysSucceeds,
kDisableGLErrorLimit,
@@ -80,6 +84,7 @@
kGpuProgramCacheSizeKb,
kTraceGL,
kDisableGpuShaderDiskCache,
+ kEnableShareGroupAsyncTextureUpload,
};
const int kNumGpuSwitches = arraysize(kGpuSwitches);
diff --git a/gpu/command_buffer/service/gpu_switches.h b/gpu/command_buffer/service/gpu_switches.h
index ba6f804..7634c57 100644
--- a/gpu/command_buffer/service/gpu_switches.h
+++ b/gpu/command_buffer/service/gpu_switches.h
@@ -28,6 +28,7 @@
GPU_EXPORT extern const char kGpuProgramCacheSizeKb[];
GPU_EXPORT extern const char kTraceGL[];
GPU_EXPORT extern const char kDisableGpuShaderDiskCache[];
+GPU_EXPORT extern const char kEnableShareGroupAsyncTextureUpload[];
GPU_EXPORT extern const char* kGpuSwitches[];
GPU_EXPORT extern const int kNumGpuSwitches;
diff --git a/gpu/command_buffer/service/logger.cc b/gpu/command_buffer/service/logger.cc
index 54b0233..b985e5e 100644
--- a/gpu/command_buffer/service/logger.cc
+++ b/gpu/command_buffer/service/logger.cc
@@ -18,7 +18,8 @@
log_message_count_(0),
log_synthesized_gl_errors_(true) {
Logger* this_temp = this;
- this_in_hex_ = base::HexEncode(&this_temp, sizeof(this_temp));
+ this_in_hex_ = std::string("GroupMarkerNotSet(crbug.com/242999)!:") +
+ base::HexEncode(&this_temp, sizeof(this_temp));
}
Logger::~Logger() {}
@@ -28,15 +29,16 @@
if (log_message_count_ < kMaxLogMessages ||
CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGLErrorLimit)) {
+ std::string prefixed_msg(std::string("[") + GetLogPrefix() + "]" + msg);
++log_message_count_;
// LOG this unless logging is turned off as any chromium code that
// generates these errors probably has a bug.
if (log_synthesized_gl_errors_) {
::logging::LogMessage(
- filename, line, ::logging::LOG_ERROR).stream() << msg;
+ filename, line, ::logging::LOG_ERROR).stream() << prefixed_msg;
}
if (!msg_callback_.is_null()) {
- msg_callback_.Run(0, msg);
+ msg_callback_.Run(0, prefixed_msg);
}
} else {
if (log_message_count_ == kMaxLogMessages) {
diff --git a/gpu/command_buffer/service/memory_program_cache.cc b/gpu/command_buffer/service/memory_program_cache.cc
index d9d944d..2582a49 100644
--- a/gpu/command_buffer/service/memory_program_cache.cc
+++ b/gpu/command_buffer/service/memory_program_cache.cc
@@ -107,13 +107,17 @@
ProgramCache::ProgramLoadResult MemoryProgramCache::LoadLinkedProgram(
GLuint program,
Shader* shader_a,
+ const ShaderTranslatorInterface* translator_a,
Shader* shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) const {
char a_sha[kHashLength];
char b_sha[kHashLength];
- ComputeShaderHash(*shader_a->deferred_compilation_source(), a_sha);
- ComputeShaderHash(*shader_b->deferred_compilation_source(), b_sha);
+ ComputeShaderHash(
+ *shader_a->deferred_compilation_source(), translator_a, a_sha);
+ ComputeShaderHash(
+ *shader_b->deferred_compilation_source(), translator_b, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
@@ -160,7 +164,9 @@
void MemoryProgramCache::SaveLinkedProgram(
GLuint program,
const Shader* shader_a,
+ const ShaderTranslatorInterface* translator_a,
const Shader* shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) {
GLenum format;
@@ -179,8 +185,10 @@
char a_sha[kHashLength];
char b_sha[kHashLength];
- ComputeShaderHash(*shader_a->deferred_compilation_source(), a_sha);
- ComputeShaderHash(*shader_b->deferred_compilation_source(), b_sha);
+ ComputeShaderHash(
+ *shader_a->deferred_compilation_source(), translator_a, a_sha);
+ ComputeShaderHash(
+ *shader_b->deferred_compilation_source(), translator_b, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
diff --git a/gpu/command_buffer/service/memory_program_cache.h b/gpu/command_buffer/service/memory_program_cache.h
index 7d5f808..ed791a8 100644
--- a/gpu/command_buffer/service/memory_program_cache.h
+++ b/gpu/command_buffer/service/memory_program_cache.h
@@ -29,13 +29,17 @@
virtual ProgramLoadResult LoadLinkedProgram(
GLuint program,
Shader* shader_a,
+ const ShaderTranslatorInterface* translator_a,
Shader* shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) const OVERRIDE;
virtual void SaveLinkedProgram(
GLuint program,
const Shader* shader_a,
+ const ShaderTranslatorInterface* translator_a,
const Shader* shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) OVERRIDE;
diff --git a/gpu/command_buffer/service/memory_program_cache_unittest.cc b/gpu/command_buffer/service/memory_program_cache_unittest.cc
index b083552..603c21e 100644
--- a/gpu/command_buffer/service/memory_program_cache_unittest.cc
+++ b/gpu/command_buffer/service/memory_program_cache_unittest.cc
@@ -96,8 +96,8 @@
::gfx::GLInterface::SetGLInterface(gl_.get());
vertex_shader_ = shader_manager_.CreateShader(kVertexShaderClientId,
- kVertexShaderServiceId,
- GL_VERTEX_SHADER);
+ kVertexShaderServiceId,
+ GL_VERTEX_SHADER);
fragment_shader_ = shader_manager_.CreateShader(
kFragmentShaderClientId,
kFragmentShaderServiceId,
@@ -196,13 +196,16 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
*vertex_shader_->deferred_compilation_source(),
+ NULL,
*fragment_shader_->deferred_compilation_source(),
+ NULL,
NULL));
EXPECT_EQ(1, shader_cache_count());
}
@@ -218,13 +221,16 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
*vertex_shader_->deferred_compilation_source(),
+ NULL,
*fragment_shader_->deferred_compilation_source(),
+ NULL,
NULL));
EXPECT_EQ(1, shader_cache_count());
@@ -233,7 +239,9 @@
cache_->LoadProgram(shader_cache_shader());
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
*vertex_shader_->deferred_compilation_source(),
+ NULL,
*fragment_shader_->deferred_compilation_source(),
+ NULL,
NULL));
}
@@ -248,7 +256,8 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(1, shader_cache_count());
@@ -268,8 +277,10 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
NULL,
+ NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
@@ -294,7 +305,8 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(1, shader_cache_count());
@@ -317,8 +329,10 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
NULL,
+ NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
@@ -343,7 +357,8 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -351,8 +366,10 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
NULL,
+ NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
}
@@ -368,7 +385,8 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -379,8 +397,10 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
NULL,
+ NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
@@ -391,8 +411,10 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
NULL,
+ NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
}
@@ -412,7 +434,9 @@
binding_map["test"] = 512;
cache_->SaveLinkedProgram(kProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
+ NULL,
&binding_map,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -421,15 +445,19 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
+ NULL,
&binding_map,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
NULL,
+ NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
}
@@ -447,7 +475,8 @@
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -472,18 +501,24 @@
SetExpectationsForSaveLinkedProgram(kEvictingProgramId, &emulator2);
cache_->SaveLinkedProgram(kEvictingProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
NULL,
+ NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
*vertex_shader_->deferred_compilation_source(),
+ NULL,
*fragment_shader_->deferred_compilation_source(),
+ NULL,
NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN, cache_->GetLinkedProgramStatus(
old_source,
+ NULL,
*fragment_shader_->deferred_compilation_source(),
+ NULL,
NULL));
}
@@ -499,13 +534,16 @@
vertex_shader_->UpdateSource("different!");
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
*vertex_shader_->deferred_compilation_source(),
+ NULL,
*fragment_shader_->deferred_compilation_source(),
+ NULL,
NULL));
}
@@ -520,13 +558,16 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
*vertex_shader_->deferred_compilation_source(),
+ NULL,
*fragment_shader_->deferred_compilation_source(),
+ NULL,
NULL));
SetExpectationsForLoadLinkedProgram(kProgramId, &emulator);
@@ -535,8 +576,10 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
NULL,
+ NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
}
@@ -552,7 +595,8 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -563,7 +607,8 @@
}
ProgramBinaryEmulator emulator2(kBinaryLength, kFormat, test_binary2);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator2);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
+ fragment_shader_, NULL, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -571,8 +616,10 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
+ NULL,
fragment_shader_,
NULL,
+ NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
}
diff --git a/gpu/command_buffer/service/mocks.h b/gpu/command_buffer/service/mocks.h
index 0964ada..11b8ae6 100644
--- a/gpu/command_buffer/service/mocks.h
+++ b/gpu/command_buffer/service/mocks.h
@@ -91,6 +91,8 @@
MOCK_CONST_METHOD0(attrib_map, const VariableMap&());
MOCK_CONST_METHOD0(uniform_map, const VariableMap&());
MOCK_CONST_METHOD0(name_map, const NameMap&());
+ MOCK_CONST_METHOD0(
+ GetStringForOptionsThatWouldEffectCompilation, std::string());
};
class MockProgramCache : public ProgramCache {
@@ -98,17 +100,21 @@
MockProgramCache();
virtual ~MockProgramCache();
- MOCK_CONST_METHOD5(LoadLinkedProgram, ProgramLoadResult(
+ MOCK_CONST_METHOD7(LoadLinkedProgram, ProgramLoadResult(
GLuint program,
Shader* shader_a,
+ const ShaderTranslatorInterface* translator_a,
Shader* shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& callback));
- MOCK_METHOD5(SaveLinkedProgram, void(
+ MOCK_METHOD7(SaveLinkedProgram, void(
GLuint program,
const Shader* shader_a,
+ const ShaderTranslatorInterface* translator_a,
const Shader* shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& callback));
MOCK_METHOD1(LoadProgram, void(const std::string&));
diff --git a/gpu/command_buffer/service/program_cache.cc b/gpu/command_buffer/service/program_cache.cc
index 48fafab..62e636d 100644
--- a/gpu/command_buffer/service/program_cache.cc
+++ b/gpu/command_buffer/service/program_cache.cc
@@ -4,6 +4,7 @@
#include "gpu/command_buffer/service/program_cache.h"
+#include <string>
#include "base/memory/scoped_ptr.h"
#include "gpu/command_buffer/service/shader_manager.h"
@@ -20,9 +21,10 @@
}
ProgramCache::CompiledShaderStatus ProgramCache::GetShaderCompilationStatus(
- const std::string& shader_src) const {
+ const std::string& shader_src,
+ const ShaderTranslatorInterface* translator) const {
char sha[kHashLength];
- ComputeShaderHash(shader_src, sha);
+ ComputeShaderHash(shader_src, translator, sha);
const std::string sha_string(sha, kHashLength);
CompileStatusMap::const_iterator found = shader_status_.find(sha_string);
@@ -35,9 +37,10 @@
}
void ProgramCache::ShaderCompilationSucceeded(
- const std::string& shader_src) {
+ const std::string& shader_src,
+ const ShaderTranslatorInterface* translator) {
char sha[kHashLength];
- ComputeShaderHash(shader_src, sha);
+ ComputeShaderHash(shader_src, translator, sha);
const std::string sha_string(sha, kHashLength);
ShaderCompilationSucceededSha(sha_string);
}
@@ -54,12 +57,14 @@
ProgramCache::LinkedProgramStatus ProgramCache::GetLinkedProgramStatus(
const std::string& untranslated_a,
+ const ShaderTranslatorInterface* translator_a,
const std::string& untranslated_b,
+ const ShaderTranslatorInterface* translator_b,
const std::map<std::string, GLint>* bind_attrib_location_map) const {
char a_sha[kHashLength];
char b_sha[kHashLength];
- ComputeShaderHash(untranslated_a, a_sha);
- ComputeShaderHash(untranslated_b, b_sha);
+ ComputeShaderHash(untranslated_a, translator_a, a_sha);
+ ComputeShaderHash(untranslated_b, translator_b, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
@@ -78,12 +83,14 @@
void ProgramCache::LinkedProgramCacheSuccess(
const std::string& shader_a,
+ const ShaderTranslatorInterface* translator_a,
const std::string& shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map) {
char a_sha[kHashLength];
char b_sha[kHashLength];
- ComputeShaderHash(shader_a, a_sha);
- ComputeShaderHash(shader_b, b_sha);
+ ComputeShaderHash(shader_a, translator_a, a_sha);
+ ComputeShaderHash(shader_b, translator_b, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
b_sha,
@@ -104,10 +111,15 @@
shader_status_[shader_b_hash].ref_count++;
}
-void ProgramCache::ComputeShaderHash(const std::string& str,
- char* result) const {
- base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()),
- str.length(), reinterpret_cast<unsigned char*>(result));
+void ProgramCache::ComputeShaderHash(
+ const std::string& str,
+ const ShaderTranslatorInterface* translator,
+ char* result) const {
+ std::string s((
+ translator ? translator->GetStringForOptionsThatWouldEffectCompilation() :
+ std::string()) + str);
+ base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(s.c_str()),
+ s.length(), reinterpret_cast<unsigned char*>(result));
}
void ProgramCache::Evict(const std::string& program_hash,
diff --git a/gpu/command_buffer/service/program_cache.h b/gpu/command_buffer/service/program_cache.h
index c4b50e8..c42d359 100644
--- a/gpu/command_buffer/service/program_cache.h
+++ b/gpu/command_buffer/service/program_cache.h
@@ -18,6 +18,7 @@
namespace gles2 {
class Shader;
+class ShaderTranslator;
// Program cache base class for caching linked gpu programs
class GPU_EXPORT ProgramCache {
@@ -45,13 +46,17 @@
virtual ~ProgramCache();
CompiledShaderStatus GetShaderCompilationStatus(
- const std::string& shader_src) const;
- void ShaderCompilationSucceeded(const std::string& shader_src);
+ const std::string& shader_src,
+ const ShaderTranslatorInterface* translator) const;
+ void ShaderCompilationSucceeded(const std::string& shader_src,
+ const ShaderTranslatorInterface* translator);
void ShaderCompilationSucceededSha(const std::string& sha_string);
LinkedProgramStatus GetLinkedProgramStatus(
- const std::string& untranslated_a,
- const std::string& untranslated_b,
+ const std::string& untranslated_shader_a,
+ const ShaderTranslatorInterface* translator_a,
+ const std::string& untranslated_shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map) const;
// Loads the linked program from the cache. If the program is not found or
@@ -59,7 +64,9 @@
virtual ProgramLoadResult LoadLinkedProgram(
GLuint program,
Shader* shader_a,
+ const ShaderTranslatorInterface* translator_a,
Shader* shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) const = 0;
@@ -68,7 +75,9 @@
virtual void SaveLinkedProgram(
GLuint program,
const Shader* shader_a,
+ const ShaderTranslatorInterface* translator_a,
const Shader* shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) = 0;
@@ -79,7 +88,9 @@
// Only for testing
void LinkedProgramCacheSuccess(const std::string& shader_a,
+ const ShaderTranslatorInterface* translator_a,
const std::string& shader_b,
+ const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map);
protected:
@@ -90,6 +101,7 @@
// result is not null terminated
void ComputeShaderHash(const std::string& shader,
+ const ShaderTranslatorInterface* translator,
char* result) const;
// result is not null terminated. hashed shaders are expected to be
diff --git a/gpu/command_buffer/service/program_cache_unittest.cc b/gpu/command_buffer/service/program_cache_unittest.cc
index 46a2fe1..63c032d 100644
--- a/gpu/command_buffer/service/program_cache_unittest.cc
+++ b/gpu/command_buffer/service/program_cache_unittest.cc
@@ -5,8 +5,11 @@
#include "gpu/command_buffer/service/program_cache.h"
#include "base/memory/scoped_ptr.h"
+#include "gpu/command_buffer/service/mocks.h"
#include "testing/gtest/include/gtest/gtest.h"
+using ::testing::Return;
+
namespace gpu {
namespace gles2 {
@@ -15,7 +18,9 @@
virtual ProgramLoadResult LoadLinkedProgram(
GLuint /* program */,
Shader* /* shader_a */,
+ const ShaderTranslatorInterface* /* translator_a */,
Shader* /* shader_b */,
+ const ShaderTranslatorInterface* /* translator_b */,
const LocationMap* /* bind_attrib_location_map */,
const ShaderCacheCallback& /* callback */) const OVERRIDE {
return PROGRAM_LOAD_SUCCESS;
@@ -23,7 +28,9 @@
virtual void SaveLinkedProgram(
GLuint /* program */,
const Shader* /* shader_a */,
+ const ShaderTranslatorInterface* /* translator_b */,
const Shader* /* shader_b */,
+ const ShaderTranslatorInterface* /* translator_b */,
const LocationMap* /* bind_attrib_location_map */,
const ShaderCacheCallback& /* callback */) OVERRIDE { }
@@ -32,12 +39,14 @@
virtual void ClearBackend() OVERRIDE {}
void SaySuccessfullyCached(const std::string& shader1,
+ const ShaderTranslatorInterface* translator_1,
const std::string& shader2,
+ const ShaderTranslatorInterface* translator_2,
std::map<std::string, GLint>* attrib_map) {
char a_sha[kHashLength];
char b_sha[kHashLength];
- ComputeShaderHash(shader1, a_sha);
- ComputeShaderHash(shader2, b_sha);
+ ComputeShaderHash(shader1, translator_1, a_sha);
+ ComputeShaderHash(shader2, translator_2, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
@@ -52,8 +61,9 @@
}
void ComputeShaderHash(const std::string& shader,
+ const ShaderTranslatorInterface* translator,
char* result) const {
- ProgramCache::ComputeShaderHash(shader, result);
+ ProgramCache::ComputeShaderHash(shader, translator, result);
}
void ComputeProgramHash(const char* hashed_shader_0,
@@ -87,22 +97,47 @@
{
std::string shader = shader1;
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader));
- cache_->ShaderCompilationSucceeded(shader);
+ cache_->GetShaderCompilationStatus(shader, NULL));
+ cache_->ShaderCompilationSucceeded(shader, NULL);
shader.clear();
}
// make sure it was copied
EXPECT_EQ(ProgramCache::COMPILATION_SUCCEEDED,
- cache_->GetShaderCompilationStatus(shader1));
+ cache_->GetShaderCompilationStatus(shader1, NULL));
+}
+
+TEST_F(ProgramCacheTest, CompilationStatusTranslatorOptionDependent) {
+ MockShaderTranslator translator;
+
+ EXPECT_CALL(translator, GetStringForOptionsThatWouldEffectCompilation())
+ .WillOnce(Return("foo")) // GetShaderCompilationStatus
+ .WillOnce(Return("foo")) // ShaderCompilationSucceeded
+ .WillOnce(Return("foo")) // GetShaderCompilationStatus
+ .WillOnce(Return("bar")); // GetShaderCompilationStatus
+
+ const std::string shader1 = "abcd1234";
+ {
+ std::string shader = shader1;
+ EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
+ cache_->GetShaderCompilationStatus(shader, &translator));
+ cache_->ShaderCompilationSucceeded(shader, &translator);
+ shader.clear();
+ }
+ // make sure it was copied
+ EXPECT_EQ(ProgramCache::COMPILATION_SUCCEEDED,
+ cache_->GetShaderCompilationStatus(shader1, &translator));
+ // make sure if the options change it's not copied.
+ EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
+ cache_->GetShaderCompilationStatus(shader1, &translator));
}
TEST_F(ProgramCacheTest, CompilationUnknownOnSourceChange) {
std::string shader1 = "abcd1234";
- cache_->ShaderCompilationSucceeded(shader1);
+ cache_->ShaderCompilationSucceeded(shader1, NULL);
shader1 = "different!";
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader1));
+ cache_->GetShaderCompilationStatus(shader1, NULL));
}
TEST_F(ProgramCacheTest, LinkStatusSave) {
@@ -112,47 +147,49 @@
std::string shader_a = shader1;
std::string shader_b = shader2;
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader_a, shader_b, NULL));
- cache_->SaySuccessfullyCached(shader_a, shader_b, NULL);
+ cache_->GetLinkedProgramStatus(
+ shader_a, NULL, shader_b, NULL, NULL));
+ cache_->SaySuccessfullyCached(shader_a, NULL, shader_b, NULL, NULL);
shader_a.clear();
shader_b.clear();
}
// make sure it was copied
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED,
- cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
+ cache_->GetLinkedProgramStatus(
+ shader1, NULL, shader2, NULL, NULL));
}
TEST_F(ProgramCacheTest, LinkUnknownOnFragmentSourceChange) {
const std::string shader1 = "abcd1234";
std::string shader2 = "abcda sda b1~#4 bbbbb1234";
- cache_->SaySuccessfullyCached(shader1, shader2, NULL);
+ cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL);
shader2 = "different!";
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
+ cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
}
TEST_F(ProgramCacheTest, LinkUnknownOnVertexSourceChange) {
std::string shader1 = "abcd1234";
const std::string shader2 = "abcda sda b1~#4 bbbbb1234";
- cache_->SaySuccessfullyCached(shader1, shader2, NULL);
+ cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL);
shader1 = "different!";
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
+ cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
}
TEST_F(ProgramCacheTest, StatusEviction) {
const std::string shader1 = "abcd1234";
const std::string shader2 = "abcda sda b1~#4 bbbbb1234";
- cache_->ShaderCompilationSucceeded(shader1);
- cache_->ShaderCompilationSucceeded(shader2);
- cache_->SaySuccessfullyCached(shader1, shader2, NULL);
+ cache_->ShaderCompilationSucceeded(shader1, NULL);
+ cache_->ShaderCompilationSucceeded(shader2, NULL);
+ cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL);
char a_sha[ProgramCache::kHashLength];
char b_sha[ProgramCache::kHashLength];
- cache_->ComputeShaderHash(shader1, a_sha);
- cache_->ComputeShaderHash(shader2, b_sha);
+ cache_->ComputeShaderHash(shader1, NULL, a_sha);
+ cache_->ComputeShaderHash(shader2, NULL, b_sha);
char sha[ProgramCache::kHashLength];
cache_->ComputeProgramHash(a_sha,
@@ -163,30 +200,30 @@
std::string(a_sha, ProgramCache::kHashLength),
std::string(b_sha, ProgramCache::kHashLength));
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader1));
+ cache_->GetShaderCompilationStatus(shader1, NULL));
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader2));
+ cache_->GetShaderCompilationStatus(shader2, NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
+ cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
}
TEST_F(ProgramCacheTest, EvictionWithReusedShader) {
const std::string shader1 = "abcd1234";
const std::string shader2 = "abcda sda b1~#4 bbbbb1234";
const std::string shader3 = "asbjbbjj239a";
- cache_->ShaderCompilationSucceeded(shader1);
- cache_->ShaderCompilationSucceeded(shader2);
- cache_->SaySuccessfullyCached(shader1, shader2, NULL);
- cache_->ShaderCompilationSucceeded(shader1);
- cache_->ShaderCompilationSucceeded(shader3);
- cache_->SaySuccessfullyCached(shader1, shader3, NULL);
+ cache_->ShaderCompilationSucceeded(shader1, NULL);
+ cache_->ShaderCompilationSucceeded(shader2, NULL);
+ cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL);
+ cache_->ShaderCompilationSucceeded(shader1, NULL);
+ cache_->ShaderCompilationSucceeded(shader3, NULL);
+ cache_->SaySuccessfullyCached(shader1, NULL, shader3, NULL, NULL);
char a_sha[ProgramCache::kHashLength];
char b_sha[ProgramCache::kHashLength];
char c_sha[ProgramCache::kHashLength];
- cache_->ComputeShaderHash(shader1, a_sha);
- cache_->ComputeShaderHash(shader2, b_sha);
- cache_->ComputeShaderHash(shader3, c_sha);
+ cache_->ComputeShaderHash(shader1, NULL, a_sha);
+ cache_->ComputeShaderHash(shader2, NULL, b_sha);
+ cache_->ComputeShaderHash(shader3, NULL, c_sha);
char sha[ProgramCache::kHashLength];
cache_->ComputeProgramHash(a_sha,
@@ -197,15 +234,15 @@
std::string(a_sha, ProgramCache::kHashLength),
std::string(b_sha, ProgramCache::kHashLength));
EXPECT_EQ(ProgramCache::COMPILATION_SUCCEEDED,
- cache_->GetShaderCompilationStatus(shader1));
+ cache_->GetShaderCompilationStatus(shader1, NULL));
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader2));
+ cache_->GetShaderCompilationStatus(shader2, NULL));
EXPECT_EQ(ProgramCache::COMPILATION_SUCCEEDED,
- cache_->GetShaderCompilationStatus(shader3));
+ cache_->GetShaderCompilationStatus(shader3, NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
+ cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED,
- cache_->GetLinkedProgramStatus(shader1, shader3, NULL));
+ cache_->GetLinkedProgramStatus(shader1, NULL, shader3, NULL, NULL));
cache_->ComputeProgramHash(a_sha,
@@ -216,37 +253,37 @@
std::string(a_sha, ProgramCache::kHashLength),
std::string(c_sha, ProgramCache::kHashLength));
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader1));
+ cache_->GetShaderCompilationStatus(shader1, NULL));
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader2));
+ cache_->GetShaderCompilationStatus(shader2, NULL));
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader3));
+ cache_->GetShaderCompilationStatus(shader3, NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
+ cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, shader3, NULL));
+ cache_->GetLinkedProgramStatus(shader1, NULL, shader3, NULL, NULL));
}
TEST_F(ProgramCacheTest, StatusClear) {
const std::string shader1 = "abcd1234";
const std::string shader2 = "abcda sda b1~#4 bbbbb1234";
const std::string shader3 = "asbjbbjj239a";
- cache_->ShaderCompilationSucceeded(shader1);
- cache_->ShaderCompilationSucceeded(shader2);
- cache_->SaySuccessfullyCached(shader1, shader2, NULL);
- cache_->ShaderCompilationSucceeded(shader3);
- cache_->SaySuccessfullyCached(shader1, shader3, NULL);
+ cache_->ShaderCompilationSucceeded(shader1, NULL);
+ cache_->ShaderCompilationSucceeded(shader2, NULL);
+ cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL);
+ cache_->ShaderCompilationSucceeded(shader3, NULL);
+ cache_->SaySuccessfullyCached(shader1, NULL, shader3, NULL, NULL);
cache_->Clear();
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader1));
+ cache_->GetShaderCompilationStatus(shader1, NULL));
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader2));
+ cache_->GetShaderCompilationStatus(shader2, NULL));
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(shader3));
+ cache_->GetShaderCompilationStatus(shader3, NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
+ cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, shader3, NULL));
+ cache_->GetLinkedProgramStatus(shader1, NULL, shader3, NULL, NULL));
}
} // namespace gles2
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index 0fecd0a..d362cde 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -446,8 +446,8 @@
TimeTicks before = TimeTicks::HighResNow();
if (program_cache_ &&
program_cache_->GetShaderCompilationStatus(
- shader->source() ? *shader->source() : std::string()) ==
- ProgramCache::COMPILATION_SUCCEEDED) {
+ shader->source() ? *shader->source() : std::string(),
+ translator) == ProgramCache::COMPILATION_SUCCEEDED) {
shader->SetStatus(true, "", translator);
shader->FlagSourceAsCompiled(false);
UMA_HISTOGRAM_CUSTOM_COUNTS(
@@ -508,7 +508,8 @@
shader->SetStatus(true, "", translator);
if (program_cache_) {
const char* untranslated_source = source ? source->c_str() : "";
- program_cache_->ShaderCompilationSucceeded(untranslated_source);
+ program_cache_->ShaderCompilationSucceeded(
+ untranslated_source, translator);
}
} else {
// We cannot reach here if we are using the shader translator.
@@ -552,14 +553,18 @@
if (cache) {
ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus(
*attached_shaders_[0]->deferred_compilation_source(),
+ vertex_translator,
*attached_shaders_[1]->deferred_compilation_source(),
+ fragment_translator,
&bind_attrib_location_map_);
if (status == ProgramCache::LINK_SUCCEEDED) {
ProgramCache::ProgramLoadResult success = cache->LoadLinkedProgram(
service_id(),
attached_shaders_[0],
+ vertex_translator,
attached_shaders_[1],
+ fragment_translator,
&bind_attrib_location_map_,
shader_callback);
link = success != ProgramCache::PROGRAM_LOAD_SUCCESS;
@@ -581,7 +586,7 @@
attached_shaders_[i],
translator,
feature_info);
- CHECK(shader->IsValid());
+ DCHECK(shader->IsValid());
}
}
}
@@ -606,7 +611,9 @@
if (cache) {
cache->SaveLinkedProgram(service_id(),
attached_shaders_[0],
+ vertex_translator,
attached_shaders_[1],
+ fragment_translator,
&bind_attrib_location_map_,
shader_callback);
}
diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc
index 8770e93..fce5ac3 100644
--- a/gpu/command_buffer/service/program_manager_unittest.cc
+++ b/gpu/command_buffer/service/program_manager_unittest.cc
@@ -1192,8 +1192,8 @@
}
void SetShadersCompiled() {
- cache_->ShaderCompilationSucceeded(*vertex_shader_->source());
- cache_->ShaderCompilationSucceeded(*fragment_shader_->source());
+ cache_->ShaderCompilationSucceeded(*vertex_shader_->source(), NULL);
+ cache_->ShaderCompilationSucceeded(*fragment_shader_->source(), NULL);
vertex_shader_->SetStatus(true, NULL, NULL);
fragment_shader_->SetStatus(true, NULL, NULL);
vertex_shader_->FlagSourceAsCompiled(true);
@@ -1209,7 +1209,9 @@
void SetProgramCached() {
cache_->LinkedProgramCacheSuccess(
vertex_shader_->source()->c_str(),
+ NULL,
fragment_shader_->source()->c_str(),
+ NULL,
&program_->bind_attrib_location_map());
}
@@ -1226,7 +1228,9 @@
EXPECT_CALL(*cache_.get(), SaveLinkedProgram(
program->service_id(),
vertex_shader,
+ NULL,
fragment_shader,
+ NULL,
&program->bind_attrib_location_map(),
_)).Times(1);
}
@@ -1244,7 +1248,9 @@
EXPECT_CALL(*cache_.get(), SaveLinkedProgram(
program->service_id(),
vertex_shader,
+ NULL,
fragment_shader,
+ NULL,
&program->bind_attrib_location_map(),
_)).Times(0);
}
@@ -1266,7 +1272,9 @@
EXPECT_CALL(*cache_.get(),
LoadLinkedProgram(service_program_id,
vertex_shader,
+ NULL,
fragment_shader,
+ NULL,
&program->bind_attrib_location_map(),
_))
.WillOnce(Return(result));
@@ -1360,7 +1368,8 @@
scoped_refptr<FeatureInfo> info(new FeatureInfo());
manager_.DoCompileShader(vertex_shader_, NULL, info.get());
EXPECT_EQ(ProgramCache::COMPILATION_SUCCEEDED,
- cache_->GetShaderCompilationStatus(*vertex_shader_->source()));
+ cache_->GetShaderCompilationStatus(
+ *vertex_shader_->source(), NULL));
}
TEST_F(ProgramManagerWithCacheTest, CacheUnknownAfterShaderError) {
@@ -1368,11 +1377,12 @@
scoped_refptr<FeatureInfo> info(new FeatureInfo());
manager_.DoCompileShader(vertex_shader_, NULL, info.get());
EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN,
- cache_->GetShaderCompilationStatus(*vertex_shader_->source()));
+ cache_->GetShaderCompilationStatus(
+ *vertex_shader_->source(), NULL));
}
TEST_F(ProgramManagerWithCacheTest, NoCompileWhenShaderCached) {
- cache_->ShaderCompilationSucceeded(vertex_shader_->source()->c_str());
+ cache_->ShaderCompilationSucceeded(vertex_shader_->source()->c_str(), NULL);
SetExpectationsForNoCompile(vertex_shader_);
scoped_refptr<FeatureInfo> info(new FeatureInfo());
manager_.DoCompileShader(vertex_shader_, NULL, info.get());
diff --git a/gpu/command_buffer/service/safe_shared_memory_pool.cc b/gpu/command_buffer/service/safe_shared_memory_pool.cc
index 05fce77..9496967 100644
--- a/gpu/command_buffer/service/safe_shared_memory_pool.cc
+++ b/gpu/command_buffer/service/safe_shared_memory_pool.cc
@@ -120,7 +120,7 @@
if (!shared_memory->ShareToProcess(
base::GetCurrentProcessHandle(),
&duped_shared_memory_handle)) {
- LOG(ERROR) << "Failed SharedMemory::ShareToProcess";
+ PLOG(ERROR) << "Failed SharedMemory::ShareToProcess";
LOG(ERROR) << "Total handles acquired " << handles_acquired_;
LOG(ERROR) << "Total handles open " << handles_consumed_;
LOG(ERROR) << "Total address space " << address_space_consumed_;
@@ -134,7 +134,7 @@
new SharedMemory(duped_shared_memory_handle, false));
// Map the shared memory into this process. This validates the size.
if (!duped_shared_memory->Map(size)) {
- LOG(ERROR) << "Failed SharedMemory::Map";
+ PLOG(ERROR) << "Failed SharedMemory::Map(" << size << ")";
LOG(ERROR) << "Total handles acquired " << handles_acquired_;
LOG(ERROR) << "Total handles open " << handles_consumed_;
LOG(ERROR) << "Total address space " << address_space_consumed_;
diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc
index 2e5541d..3bd2a97 100644
--- a/gpu/command_buffer/service/shader_translator.cc
+++ b/gpu/command_buffer/service/shader_translator.cc
@@ -8,19 +8,24 @@
#include <algorithm>
#include "base/at_exit.h"
+#include "base/debug/trace_event.h"
#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
namespace {
using gpu::gles2::ShaderTranslator;
void FinalizeShaderTranslator(void* /* dummy */) {
+ TRACE_EVENT0("gpu", "ShFinalize");
ShFinalize();
}
bool InitializeShaderTranslator() {
static bool initialized = false;
- if (!initialized && ShInitialize()) {
+ if (!initialized) {
+ TRACE_EVENT0("gpu", "ShInitialize");
+ CHECK(ShInitialize());
base::AtExitManager::RegisterCallback(&FinalizeShaderTranslator, NULL);
initialized = true;
}
@@ -137,14 +142,32 @@
ShShaderOutput shader_output =
(glsl_implementation_type == kGlslES ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT);
- compiler_ = ShConstructCompiler(
- shader_type, shader_spec, shader_output, resources);
+ {
+ TRACE_EVENT0("gpu", "ShConstructCompiler");
+ compiler_ = ShConstructCompiler(
+ shader_type, shader_spec, shader_output, resources);
+ }
+ compiler_options_ = *resources;
implementation_is_glsl_es_ = (glsl_implementation_type == kGlslES);
needs_built_in_function_emulation_ =
(glsl_built_in_function_behavior == kGlslBuiltInFunctionEmulated);
return compiler_ != NULL;
}
+int ShaderTranslator::GetCompileOptions() const {
+ int compile_options =
+ SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS |
+ SH_MAP_LONG_VARIABLE_NAMES | SH_ENFORCE_PACKING_RESTRICTIONS |
+ SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH;
+
+ compile_options |= SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
+
+ if (needs_built_in_function_emulation_)
+ compile_options |= SH_EMULATE_BUILT_IN_FUNCTIONS;
+
+ return compile_options;
+}
+
bool ShaderTranslator::Translate(const char* shader) {
// Make sure this instance is initialized.
DCHECK(compiler_ != NULL);
@@ -152,16 +175,11 @@
ClearResults();
bool success = false;
- int compile_options =
- SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS |
- SH_MAP_LONG_VARIABLE_NAMES | SH_ENFORCE_PACKING_RESTRICTIONS;
-
- compile_options |= SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
-
- if (needs_built_in_function_emulation_)
- compile_options |= SH_EMULATE_BUILT_IN_FUNCTIONS;
- if (ShCompile(compiler_, &shader, 1, compile_options)) {
- success = true;
+ {
+ TRACE_EVENT0("gpu", "ShCompile");
+ success = !!ShCompile(compiler_, &shader, 1, GetCompileOptions());
+ }
+ if (success) {
// Get translated shader.
ANGLEGetInfoType obj_code_len = 0;
ShGetInfo(compiler_, SH_OBJECT_CODE_LENGTH, &obj_code_len);
@@ -189,6 +207,60 @@
return success;
}
+std::string ShaderTranslator::GetStringForOptionsThatWouldEffectCompilation()
+ const {
+ const size_t kNumIntFields = 15;
+ const size_t kNumEnumFields = 1;
+ const size_t kNumFunctionPointerFields = 1;
+ struct MustMatchShBuiltInResource {
+ typedef khronos_uint64_t (*FunctionPointer)(const char*, size_t);
+ enum Enum {
+ kFirst,
+ };
+ int int_fields[kNumIntFields];
+ FunctionPointer pointer_fields[kNumFunctionPointerFields];
+ Enum enum_fields[kNumEnumFields];
+ };
+ // If this assert fails most likely that means something below needs updating.
+ COMPILE_ASSERT(
+ sizeof(ShBuiltInResources) == sizeof(MustMatchShBuiltInResource),
+ Fields_Have_Changed_In_ShBuiltInResource_So_Update_Below);
+
+ return std::string(
+ ":CompileOptions:" +
+ base::IntToString(GetCompileOptions()) +
+ ":MaxVertexAttribs:" +
+ base::IntToString(compiler_options_.MaxVertexAttribs) +
+ ":MaxVertexUniformVectors:" +
+ base::IntToString(compiler_options_.MaxVertexUniformVectors) +
+ ":MaxVaryingVectors:" +
+ base::IntToString(compiler_options_.MaxVaryingVectors) +
+ ":MaxVertexTextureImageUnits:" +
+ base::IntToString(compiler_options_.MaxVertexTextureImageUnits) +
+ ":MaxCombinedTextureImageUnits:" +
+ base::IntToString(compiler_options_.MaxCombinedTextureImageUnits) +
+ ":MaxTextureImageUnits:" +
+ base::IntToString(compiler_options_.MaxTextureImageUnits) +
+ ":MaxFragmentUniformVectors:" +
+ base::IntToString(compiler_options_.MaxFragmentUniformVectors) +
+ ":MaxDrawBuffers:" +
+ base::IntToString(compiler_options_.MaxDrawBuffers) +
+ ":OES_standard_derivatives:" +
+ base::IntToString(compiler_options_.OES_standard_derivatives) +
+ ":OES_EGL_image_external:" +
+ base::IntToString(compiler_options_.OES_EGL_image_external) +
+ ":ARB_texture_rectangle:" +
+ base::IntToString(compiler_options_.ARB_texture_rectangle) +
+ ":EXT_draw_buffers:" +
+ base::IntToString(compiler_options_.EXT_draw_buffers) +
+ ":FragmentPrecisionHigh:" +
+ base::IntToString(compiler_options_.FragmentPrecisionHigh) +
+ ":MaxExpressionComplexity:" +
+ base::IntToString(compiler_options_.MaxExpressionComplexity) +
+ ":MaxCallStackDepth:" +
+ base::IntToString(compiler_options_.MaxCallStackDepth));
+}
+
const char* ShaderTranslator::translated_shader() const {
return translated_shader_.get();
}
diff --git a/gpu/command_buffer/service/shader_translator.h b/gpu/command_buffer/service/shader_translator.h
index 9260171..5904f73 100644
--- a/gpu/command_buffer/service/shader_translator.h
+++ b/gpu/command_buffer/service/shader_translator.h
@@ -84,6 +84,10 @@
virtual const VariableMap& uniform_map() const = 0;
virtual const NameMap& name_map() const = 0;
+ // Return a string that is unique for a specfic set of options that would
+ // possibly effect compilation.
+ virtual std::string GetStringForOptionsThatWouldEffectCompilation() const = 0;
+
protected:
virtual ~ShaderTranslatorInterface() {}
};
@@ -126,6 +130,9 @@
virtual const VariableMap& uniform_map() const OVERRIDE;
virtual const NameMap& name_map() const OVERRIDE;
+ virtual std::string GetStringForOptionsThatWouldEffectCompilation() const
+ OVERRIDE;
+
void AddDestructionObserver(DestructionObserver* observer);
void RemoveDestructionObserver(DestructionObserver* observer);
@@ -134,8 +141,10 @@
virtual ~ShaderTranslator();
void ClearResults();
+ int GetCompileOptions() const;
ShHandle compiler_;
+ ShBuiltInResources compiler_options_;
scoped_ptr<char[]> translated_shader_;
scoped_ptr<char[]> info_log_;
VariableMap attrib_map_;
diff --git a/gpu/command_buffer/service/shader_translator_unittest.cc b/gpu/command_buffer/service/shader_translator_unittest.cc
index 469028d..a08851a 100644
--- a/gpu/command_buffer/service/shader_translator_unittest.cc
+++ b/gpu/command_buffer/service/shader_translator_unittest.cc
@@ -19,6 +19,8 @@
protected:
virtual void SetUp() {
ShBuiltInResources resources;
+ resources.MaxExpressionComplexity = 32;
+ resources.MaxCallStackDepth = 32;
ShInitBuiltInResources(&resources);
vertex_translator_ = new ShaderTranslator();
fragment_translator_ = new ShaderTranslator();
@@ -63,7 +65,7 @@
// Info log must be NULL.
EXPECT_TRUE(vertex_translator_->info_log() == NULL);
// Translated shader must be valid and non-empty.
- EXPECT_TRUE(vertex_translator_->translated_shader() != NULL);
+ ASSERT_TRUE(vertex_translator_->translated_shader() != NULL);
EXPECT_GT(strlen(vertex_translator_->translated_shader()), 0u);
// There should be no attributes or uniforms.
EXPECT_TRUE(vertex_translator_->attrib_map().empty());
@@ -80,7 +82,7 @@
// An invalid shader should fail.
EXPECT_FALSE(vertex_translator_->Translate(bad_shader));
// Info log must be valid and non-empty.
- EXPECT_TRUE(vertex_translator_->info_log() != NULL);
+ ASSERT_TRUE(vertex_translator_->info_log() != NULL);
EXPECT_GT(strlen(vertex_translator_->info_log()), 0u);
// Translated shader must be NULL.
EXPECT_TRUE(vertex_translator_->translated_shader() == NULL);
@@ -91,7 +93,7 @@
// Try a good shader after bad.
EXPECT_TRUE(vertex_translator_->Translate(good_shader));
EXPECT_TRUE(vertex_translator_->info_log() == NULL);
- EXPECT_TRUE(vertex_translator_->translated_shader() != NULL);
+ ASSERT_TRUE(vertex_translator_->translated_shader() != NULL);
EXPECT_GT(strlen(vertex_translator_->translated_shader()), 0u);
}
@@ -106,7 +108,7 @@
// Info log must be NULL.
EXPECT_TRUE(fragment_translator_->info_log() == NULL);
// Translated shader must be valid and non-empty.
- EXPECT_TRUE(fragment_translator_->translated_shader() != NULL);
+ ASSERT_TRUE(fragment_translator_->translated_shader() != NULL);
EXPECT_GT(strlen(fragment_translator_->translated_shader()), 0u);
// There should be no attributes or uniforms.
EXPECT_TRUE(fragment_translator_->attrib_map().empty());
@@ -119,7 +121,7 @@
// An invalid shader should fail.
EXPECT_FALSE(fragment_translator_->Translate(shader));
// Info log must be valid and non-empty.
- EXPECT_TRUE(fragment_translator_->info_log() != NULL);
+ ASSERT_TRUE(fragment_translator_->info_log() != NULL);
EXPECT_GT(strlen(fragment_translator_->info_log()), 0u);
// Translated shader must be NULL.
EXPECT_TRUE(fragment_translator_->translated_shader() == NULL);
@@ -139,7 +141,7 @@
// Info log must be NULL.
EXPECT_TRUE(vertex_translator_->info_log() == NULL);
// Translated shader must be valid and non-empty.
- EXPECT_TRUE(vertex_translator_->translated_shader() != NULL);
+ ASSERT_TRUE(vertex_translator_->translated_shader() != NULL);
EXPECT_GT(strlen(vertex_translator_->translated_shader()), 0u);
// There should be no uniforms.
EXPECT_TRUE(vertex_translator_->uniform_map().empty());
@@ -174,7 +176,7 @@
// Info log must be NULL.
EXPECT_TRUE(fragment_translator_->info_log() == NULL);
// Translated shader must be valid and non-empty.
- EXPECT_TRUE(fragment_translator_->translated_shader() != NULL);
+ ASSERT_TRUE(fragment_translator_->translated_shader() != NULL);
EXPECT_GT(strlen(fragment_translator_->translated_shader()), 0u);
// There should be no attributes.
EXPECT_TRUE(fragment_translator_->attrib_map().empty());
@@ -213,12 +215,49 @@
// Info log must be NULL.
EXPECT_TRUE(vertex_translator_->info_log() == NULL);
// Translated shader must be valid and non-empty.
- EXPECT_TRUE(vertex_translator_->translated_shader() != NULL);
+ ASSERT_TRUE(vertex_translator_->translated_shader() != NULL);
EXPECT_TRUE(strstr(vertex_translator_->translated_shader(),
"webgl_dot_emu") != NULL);
}
#endif
+TEST_F(ShaderTranslatorTest, OptionsString) {
+ scoped_refptr<ShaderTranslator> translator_1 = new ShaderTranslator();
+ scoped_refptr<ShaderTranslator> translator_2 = new ShaderTranslator();
+ scoped_refptr<ShaderTranslator> translator_3 = new ShaderTranslator();
+
+ ShBuiltInResources resources;
+ ShInitBuiltInResources(&resources);
+
+ ASSERT_TRUE(translator_1->Init(
+ SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources,
+ ShaderTranslatorInterface::kGlsl,
+ ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated));
+ ASSERT_TRUE(translator_2->Init(
+ SH_FRAGMENT_SHADER, SH_GLES2_SPEC, &resources,
+ ShaderTranslatorInterface::kGlsl,
+ ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal));
+ resources.EXT_draw_buffers = 1;
+ ASSERT_TRUE(translator_3->Init(
+ SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources,
+ ShaderTranslatorInterface::kGlsl,
+ ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated));
+
+ std::string options_1(
+ translator_1->GetStringForOptionsThatWouldEffectCompilation());
+ std::string options_2(
+ translator_1->GetStringForOptionsThatWouldEffectCompilation());
+ std::string options_3(
+ translator_2->GetStringForOptionsThatWouldEffectCompilation());
+ std::string options_4(
+ translator_3->GetStringForOptionsThatWouldEffectCompilation());
+
+ EXPECT_EQ(options_1, options_2);
+ EXPECT_NE(options_1, options_3);
+ EXPECT_NE(options_1, options_4);
+ EXPECT_NE(options_3, options_4);
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/test_helper.cc b/gpu/command_buffer/service/test_helper.cc
index 5b3f57c..074e301 100644
--- a/gpu/command_buffer/service/test_helper.cc
+++ b/gpu/command_buffer/service/test_helper.cc
@@ -285,12 +285,6 @@
EXPECT_CALL(*gl, GetString(GL_EXTENSIONS))
.WillOnce(Return(reinterpret_cast<const uint8*>(extensions)))
.RetiresOnSaturation();
- EXPECT_CALL(*gl, GetString(GL_VENDOR))
- .WillOnce(Return(reinterpret_cast<const uint8*>("")))
- .RetiresOnSaturation();
- EXPECT_CALL(*gl, GetString(GL_RENDERER))
- .WillOnce(Return(reinterpret_cast<const uint8*>("")))
- .RetiresOnSaturation();
EXPECT_CALL(*gl, GetString(GL_VERSION))
.WillOnce(Return(reinterpret_cast<const uint8*>(version)))
.RetiresOnSaturation();
@@ -523,11 +517,12 @@
void TestHelper::SetTexParameterWithExpectations(
::gfx::MockGLInterface* gl, MockErrorState* error_state,
- TextureManager* manager, Texture* texture,
+ TextureManager* manager, TextureRef* texture_ref,
GLenum pname, GLint value, GLenum error) {
if (error == GL_NO_ERROR) {
if (pname != GL_TEXTURE_POOL_CHROMIUM) {
- EXPECT_CALL(*gl, TexParameteri(texture->target(), pname, value))
+ EXPECT_CALL(*gl, TexParameteri(texture_ref->texture()->target(),
+ pname, value))
.Times(1)
.RetiresOnSaturation();
}
@@ -540,7 +535,7 @@
.Times(1)
.RetiresOnSaturation();
}
- manager->SetParameter("", error_state, texture, pname, value);
+ manager->SetParameter("", error_state, texture_ref, pname, value);
}
ScopedGLImplementationSetter::ScopedGLImplementationSetter(
diff --git a/gpu/command_buffer/service/test_helper.h b/gpu/command_buffer/service/test_helper.h
index 41cb3aa..11f7004 100644
--- a/gpu/command_buffer/service/test_helper.h
+++ b/gpu/command_buffer/service/test_helper.h
@@ -15,7 +15,7 @@
class Buffer;
class BufferManager;
class MockErrorState;
-class Texture;
+class TextureRef;
class TextureManager;
class TestHelper {
@@ -98,7 +98,7 @@
static void SetTexParameterWithExpectations(
::gfx::MockGLInterface* gl, MockErrorState* error_state,
- TextureManager* manager, Texture* texture,
+ TextureManager* manager, TextureRef* texture_ref,
GLenum pname, GLint value, GLenum error);
private:
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index d64ac25..e2fac59 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -8,6 +8,7 @@
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/error_state.h"
#include "gpu/command_buffer/service/feature_info.h"
+#include "gpu/command_buffer/service/framebuffer_manager.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/memory_tracking.h"
@@ -87,10 +88,9 @@
DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented());
}
-Texture::Texture(TextureManager* manager, GLuint service_id)
- : manager_(manager),
+Texture::Texture(GLuint service_id)
+ : memory_tracking_ref_(NULL),
service_id_(service_id),
- deleted_(false),
cleared_(true),
num_uncleared_mips_(0),
target_(0),
@@ -109,24 +109,48 @@
owned_(true),
stream_texture_(false),
immutable_(false),
- estimated_size_(0) {
- if (manager_) {
- manager_->StartTracking(this);
- }
+ estimated_size_(0),
+ can_render_condition_(CAN_RENDER_ALWAYS) {
}
Texture::~Texture() {
- if (manager_) {
- if (owned_ && manager_->have_context_) {
+}
+
+void Texture::AddTextureRef(TextureRef* ref) {
+ DCHECK(refs_.find(ref) == refs_.end());
+ refs_.insert(ref);
+ if (!memory_tracking_ref_) {
+ memory_tracking_ref_ = ref;
+ GetMemTracker()->TrackMemAlloc(estimated_size());
+ }
+}
+
+void Texture::RemoveTextureRef(TextureRef* ref, bool have_context) {
+ if (memory_tracking_ref_ == ref) {
+ GetMemTracker()->TrackMemFree(estimated_size());
+ memory_tracking_ref_ = NULL;
+ }
+ size_t result = refs_.erase(ref);
+ DCHECK_EQ(result, 1u);
+ if (refs_.empty()) {
+ if (owned_ && have_context) {
GLuint id = service_id();
glDeleteTextures(1, &id);
}
- MarkAsDeleted();
- manager_->StopTracking(this);
- manager_ = NULL;
+ delete this;
+ } else if (memory_tracking_ref_ == NULL) {
+ // TODO(piman): tune ownership semantics for cross-context group shared
+ // textures.
+ memory_tracking_ref_ = *refs_.begin();
+ GetMemTracker()->TrackMemAlloc(estimated_size());
}
}
+MemoryTypeTracker* Texture::GetMemTracker() {
+ DCHECK(memory_tracking_ref_);
+ return memory_tracking_ref_->manager()->GetMemTracker(pool_);
+}
+
Texture::LevelInfo::LevelInfo()
: cleared(true),
target(0),
@@ -159,26 +183,59 @@
Texture::LevelInfo::~LevelInfo() {
}
-bool Texture::CanRender(const FeatureInfo* feature_info) const {
- if (target_ == 0) {
- return false;
- }
- bool needs_mips = NeedsMips();
- if ((npot() && !feature_info->feature_flags().npot_ok) ||
- (target_ == GL_TEXTURE_RECTANGLE_ARB)) {
- return !needs_mips &&
- wrap_s_ == GL_CLAMP_TO_EDGE &&
- wrap_t_ == GL_CLAMP_TO_EDGE;
- }
- if (needs_mips) {
- if (target_ == GL_TEXTURE_2D) {
- return texture_complete();
- } else {
- return texture_complete() && cube_complete();
+Texture::CanRenderCondition Texture::GetCanRenderCondition() const {
+ if (target_ == 0)
+ return CAN_RENDER_ALWAYS;
+
+ if (target_ == GL_TEXTURE_EXTERNAL_OES) {
+ if (!IsStreamTexture()) {
+ return CAN_RENDER_NEVER;
}
} else {
- return true;
+ if (level_infos_.empty()) {
+ return CAN_RENDER_NEVER;
+ }
+
+ const Texture::LevelInfo& first_face = level_infos_[0][0];
+ if (first_face.width == 0 ||
+ first_face.height == 0 ||
+ first_face.depth == 0) {
+ return CAN_RENDER_NEVER;
+ }
}
+
+ bool needs_mips = NeedsMips();
+ if (needs_mips) {
+ if (!texture_complete())
+ return CAN_RENDER_NEVER;
+ if (target_ == GL_TEXTURE_CUBE_MAP && !cube_complete())
+ return CAN_RENDER_NEVER;
+ }
+
+ bool is_npot_compatible = !needs_mips &&
+ wrap_s_ == GL_CLAMP_TO_EDGE &&
+ wrap_t_ == GL_CLAMP_TO_EDGE;
+
+ if (!is_npot_compatible) {
+ if (target_ == GL_TEXTURE_RECTANGLE_ARB)
+ return CAN_RENDER_NEVER;
+ else if (npot())
+ return CAN_RENDER_ONLY_IF_NPOT;
+ }
+
+ return CAN_RENDER_ALWAYS;
+}
+
+bool Texture::CanRender(const FeatureInfo* feature_info) const {
+ switch (can_render_condition_) {
+ case CAN_RENDER_ALWAYS:
+ return true;
+ case CAN_RENDER_NEVER:
+ return false;
+ case CAN_RENDER_ONLY_IF_NPOT:
+ break;
+ }
+ return feature_info->feature_flags().npot_ok;
}
void Texture::AddToSignature(
@@ -243,7 +300,8 @@
return true;
}
-void Texture::SetTarget(GLenum target, GLint max_levels) {
+void Texture::SetTarget(
+ const FeatureInfo* feature_info, GLenum target, GLint max_levels) {
DCHECK_EQ(0u, target_); // you can only set this once.
target_ = target;
size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
@@ -260,6 +318,8 @@
if (target == GL_TEXTURE_EXTERNAL_OES) {
immutable_ = true;
}
+ Update(feature_info);
+ UpdateCanRenderCondition();
}
bool Texture::CanGenerateMipmaps(
@@ -305,13 +365,7 @@
level_infos_[GLTargetToFaceIndex(target)].size());
Texture::LevelInfo& info =
level_infos_[GLTargetToFaceIndex(target)][level];
- if (!info.cleared) {
- DCHECK_NE(0, num_uncleared_mips_);
- --num_uncleared_mips_;
- } else {
- ++num_uncleared_mips_;
- }
- info.cleared = cleared;
+ UpdateMipCleared(&info, cleared);
UpdateCleared();
}
@@ -323,17 +377,61 @@
const Texture::LevelInfo& first_face = level_infos_[0][0];
int levels_needed = TextureManager::ComputeMipMapCount(
first_face.width, first_face.height, first_face.depth);
- cleared_ = true;
+ bool cleared = true;
for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
for (GLint jj = 0; jj < levels_needed; ++jj) {
const Texture::LevelInfo& info = level_infos_[ii][jj];
if (info.width > 0 && info.height > 0 && info.depth > 0 &&
!info.cleared) {
- cleared_ = false;
- return;
+ cleared = false;
+ break;
}
}
}
+ UpdateSafeToRenderFrom(cleared);
+}
+
+void Texture::UpdateSafeToRenderFrom(bool cleared) {
+ if (cleared_ == cleared)
+ return;
+ cleared_ = cleared;
+ int delta = cleared ? -1 : +1;
+ for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
+ (*it)->manager()->UpdateSafeToRenderFrom(delta);
+}
+
+void Texture::UpdateMipCleared(LevelInfo* info, bool cleared) {
+ if (info->cleared == cleared)
+ return;
+ info->cleared = cleared;
+ int delta = cleared ? -1 : +1;
+ num_uncleared_mips_ += delta;
+ for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
+ (*it)->manager()->UpdateUnclearedMips(delta);
+}
+
+void Texture::UpdateCanRenderCondition() {
+ CanRenderCondition can_render_condition = GetCanRenderCondition();
+ if (can_render_condition_ == can_render_condition)
+ return;
+ for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
+ (*it)->manager()->UpdateCanRenderCondition(can_render_condition_,
+ can_render_condition);
+ can_render_condition_ = can_render_condition;
+}
+
+void Texture::IncAllFramebufferStateChangeCount() {
+ for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
+ (*it)->manager()->IncFramebufferStateChangeCount();
+}
+
+AsyncPixelTransferState* Texture::GetAsyncTransferState() const {
+ for (RefSet::const_iterator it = refs_.begin(); it != refs_.end(); ++it) {
+ AsyncPixelTransferState* state = (*it)->async_transfer_state();
+ if (state)
+ return state;
+ }
+ return NULL;
}
void Texture::SetLevelInfo(
@@ -374,17 +472,16 @@
width, height, format, type, 4, &info.estimated_size, NULL, NULL);
estimated_size_ += info.estimated_size;
- if (!info.cleared) {
- DCHECK_NE(0, num_uncleared_mips_);
- --num_uncleared_mips_;
- }
- info.cleared = cleared;
- if (!info.cleared) {
- ++num_uncleared_mips_;
- }
+ UpdateMipCleared(&info, cleared);
max_level_set_ = std::max(max_level_set_, level);
Update(feature_info);
UpdateCleared();
+ UpdateCanRenderCondition();
+ if (IsAttachedToFramebuffer()) {
+ // TODO(gman): If textures tracked which framebuffers they were attached to
+ // we could just mark those framebuffers as not complete.
+ IncAllFramebufferStateChangeCount();
+ }
}
bool Texture::ValidForTexture(
@@ -479,9 +576,9 @@
if (!feature_info->validators()->texture_pool.IsValid(param)) {
return GL_INVALID_ENUM;
}
- manager_->GetMemTracker(pool_)->TrackMemFree(estimated_size());
+ GetMemTracker()->TrackMemFree(estimated_size());
pool_ = param;
- manager_->GetMemTracker(pool_)->TrackMemAlloc(estimated_size());
+ GetMemTracker()->TrackMemAlloc(estimated_size());
break;
case GL_TEXTURE_WRAP_S:
if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
@@ -512,12 +609,14 @@
}
Update(feature_info);
UpdateCleared();
+ UpdateCanRenderCondition();
return GL_NO_ERROR;
}
void Texture::Update(const FeatureInfo* feature_info) {
// Update npot status.
- npot_ = false;
+ // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
+ npot_ = target_ == GL_TEXTURE_EXTERNAL_OES;
if (level_infos_.empty()) {
texture_complete_ = false;
@@ -598,7 +697,7 @@
bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) {
DCHECK(decoder);
- if (SafeToRenderFrom()) {
+ if (cleared_) {
return true;
}
@@ -616,7 +715,7 @@
}
}
}
- cleared_ = true;
+ UpdateSafeToRenderFrom(true);
return true;
}
@@ -653,18 +752,13 @@
return true;
}
- DCHECK_NE(0, num_uncleared_mips_);
- --num_uncleared_mips_;
-
// NOTE: It seems kind of gross to call back into the decoder for this
// but only the decoder knows all the state (like unpack_alignment_) that's
// needed to be able to call GL correctly.
- info.cleared = decoder->ClearLevel(
+ bool cleared = decoder->ClearLevel(
service_id_, target_, info.target, info.level, info.format, info.type,
info.width, info.height, immutable_);
- if (!info.cleared) {
- ++num_uncleared_mips_;
- }
+ UpdateMipCleared(&info, cleared);
return info.cleared;
}
@@ -683,6 +777,7 @@
DCHECK_EQ(info.target, target);
DCHECK_EQ(info.level, level);
info.image = image;
+ UpdateCanRenderCondition();
}
gfx::GLImage* Texture::GetLevelImage(
@@ -698,6 +793,28 @@
return 0;
}
+
+TextureRef::TextureRef(TextureManager* manager, Texture* texture)
+ : manager_(manager),
+ texture_(texture) {
+ DCHECK(manager_);
+ DCHECK(texture_);
+ texture_->AddTextureRef(this);
+ manager_->StartTracking(this);
+}
+
+scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager,
+ GLuint service_id) {
+ return new TextureRef(manager, new Texture(service_id));
+}
+
+TextureRef::~TextureRef() {
+ manager_->StopTracking(this);
+ texture_->RemoveTextureRef(this, manager_->have_context_);
+ manager_ = NULL;
+}
+
+
TextureManager::TextureManager(
MemoryTracker* memory_tracker,
FeatureInfo* feature_info,
@@ -708,6 +825,7 @@
memory_tracker_unmanaged_(
new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)),
feature_info_(feature_info),
+ framebuffer_manager_(NULL),
max_texture_size_(max_texture_size),
max_cube_map_texture_size_(max_cube_map_texture_size),
max_levels_(ComputeMipMapCount(max_texture_size,
@@ -749,7 +867,7 @@
return true;
}
-scoped_refptr<Texture>
+scoped_refptr<TextureRef>
TextureManager::CreateDefaultAndBlackTextures(
GLenum target,
GLuint* black_texture) {
@@ -779,10 +897,7 @@
}
glBindTexture(target, 0);
- // Since we are manually setting up these textures
- // we need to manually manipulate some of the their bookkeeping.
- ++num_unrenderable_textures_;
- scoped_refptr<Texture> default_texture(new Texture(this, ids[1]));
+ scoped_refptr<TextureRef> default_texture(TextureRef::Create(this, ids[1]));
SetTarget(default_texture, target);
if (needs_faces) {
for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
@@ -825,78 +940,45 @@
(target != GL_TEXTURE_2D || (depth == 1));
}
-void TextureManager::SetTarget(Texture* texture, GLenum target) {
- DCHECK(texture);
- if (!texture->CanRender(feature_info_)) {
- DCHECK_NE(0, num_unrenderable_textures_);
- --num_unrenderable_textures_;
- }
- texture->SetTarget(target, MaxLevelsForTarget(target));
- if (!texture->CanRender(feature_info_)) {
- ++num_unrenderable_textures_;
- }
+void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
+ DCHECK(ref);
+ ref->texture()->SetTarget(feature_info_, target, MaxLevelsForTarget(target));
}
-void TextureManager::SetLevelCleared(Texture* texture,
+void TextureManager::SetStreamTexture(TextureRef* ref, bool stream_texture) {
+ DCHECK(ref);
+ ref->texture()->SetStreamTexture(stream_texture);
+}
+
+void TextureManager::SetLevelCleared(TextureRef* ref,
GLenum target,
GLint level,
bool cleared) {
- DCHECK(texture);
- if (!texture->SafeToRenderFrom()) {
- DCHECK_NE(0, num_unsafe_textures_);
- --num_unsafe_textures_;
- }
- num_uncleared_mips_ -= texture->num_uncleared_mips();
- DCHECK_GE(num_uncleared_mips_, 0);
- texture->SetLevelCleared(target, level, cleared);
- num_uncleared_mips_ += texture->num_uncleared_mips();
- if (!texture->SafeToRenderFrom()) {
- ++num_unsafe_textures_;
- }
+ DCHECK(ref);
+ ref->texture()->SetLevelCleared(target, level, cleared);
}
bool TextureManager::ClearRenderableLevels(
- GLES2Decoder* decoder,Texture* texture) {
- DCHECK(texture);
- if (texture->SafeToRenderFrom()) {
- return true;
- }
- DCHECK_NE(0, num_unsafe_textures_);
- --num_unsafe_textures_;
- num_uncleared_mips_ -= texture->num_uncleared_mips();
- DCHECK_GE(num_uncleared_mips_, 0);
- bool result = texture->ClearRenderableLevels(decoder);
- num_uncleared_mips_ += texture->num_uncleared_mips();
- if (!texture->SafeToRenderFrom()) {
- ++num_unsafe_textures_;
- }
- return result;
+ GLES2Decoder* decoder, TextureRef* ref) {
+ DCHECK(ref);
+ return ref->texture()->ClearRenderableLevels(decoder);
}
bool TextureManager::ClearTextureLevel(
- GLES2Decoder* decoder,Texture* texture,
+ GLES2Decoder* decoder, TextureRef* ref,
GLenum target, GLint level) {
- DCHECK(texture);
+ DCHECK(ref);
+ Texture* texture = ref->texture();
if (texture->num_uncleared_mips() == 0) {
return true;
}
- num_uncleared_mips_ -= texture->num_uncleared_mips();
- DCHECK_GE(num_uncleared_mips_, 0);
- if (!texture->SafeToRenderFrom()) {
- DCHECK_NE(0, num_unsafe_textures_);
- --num_unsafe_textures_;
- }
bool result = texture->ClearLevel(decoder, target, level);
texture->UpdateCleared();
- num_uncleared_mips_ += texture->num_uncleared_mips();
- if (!texture->SafeToRenderFrom()) {
- ++num_unsafe_textures_;
- }
return result;
}
void TextureManager::SetLevelInfo(
- Texture* texture,
+ TextureRef* ref,
GLenum target,
GLint level,
GLenum internal_format,
@@ -907,34 +989,19 @@
GLenum format,
GLenum type,
bool cleared) {
- DCHECK(texture);
- if (!texture->CanRender(feature_info_)) {
- DCHECK_NE(0, num_unrenderable_textures_);
- --num_unrenderable_textures_;
- }
- if (!texture->SafeToRenderFrom()) {
- DCHECK_NE(0, num_unsafe_textures_);
- --num_unsafe_textures_;
- }
- num_uncleared_mips_ -= texture->num_uncleared_mips();
- DCHECK_GE(num_uncleared_mips_, 0);
+ DCHECK(ref);
+ Texture* texture = ref->texture();
- GetMemTracker(texture->pool_)->TrackMemFree(texture->estimated_size());
+ texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
texture->SetLevelInfo(
feature_info_, target, level, internal_format, width, height, depth,
border, format, type, cleared);
- GetMemTracker(texture->pool_)->TrackMemAlloc(texture->estimated_size());
-
- num_uncleared_mips_ += texture->num_uncleared_mips();
- if (!texture->CanRender(feature_info_)) {
- ++num_unrenderable_textures_;
- }
- if (!texture->SafeToRenderFrom()) {
- ++num_unsafe_textures_;
- }
+ texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
}
-TextureDefinition* TextureManager::Save(Texture* texture) {
+TextureDefinition* TextureManager::Save(TextureRef* ref) {
+ DCHECK(ref);
+ Texture* texture = ref->texture();
DCHECK(texture->owned_);
if (texture->IsAttachedToFramebuffer())
@@ -960,7 +1027,7 @@
level_info.type,
level_info.cleared));
- SetLevelInfo(texture,
+ SetLevelInfo(ref,
target,
level,
GL_RGBA,
@@ -999,8 +1066,10 @@
bool TextureManager::Restore(
const char* function_name,
GLES2Decoder* decoder,
- Texture* texture,
+ TextureRef* ref,
TextureDefinition* definition) {
+ DCHECK(ref);
+ Texture* texture = ref->texture();
DCHECK(texture->owned_);
scoped_ptr<TextureDefinition> scoped_definition(definition);
@@ -1028,7 +1097,7 @@
const TextureDefinition::LevelInfo& level_info =
level <= new_max_level ? definition->level_infos()[face][level]
: TextureDefinition::LevelInfo();
- SetLevelInfo(texture,
+ SetLevelInfo(ref,
target,
level,
level_info.internal_format,
@@ -1048,19 +1117,18 @@
glBindTexture(texture->target(), texture->service_id());
texture->SetImmutable(definition->immutable());
texture->SetStreamTexture(definition->stream_texture());
-
ErrorState* error_state = decoder->GetErrorState();
- SetParameter(function_name, error_state, texture, GL_TEXTURE_MIN_FILTER,
+ SetParameter(function_name, error_state, ref, GL_TEXTURE_MIN_FILTER,
definition->min_filter());
- SetParameter(function_name, error_state, texture, GL_TEXTURE_MAG_FILTER,
+ SetParameter(function_name, error_state, ref, GL_TEXTURE_MAG_FILTER,
definition->mag_filter());
- SetParameter(function_name, error_state, texture, GL_TEXTURE_WRAP_S,
+ SetParameter(function_name, error_state, ref, GL_TEXTURE_WRAP_S,
definition->wrap_s());
- SetParameter(function_name, error_state, texture, GL_TEXTURE_WRAP_T,
+ SetParameter(function_name, error_state, ref, GL_TEXTURE_WRAP_T,
definition->wrap_t());
if (feature_info_->validators()->texture_parameter.IsValid(
GL_TEXTURE_USAGE_ANGLE)) {
- SetParameter(function_name, error_state, texture, GL_TEXTURE_USAGE_ANGLE,
+ SetParameter(function_name, error_state, ref, GL_TEXTURE_USAGE_ANGLE,
definition->usage());
}
@@ -1069,17 +1137,10 @@
void TextureManager::SetParameter(
const char* function_name, ErrorState* error_state,
- Texture* texture, GLenum pname, GLint param) {
+ TextureRef* ref, GLenum pname, GLint param) {
DCHECK(error_state);
- DCHECK(texture);
- if (!texture->CanRender(feature_info_)) {
- DCHECK_NE(0, num_unrenderable_textures_);
- --num_unrenderable_textures_;
- }
- if (!texture->SafeToRenderFrom()) {
- DCHECK_NE(0, num_unsafe_textures_);
- --num_unsafe_textures_;
- }
+ DCHECK(ref);
+ Texture* texture = ref->texture();
GLenum result = texture->SetParameter(feature_info_, pname, param);
if (result != GL_NO_ERROR) {
if (result == GL_INVALID_ENUM) {
@@ -1096,59 +1157,28 @@
glTexParameteri(texture->target(), pname, param);
}
}
-
- if (!texture->CanRender(feature_info_)) {
- ++num_unrenderable_textures_;
- }
- if (!texture->SafeToRenderFrom()) {
- ++num_unsafe_textures_;
- }
}
-bool TextureManager::MarkMipmapsGenerated(Texture* texture) {
- DCHECK(texture);
- if (!texture->CanRender(feature_info_)) {
- DCHECK_NE(0, num_unrenderable_textures_);
- --num_unrenderable_textures_;
- }
- if (!texture->SafeToRenderFrom()) {
- DCHECK_NE(0, num_unsafe_textures_);
- --num_unsafe_textures_;
- }
- num_uncleared_mips_ -= texture->num_uncleared_mips();
- DCHECK_GE(num_uncleared_mips_, 0);
- GetMemTracker(texture->pool_)->TrackMemFree(texture->estimated_size());
+bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) {
+ DCHECK(ref);
+ Texture* texture = ref->texture();
+ texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
bool result = texture->MarkMipmapsGenerated(feature_info_);
- GetMemTracker(texture->pool_)->TrackMemAlloc(texture->estimated_size());
-
- num_uncleared_mips_ += texture->num_uncleared_mips();
- if (!texture->CanRender(feature_info_)) {
- ++num_unrenderable_textures_;
- }
- if (!texture->SafeToRenderFrom()) {
- ++num_unsafe_textures_;
- }
+ texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
return result;
}
-Texture* TextureManager::CreateTexture(
+TextureRef* TextureManager::CreateTexture(
GLuint client_id, GLuint service_id) {
DCHECK_NE(0u, service_id);
- scoped_refptr<Texture> texture(new Texture(this, service_id));
+ scoped_refptr<TextureRef> ref(TextureRef::Create(this, service_id));
std::pair<TextureMap::iterator, bool> result =
- textures_.insert(std::make_pair(client_id, texture));
+ textures_.insert(std::make_pair(client_id, ref));
DCHECK(result.second);
- if (!texture->CanRender(feature_info_)) {
- ++num_unrenderable_textures_;
- }
- if (!texture->SafeToRenderFrom()) {
- ++num_unsafe_textures_;
- }
- num_uncleared_mips_ += texture->num_uncleared_mips();
- return texture.get();
+ return ref.get();
}
-Texture* TextureManager::GetTexture(
+TextureRef* TextureManager::GetTexture(
GLuint client_id) const {
TextureMap::const_iterator it = textures_.find(client_id);
return it != textures_.end() ? it->second : NULL;
@@ -1157,17 +1187,22 @@
void TextureManager::RemoveTexture(GLuint client_id) {
TextureMap::iterator it = textures_.find(client_id);
if (it != textures_.end()) {
- Texture* texture = it->second;
- texture->MarkAsDeleted();
textures_.erase(it);
}
}
-void TextureManager::StartTracking(Texture* /* texture */) {
+void TextureManager::StartTracking(TextureRef* ref) {
+ Texture* texture = ref->texture();
++texture_count_;
+ num_uncleared_mips_ += texture->num_uncleared_mips();
+ if (!texture->SafeToRenderFrom())
+ ++num_unsafe_textures_;
+ if (!texture->CanRender(feature_info_))
+ ++num_unrenderable_textures_;
}
-void TextureManager::StopTracking(Texture* texture) {
+void TextureManager::StopTracking(TextureRef* ref) {
+ Texture* texture = ref->texture();
--texture_count_;
if (!texture->CanRender(feature_info_)) {
DCHECK_NE(0, num_unrenderable_textures_);
@@ -1179,7 +1214,6 @@
}
num_uncleared_mips_ -= texture->num_uncleared_mips();
DCHECK_GE(num_uncleared_mips_, 0);
- GetMemTracker(texture->pool_)->TrackMemFree(texture->estimated_size());
}
MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) {
@@ -1201,7 +1235,7 @@
// This doesn't need to be fast. It's only used during slow queries.
for (TextureMap::const_iterator it = textures_.begin();
it != textures_.end(); ++it) {
- if (it->second->service_id() == service_id) {
+ if (it->second->texture()->service_id() == service_id) {
*client_id = it->first;
return true;
}
@@ -1215,34 +1249,51 @@
}
void TextureManager::SetLevelImage(
- Texture* texture,
+ TextureRef* ref,
GLenum target,
GLint level,
gfx::GLImage* image) {
- DCHECK(texture);
- if (!texture->CanRender(feature_info_)) {
- DCHECK_NE(0, num_unrenderable_textures_);
- --num_unrenderable_textures_;
- }
- if (!texture->SafeToRenderFrom()) {
- DCHECK_NE(0, num_unsafe_textures_);
- --num_unsafe_textures_;
- }
- texture->SetLevelImage(feature_info_, target, level, image);
- if (!texture->CanRender(feature_info_)) {
- ++num_unrenderable_textures_;
- }
- if (!texture->SafeToRenderFrom()) {
- ++num_unsafe_textures_;
- }
+ DCHECK(ref);
+ ref->texture()->SetLevelImage(feature_info_, target, level, image);
}
void TextureManager::AddToSignature(
- Texture* texture,
+ TextureRef* ref,
GLenum target,
GLint level,
std::string* signature) const {
- texture->AddToSignature(feature_info_.get(), target, level, signature);
+ ref->texture()->AddToSignature(feature_info_.get(), target, level, signature);
+}
+
+void TextureManager::UpdateSafeToRenderFrom(int delta) {
+ num_unsafe_textures_ += delta;
+ DCHECK_GE(num_unsafe_textures_, 0);
+}
+
+void TextureManager::UpdateUnclearedMips(int delta) {
+ num_uncleared_mips_ += delta;
+ DCHECK_GE(num_uncleared_mips_, 0);
+}
+
+void TextureManager::UpdateCanRenderCondition(
+ Texture::CanRenderCondition old_condition,
+ Texture::CanRenderCondition new_condition) {
+ if (old_condition == Texture::CAN_RENDER_NEVER ||
+ (old_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
+ !feature_info_->feature_flags().npot_ok)) {
+ DCHECK_GT(num_unrenderable_textures_, 0);
+ --num_unrenderable_textures_;
+ }
+ if (new_condition == Texture::CAN_RENDER_NEVER ||
+ (new_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
+ !feature_info_->feature_flags().npot_ok))
+ ++num_unrenderable_textures_;
+}
+
+void TextureManager::IncFramebufferStateChangeCount() {
+ if (framebuffer_manager_)
+ framebuffer_manager_->IncFramebufferStateChangeCount();
+
}
} // namespace gles2
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index 7293f27..af5eb0c 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -6,6 +6,7 @@
#define GPU_COMMAND_BUFFER_SERVICE_TEXTURE_MANAGER_H_
#include <list>
+#include <set>
#include <string>
#include <vector>
#include "base/basictypes.h"
@@ -25,13 +26,17 @@
class Display;
class ErrorState;
class FeatureInfo;
+class FramebufferManager;
class TextureDefinition;
class TextureManager;
+class TextureRef;
// Info about Textures currently in the system.
-class GPU_EXPORT Texture : public base::RefCounted<Texture> {
+// This class wraps a real GL texture, keeping track of its meta-data. It is
+// jointly owned by possibly multiple TextureRef.
+class GPU_EXPORT Texture {
public:
- Texture(TextureManager* manager, GLuint service_id);
+ explicit Texture(GLuint service_id);
GLenum min_filter() const {
return min_filter_;
@@ -102,10 +107,6 @@
// does not exist.
gfx::GLImage* GetLevelImage(GLint target, GLint level) const;
- bool IsDeleted() const {
- return deleted_;
- }
-
// Returns true of the given dimensions are inside the dimensions of the
// level and if the format and type match the level.
bool ValidForTexture(
@@ -119,7 +120,7 @@
GLenum type) const;
bool IsValid() const {
- return target() && !IsDeleted();
+ return !!target();
}
void SetNotOwned() {
@@ -139,30 +140,24 @@
--framebuffer_attachment_count_;
}
- void SetStreamTexture(bool stream_texture) {
- stream_texture_ = stream_texture;
- }
-
- bool IsStreamTexture() {
+ bool IsStreamTexture() const {
return stream_texture_;
}
- gpu::AsyncPixelTransferState* GetAsyncTransferState() const {
- return async_transfer_state_.get();
- }
- void SetAsyncTransferState(scoped_ptr<gpu::AsyncPixelTransferState> state) {
- async_transfer_state_ = state.Pass();
- }
+ // Gets the async transfer state for this texture. Note: the transfer state is
+ // owned by a single TextureRef.
+ AsyncPixelTransferState* GetAsyncTransferState() const;
+
bool AsyncTransferIsInProgress() {
- return async_transfer_state_ &&
- async_transfer_state_->TransferIsInProgress();
+ AsyncPixelTransferState* state = GetAsyncTransferState();
+ return state && state->TransferIsInProgress();
}
void SetImmutable(bool immutable) {
immutable_ = immutable;
}
- bool IsImmutable() {
+ bool IsImmutable() const {
return immutable_;
}
@@ -170,16 +165,31 @@
bool IsLevelCleared(GLenum target, GLint level) const;
// Whether the texture has been defined
- bool IsDefined() {
+ bool IsDefined() const {
return estimated_size() > 0;
}
private:
friend class TextureManager;
+ friend class TextureRef;
friend class TextureTestHelper;
- friend class base::RefCounted<Texture>;
~Texture();
+ void AddTextureRef(TextureRef* ref);
+ void RemoveTextureRef(TextureRef* ref, bool have_context);
+ MemoryTypeTracker* GetMemTracker();
+
+ // Condition on which this texture is renderable. Can be ONLY_IF_NPOT if it
+ // depends on context support for non-power-of-two textures (i.e. will be
+ // renderable if NPOT support is in the context, otherwise not, e.g. texture
+ // with a NPOT level). ALWAYS means it doesn't depend on context features
+ // (e.g. complete POT), NEVER means it's not renderable regardless (e.g.
+ // incomplete).
+ enum CanRenderCondition {
+ CAN_RENDER_ALWAYS,
+ CAN_RENDER_NEVER,
+ CAN_RENDER_ONLY_IF_NPOT
+ };
struct LevelInfo {
LevelInfo();
@@ -232,6 +242,11 @@
return npot_;
}
+ void SetStreamTexture(bool stream_texture) {
+ stream_texture_ = stream_texture;
+ UpdateCanRenderCondition();
+ }
+
// Marks a particular level as cleared or uncleared.
void SetLevelCleared(GLenum target, GLint level, bool cleared);
@@ -255,10 +270,6 @@
// Makes each of the mip levels as though they were generated.
bool MarkMipmapsGenerated(const FeatureInfo* feature_info);
- void MarkAsDeleted() {
- deleted_ = true;
- }
-
bool NeedsMips() const {
return min_filter_ != GL_NEAREST && min_filter_ != GL_LINEAR;
}
@@ -275,7 +286,8 @@
// target: GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP or
// GL_TEXTURE_EXTERNAL_OES or GL_TEXTURE_RECTANGLE_ARB
// max_levels: The maximum levels this type of target can have.
- void SetTarget(GLenum target, GLint max_levels);
+ void SetTarget(
+ const FeatureInfo* feature_info, GLenum target, GLint max_levels);
// Update info about this texture.
void Update(const FeatureInfo* feature_info);
@@ -292,18 +304,39 @@
const FeatureInfo* feature_info,
GLenum target, GLint level, std::string* signature) const;
+ // Updates the unsafe textures count in all the managers referencing this
+ // texture.
+ void UpdateSafeToRenderFrom(bool cleared);
+
+ // Updates the uncleared mip count in all the managers referencing this
+ // texture.
+ void UpdateMipCleared(LevelInfo* info, bool cleared);
+
+ // Computes the CanRenderCondition flag.
+ CanRenderCondition GetCanRenderCondition() const;
+
+ // Updates the unrenderable texture count in all the managers referencing this
+ // texture.
+ void UpdateCanRenderCondition();
+
+ // Increment the framebuffer state change count in all the managers
+ // referencing this texture.
+ void IncAllFramebufferStateChangeCount();
+
// Info about each face and level of texture.
std::vector<std::vector<LevelInfo> > level_infos_;
- // The texture manager that manages this Texture.
- TextureManager* manager_;
+ // The texture refs that point to this Texture.
+ typedef std::set<TextureRef*> RefSet;
+ RefSet refs_;
+
+ // The single TextureRef that accounts for memory for this texture. Must be
+ // one of refs_.
+ TextureRef* memory_tracking_ref_;
// The id of the texure
GLuint service_id_;
- // Whether this texture has been deleted.
- bool deleted_;
-
// Whether all renderable mips of this texture have been cleared.
bool cleared_;
@@ -345,9 +378,6 @@
// Whether this is a special streaming texture.
bool stream_texture_;
- // State to facilitate async transfers on this texture.
- scoped_ptr<gpu::AsyncPixelTransferState> async_transfer_state_;
-
// Whether the texture is immutable and no further changes to the format
// or dimensions of the texture object can be made.
bool immutable_;
@@ -355,9 +385,55 @@
// Size in bytes this texture is assumed to take in memory.
uint32 estimated_size_;
+ // Cache of the computed CanRenderCondition flag.
+ CanRenderCondition can_render_condition_;
+
DISALLOW_COPY_AND_ASSIGN(Texture);
};
+// This class represents a texture in a client context group. It's mostly 1:1
+// with a client id, though it can outlive the client id if it's still bound to
+// a FBO or another context when destroyed.
+// Multiple TextureRef can point to the same texture with cross-context sharing.
+class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> {
+ public:
+ TextureRef(TextureManager* manager, Texture* texture);
+ static scoped_refptr<TextureRef> Create(TextureManager* manager,
+ GLuint service_id);
+ const Texture* texture() const { return texture_; }
+ Texture* texture() { return texture_; }
+ GLuint service_id() const { return texture_->service_id(); }
+
+ // Sets the async transfer state for this texture. Only a single TextureRef
+ // can set this on a given texture at any time.
+ // NOTE: this should be per-context rather than per-texture. crbug.com/240504
+ void SetAsyncTransferState(
+ scoped_ptr<AsyncPixelTransferState> state) {
+ DCHECK(!state || !texture_->GetAsyncTransferState());
+ async_transfer_state_ = state.Pass();
+ }
+
+ private:
+ friend class base::RefCounted<TextureRef>;
+ friend class Texture;
+ friend class TextureManager;
+
+ ~TextureRef();
+ const TextureManager* manager() const { return manager_; }
+ TextureManager* manager() { return manager_; }
+ AsyncPixelTransferState* async_transfer_state() const {
+ return async_transfer_state_.get();
+ }
+
+ TextureManager* manager_;
+ Texture* texture_;
+
+ // State to facilitate async transfers on this texture.
+ scoped_ptr<AsyncPixelTransferState> async_transfer_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(TextureRef);
+};
+
// This class keeps track of the textures and their sizes so we can do NPOT and
// texture complete checking.
//
@@ -379,6 +455,10 @@
GLsizei max_cube_map_texture_size);
~TextureManager();
+ void set_framebuffer_manager(FramebufferManager* manager) {
+ framebuffer_manager_ = manager;
+ }
+
// Init the texture manager.
bool Initialize();
@@ -419,13 +499,13 @@
// True if this texture meets all the GLES2 criteria for rendering.
// See section 3.8.2 of the GLES2 spec.
- bool CanRender(const Texture* texture) const {
- return texture->CanRender(feature_info_);
+ bool CanRender(const TextureRef* ref) const {
+ return ref->texture()->CanRender(feature_info_);
}
// Returns true if mipmaps can be generated by GL.
- bool CanGenerateMipmaps(const Texture* texture) const {
- return texture->CanGenerateMipmaps(feature_info_);
+ bool CanGenerateMipmaps(const TextureRef* ref) const {
+ return ref->texture()->CanGenerateMipmaps(feature_info_);
}
// Sets the Texture's target
@@ -433,12 +513,15 @@
// target: GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP
// max_levels: The maximum levels this type of target can have.
void SetTarget(
- Texture* texture,
+ TextureRef* ref,
GLenum target);
+ // Marks a texture as a stream texture.
+ void SetStreamTexture(TextureRef* ref, bool stream_texture);
+
// Set the info for a particular level in a TexureInfo.
void SetLevelInfo(
- Texture* texture,
+ TextureRef* ref,
GLenum target,
GLint level,
GLenum internal_format,
@@ -451,27 +534,27 @@
bool cleared);
// Adapter to call above function.
- void SetLevelInfoFromParams(Texture* texture,
+ void SetLevelInfoFromParams(TextureRef* ref,
const gpu::AsyncTexImage2DParams& params) {
SetLevelInfo(
- texture, params.target, params.level, params.internal_format,
+ ref, params.target, params.level, params.internal_format,
params.width, params.height, 1 /* depth */,
params.border, params.format,
params.type, true /* cleared */ );
}
// Save the texture definition and leave it undefined.
- TextureDefinition* Save(Texture* texture);
+ TextureDefinition* Save(TextureRef* ref);
// Redefine all the levels from the texture definition.
bool Restore(
const char* function_name,
GLES2Decoder* decoder,
- Texture* texture,
+ TextureRef* ref,
TextureDefinition* definition);
// Sets a mip as cleared.
- void SetLevelCleared(Texture* texture, GLenum target,
+ void SetLevelCleared(TextureRef* ref, GLenum target,
GLint level, bool cleared);
// Sets a texture parameter of a Texture
@@ -479,24 +562,24 @@
// TODO(gman): Expand to SetParameteri,f,iv,fv
void SetParameter(
const char* function_name, ErrorState* error_state,
- Texture* texture, GLenum pname, GLint param);
+ TextureRef* ref, GLenum pname, GLint param);
// Makes each of the mip levels as though they were generated.
// Returns false if that's not allowed for the given texture.
- bool MarkMipmapsGenerated(Texture* texture);
+ bool MarkMipmapsGenerated(TextureRef* ref);
// Clears any uncleared renderable levels.
- bool ClearRenderableLevels(GLES2Decoder* decoder, Texture* texture);
+ bool ClearRenderableLevels(GLES2Decoder* decoder, TextureRef* ref);
// Clear a specific level.
bool ClearTextureLevel(
- GLES2Decoder* decoder,Texture* texture, GLenum target, GLint level);
+ GLES2Decoder* decoder, TextureRef* ref, GLenum target, GLint level);
// Creates a new texture info.
- Texture* CreateTexture(GLuint client_id, GLuint service_id);
+ TextureRef* CreateTexture(GLuint client_id, GLuint service_id);
// Gets the texture info for the given texture.
- Texture* GetTexture(GLuint client_id) const;
+ TextureRef* GetTexture(GLuint client_id) const;
// Removes a texture info.
void RemoveTexture(GLuint client_id);
@@ -504,7 +587,7 @@
// Gets a client id for a given service id.
bool GetClientId(GLuint service_id, GLuint* client_id) const;
- Texture* GetDefaultTextureInfo(GLenum target) {
+ TextureRef* GetDefaultTextureInfo(GLenum target) {
switch (target) {
case GL_TEXTURE_2D:
return default_textures_[kTexture2D];
@@ -555,27 +638,34 @@
}
void SetLevelImage(
- Texture* texture,
+ TextureRef* ref,
GLenum target,
GLint level,
gfx::GLImage* image);
void AddToSignature(
- Texture* texture,
+ TextureRef* ref,
GLenum target,
GLint level,
std::string* signature) const;
private:
friend class Texture;
+ friend class TextureRef;
// Helper for Initialize().
- scoped_refptr<Texture> CreateDefaultAndBlackTextures(
+ scoped_refptr<TextureRef> CreateDefaultAndBlackTextures(
GLenum target,
GLuint* black_texture);
- void StartTracking(Texture* texture);
- void StopTracking(Texture* texture);
+ void StartTracking(TextureRef* texture);
+ void StopTracking(TextureRef* texture);
+
+ void UpdateSafeToRenderFrom(int delta);
+ void UpdateUnclearedMips(int delta);
+ void UpdateCanRenderCondition(Texture::CanRenderCondition old_condition,
+ Texture::CanRenderCondition new_condition);
+ void IncFramebufferStateChangeCount();
MemoryTypeTracker* GetMemTracker(GLenum texture_pool);
scoped_ptr<MemoryTypeTracker> memory_tracker_managed_;
@@ -583,8 +673,10 @@
scoped_refptr<FeatureInfo> feature_info_;
+ FramebufferManager* framebuffer_manager_;
+
// Info for each texture in the system.
- typedef base::hash_map<GLuint, scoped_refptr<Texture> > TextureMap;
+ typedef base::hash_map<GLuint, scoped_refptr<TextureRef> > TextureMap;
TextureMap textures_;
GLsizei max_texture_size_;
@@ -608,7 +700,7 @@
GLuint black_texture_ids_[kNumDefaultTextures];
// The default textures for each target (texture name = 0)
- scoped_refptr<Texture> default_textures_[kNumDefaultTextures];
+ scoped_refptr<TextureRef> default_textures_[kNumDefaultTextures];
DISALLOW_COPY_AND_ASSIGN(TextureManager);
};
diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc
index bef870b..c66ffa6 100644
--- a/gpu/command_buffer/service/texture_manager_unittest.cc
+++ b/gpu/command_buffer/service/texture_manager_unittest.cc
@@ -7,6 +7,7 @@
#include "base/memory/scoped_ptr.h"
#include "gpu/command_buffer/service/error_state_mock.h"
#include "gpu/command_buffer/service/feature_info.h"
+#include "gpu/command_buffer/service/framebuffer_manager.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/mocks.h"
@@ -75,10 +76,10 @@
}
void SetParameter(
- Texture* texture, GLenum pname, GLint value, GLenum error) {
+ TextureRef* texture_ref, GLenum pname, GLint value, GLenum error) {
TestHelper::SetTexParameterWithExpectations(
gl_.get(), error_state_.get(), manager_.get(),
- texture, pname, value, error);
+ texture_ref, pname, value, error);
}
// Use StrictMock to make 100% sure we know how GL will be called.
@@ -108,7 +109,7 @@
// Check we can create texture.
manager_->CreateTexture(kClient1Id, kService1Id);
// Check texture got created.
- Texture* texture = manager_->GetTexture(kClient1Id);
+ TextureRef* texture = manager_->GetTexture(kClient1Id);
ASSERT_TRUE(texture != NULL);
EXPECT_EQ(kService1Id, texture->service_id());
GLuint client_id = 0;
@@ -133,30 +134,31 @@
// Check we can create texture.
manager_->CreateTexture(kClient1Id, kService1Id);
// Check texture got created.
- Texture* texture = manager_->GetTexture(kClient1Id);
- manager_->SetTarget(texture, GL_TEXTURE_2D);
- ASSERT_TRUE(texture != NULL);
- SetParameter(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST, GL_NO_ERROR);
+ TextureRef* texture_ref = manager_->GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
+ manager_->SetTarget(texture_ref, GL_TEXTURE_2D);
+ SetParameter(texture_ref, GL_TEXTURE_MIN_FILTER, GL_NEAREST, GL_NO_ERROR);
EXPECT_EQ(static_cast<GLenum>(GL_NEAREST), texture->min_filter());
- SetParameter(texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
+ SetParameter(texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
EXPECT_EQ(static_cast<GLenum>(GL_NEAREST), texture->mag_filter());
- SetParameter(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
+ SetParameter(texture_ref, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
EXPECT_EQ(static_cast<GLenum>(GL_CLAMP_TO_EDGE), texture->wrap_s());
- SetParameter(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
+ SetParameter(texture_ref, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
EXPECT_EQ(static_cast<GLenum>(GL_CLAMP_TO_EDGE), texture->wrap_t());
- SetParameter(texture, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1, GL_NO_ERROR);
- SetParameter(texture, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2, GL_NO_ERROR);
+ SetParameter(texture_ref, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1, GL_NO_ERROR);
+ SetParameter(texture_ref, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2, GL_NO_ERROR);
SetParameter(
- texture, GL_TEXTURE_MIN_FILTER, GL_CLAMP_TO_EDGE, GL_INVALID_ENUM);
+ texture_ref, GL_TEXTURE_MIN_FILTER, GL_CLAMP_TO_EDGE, GL_INVALID_ENUM);
EXPECT_EQ(static_cast<GLenum>(GL_NEAREST), texture->min_filter());
SetParameter(
- texture, GL_TEXTURE_MAG_FILTER, GL_CLAMP_TO_EDGE, GL_INVALID_ENUM);
+ texture_ref, GL_TEXTURE_MAG_FILTER, GL_CLAMP_TO_EDGE, GL_INVALID_ENUM);
EXPECT_EQ(static_cast<GLenum>(GL_NEAREST), texture->min_filter());
- SetParameter(texture, GL_TEXTURE_WRAP_S, GL_NEAREST, GL_INVALID_ENUM);
+ SetParameter(texture_ref, GL_TEXTURE_WRAP_S, GL_NEAREST, GL_INVALID_ENUM);
EXPECT_EQ(static_cast<GLenum>(GL_CLAMP_TO_EDGE), texture->wrap_s());
- SetParameter(texture, GL_TEXTURE_WRAP_T, GL_NEAREST, GL_INVALID_ENUM);
+ SetParameter(texture_ref, GL_TEXTURE_WRAP_T, GL_NEAREST, GL_INVALID_ENUM);
EXPECT_EQ(static_cast<GLenum>(GL_CLAMP_TO_EDGE), texture->wrap_t());
- SetParameter(texture, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0, GL_INVALID_VALUE);
+ SetParameter(texture_ref, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0, GL_INVALID_VALUE);
}
TEST_F(TextureManagerTest, TextureUsageExt) {
@@ -170,13 +172,13 @@
// Check we can create texture.
manager.CreateTexture(kClient1Id, kService1Id);
// Check texture got created.
- Texture* texture = manager.GetTexture(kClient1Id);
- ASSERT_TRUE(texture != NULL);
+ TextureRef* texture_ref = manager.GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref != NULL);
TestHelper::SetTexParameterWithExpectations(
- gl_.get(), error_state_.get(), &manager, texture,
+ gl_.get(), error_state_.get(), &manager, texture_ref,
GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE,GL_NO_ERROR);
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_ATTACHMENT_ANGLE),
- texture->usage());
+ texture_ref->texture()->usage());
manager.Destroy(false);
}
@@ -190,7 +192,7 @@
// Check we can create texture.
manager.CreateTexture(kClient1Id, kService1Id);
// Check texture got created.
- Texture* texture = manager.GetTexture(kClient1Id);
+ TextureRef* texture = manager.GetTexture(kClient1Id);
ASSERT_TRUE(texture != NULL);
EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService1Id)))
.Times(1)
@@ -210,12 +212,12 @@
NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
manager.Initialize();
// Check we can create texture.
- Texture* created_texture =
+ TextureRef* created_texture =
manager.CreateTexture(kClient1Id, kService1Id);
- created_texture->SetNotOwned();
+ created_texture->texture()->SetNotOwned();
// Check texture got created.
- Texture* texture = manager.GetTexture(kClient1Id);
+ TextureRef* texture = manager.GetTexture(kClient1Id);
ASSERT_TRUE(texture != NULL);
// Check that it is not freed if it is not owned.
@@ -365,7 +367,7 @@
: feature_info_(new FeatureInfo()) {
}
virtual ~TextureTestBase() {
- texture_ = NULL;
+ texture_ref_ = NULL;
}
protected:
@@ -385,23 +387,23 @@
decoder_.reset(new ::testing::StrictMock<gles2::MockGLES2Decoder>());
error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>());
manager_->CreateTexture(kClient1Id, kService1Id);
- texture_ = manager_->GetTexture(kClient1Id);
- ASSERT_TRUE(texture_.get() != NULL);
+ texture_ref_ = manager_->GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref_.get() != NULL);
}
virtual void TearDown() {
- if (texture_.get()) {
+ if (texture_ref_.get()) {
GLuint client_id = 0;
- // If it's not in the manager then setting texture_ to NULL will
+ // If it's not in the manager then setting texture_ref_ to NULL will
// delete the texture.
- if (!manager_->GetClientId(texture_->service_id(), &client_id)) {
+ if (!manager_->GetClientId(texture_ref_->service_id(), &client_id)) {
// Check that it gets deleted when the last reference is released.
EXPECT_CALL(*gl_,
- DeleteTextures(1, ::testing::Pointee(texture_->service_id())))
+ DeleteTextures(1, ::testing::Pointee(texture_ref_->service_id())))
.Times(1)
.RetiresOnSaturation();
}
- texture_ = NULL;
+ texture_ref_ = NULL;
}
manager_->Destroy(false);
manager_.reset();
@@ -410,10 +412,10 @@
}
void SetParameter(
- Texture* texture, GLenum pname, GLint value, GLenum error) {
+ TextureRef* texture_ref, GLenum pname, GLint value, GLenum error) {
TestHelper::SetTexParameterWithExpectations(
gl_.get(), error_state_.get(), manager_.get(),
- texture, pname, value, error);
+ texture_ref, pname, value, error);
}
scoped_ptr<MockGLES2Decoder> decoder_;
@@ -422,7 +424,7 @@
scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
scoped_refptr<FeatureInfo> feature_info_;
scoped_ptr<TextureManager> manager_;
- scoped_refptr<Texture> texture_;
+ scoped_refptr<TextureRef> texture_ref_;
};
class TextureTest : public TextureTestBase {
@@ -449,65 +451,81 @@
.RetiresOnSaturation() \
TEST_F(TextureTest, Basic) {
- EXPECT_EQ(0u, texture_->target());
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_EQ(0, texture_->num_uncleared_mips());
- EXPECT_FALSE(manager_->CanRender(texture_));
- EXPECT_TRUE(texture_->SafeToRenderFrom());
- EXPECT_FALSE(texture_->IsImmutable());
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(0u, texture->target());
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_EQ(0, texture->num_uncleared_mips());
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
+ EXPECT_TRUE(texture->SafeToRenderFrom());
+ EXPECT_FALSE(texture->IsImmutable());
EXPECT_EQ(static_cast<GLenum>(GL_NEAREST_MIPMAP_LINEAR),
- texture_->min_filter());
- EXPECT_EQ(static_cast<GLenum>(GL_LINEAR), texture_->mag_filter());
- EXPECT_EQ(static_cast<GLenum>(GL_REPEAT), texture_->wrap_s());
- EXPECT_EQ(static_cast<GLenum>(GL_REPEAT), texture_->wrap_t());
- EXPECT_TRUE(manager_->HaveUnrenderableTextures());
+ texture->min_filter());
+ EXPECT_EQ(static_cast<GLenum>(GL_LINEAR), texture->mag_filter());
+ EXPECT_EQ(static_cast<GLenum>(GL_REPEAT), texture->wrap_s());
+ EXPECT_EQ(static_cast<GLenum>(GL_REPEAT), texture->wrap_t());
+ EXPECT_FALSE(manager_->HaveUnrenderableTextures());
EXPECT_FALSE(manager_->HaveUnsafeTextures());
- EXPECT_EQ(0u, texture_->estimated_size());
+ EXPECT_EQ(0u, texture->estimated_size());
}
TEST_F(TextureTest, SetTargetTexture2D) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(manager_->CanRender(texture_));
- EXPECT_TRUE(texture_->SafeToRenderFrom());
- EXPECT_FALSE(texture_->IsImmutable());
+ Texture* texture = texture_ref_->texture();
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
+ EXPECT_TRUE(texture->SafeToRenderFrom());
+ EXPECT_FALSE(texture->IsImmutable());
}
TEST_F(TextureTest, SetTargetTextureExternalOES) {
- manager_->SetTarget(texture_, GL_TEXTURE_EXTERNAL_OES);
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_TRUE(manager_->CanRender(texture_));
- EXPECT_TRUE(texture_->SafeToRenderFrom());
- EXPECT_TRUE(texture_->IsImmutable());
+ Texture* texture = texture_ref_->texture();
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_EXTERNAL_OES);
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_));
+ EXPECT_TRUE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
+ EXPECT_TRUE(texture->SafeToRenderFrom());
+ EXPECT_TRUE(texture->IsImmutable());
+ manager_->SetStreamTexture(texture_ref_, true);
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
+}
+
+TEST_F(TextureTest, ZeroSizeCanNotRender) {
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
+ manager_->SetLevelInfo(texture_ref_,
+ GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
+ manager_->SetLevelInfo(texture_ref_,
+ GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
}
TEST_F(TextureTest, EstimatedSize) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- manager_->SetLevelInfo(texture_,
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_EQ(8u * 4u * 4u, texture_->estimated_size());
- manager_->SetLevelInfo(texture_,
+ EXPECT_EQ(8u * 4u * 4u, texture_ref_->texture()->estimated_size());
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 2, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_EQ(8u * 4u * 4u * 2u, texture_->estimated_size());
+ EXPECT_EQ(8u * 4u * 4u * 2u, texture_ref_->texture()->estimated_size());
}
TEST_F(TextureMemoryTrackerTest, EstimatedSize) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kUnmanaged);
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kUnmanaged);
EXPECT_MEMORY_ALLOCATION_CHANGE(0, 256, MemoryTracker::kUnmanaged);
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 2, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
// Add expectation for texture deletion.
EXPECT_MEMORY_ALLOCATION_CHANGE(256, 0, MemoryTracker::kUnmanaged);
@@ -515,14 +533,14 @@
}
TEST_F(TextureMemoryTrackerTest, SetParameterPool) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kUnmanaged);
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kUnmanaged);
EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kManaged);
SetParameter(
- texture_, GL_TEXTURE_POOL_CHROMIUM, GL_TEXTURE_POOL_MANAGED_CHROMIUM,
+ texture_ref_, GL_TEXTURE_POOL_CHROMIUM, GL_TEXTURE_POOL_MANAGED_CHROMIUM,
GL_NO_ERROR);
// Add expectation for texture deletion.
EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kManaged);
@@ -531,116 +549,119 @@
}
TEST_F(TextureTest, POT2D) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture_->target());
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
// Check Setting level 0 to POT
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_FALSE(manager_->CanRender(texture_));
- EXPECT_EQ(0, texture_->num_uncleared_mips());
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
+ EXPECT_EQ(0, texture->num_uncleared_mips());
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
// Set filters to something that will work with a single mip.
- SetParameter(texture_, GL_TEXTURE_MIN_FILTER, GL_LINEAR, GL_NO_ERROR);
- EXPECT_TRUE(manager_->CanRender(texture_));
+ SetParameter(texture_ref_, GL_TEXTURE_MIN_FILTER, GL_LINEAR, GL_NO_ERROR);
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
// Set them back.
- SetParameter(
- texture_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR, GL_NO_ERROR);
+ SetParameter(texture_ref_, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR, GL_NO_ERROR);
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
- EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
+ EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_));
// Make mips.
- EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_TRUE(manager_->CanRender(texture_));
+ EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_));
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
// Change a mip.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
- EXPECT_FALSE(manager_->CanRender(texture_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
// Set a level past the number of mips that would get generated.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 3, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
+ EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_));
// Make mips.
- EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
- EXPECT_TRUE(manager_->CanRender(texture_));
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture_));
+ EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_));
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
}
TEST_F(TextureMemoryTrackerTest, MarkMipmapsGenerated) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
EXPECT_MEMORY_ALLOCATION_CHANGE(0, 64, MemoryTracker::kUnmanaged);
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
EXPECT_MEMORY_ALLOCATION_CHANGE(64, 0, MemoryTracker::kUnmanaged);
EXPECT_MEMORY_ALLOCATION_CHANGE(0, 84, MemoryTracker::kUnmanaged);
- EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
+ EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_));
EXPECT_MEMORY_ALLOCATION_CHANGE(84, 0, MemoryTracker::kUnmanaged);
EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kUnmanaged);
}
TEST_F(TextureTest, UnusedMips) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture_->target());
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
// Set level zero to large size.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_TRUE(manager_->CanRender(texture_));
+ EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
// Set level zero to large smaller (levels unused mips)
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_TRUE(manager_->CanRender(texture_));
+ EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
// Set an unused level to some size
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 4, GL_RGBA, 16, 16, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_TRUE(manager_->CanRender(texture_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
}
TEST_F(TextureTest, NPOT2D) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture_->target());
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
// Check Setting level 0 to NPOT
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_TRUE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
- EXPECT_FALSE(manager_->CanRender(texture_));
+ EXPECT_TRUE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
- SetParameter(texture_, GL_TEXTURE_MIN_FILTER, GL_LINEAR, GL_NO_ERROR);
- EXPECT_FALSE(manager_->CanRender(texture_));
+ SetParameter(texture_ref_, GL_TEXTURE_MIN_FILTER, GL_LINEAR, GL_NO_ERROR);
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
- SetParameter(texture_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
- EXPECT_FALSE(manager_->CanRender(texture_));
+ SetParameter(texture_ref_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
- SetParameter(texture_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
- EXPECT_TRUE(manager_->CanRender(texture_));
+ SetParameter(texture_ref_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
// Change it to POT.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_));
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
}
@@ -652,190 +673,195 @@
TextureManager manager(
NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
manager.CreateTexture(kClient1Id, kService1Id);
- Texture* texture = manager.GetTexture(kClient1Id);
- ASSERT_TRUE(texture != NULL);
+ TextureRef* texture_ref = manager.GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
- manager.SetTarget(texture, GL_TEXTURE_2D);
+ manager.SetTarget(texture_ref, GL_TEXTURE_2D);
EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
// Check Setting level 0 to NPOT
- manager.SetLevelInfo(texture,
+ manager.SetLevelInfo(texture_ref,
GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
EXPECT_TRUE(TextureTestHelper::IsNPOT(texture));
EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
- EXPECT_TRUE(manager.CanGenerateMipmaps(texture));
- EXPECT_FALSE(manager.CanRender(texture));
+ EXPECT_TRUE(manager.CanGenerateMipmaps(texture_ref));
+ EXPECT_FALSE(manager.CanRender(texture_ref));
EXPECT_TRUE(manager.HaveUnrenderableTextures());
- EXPECT_TRUE(manager.MarkMipmapsGenerated(texture));
+ EXPECT_TRUE(manager.MarkMipmapsGenerated(texture_ref));
EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
- EXPECT_TRUE(manager.CanRender(texture));
+ EXPECT_TRUE(manager.CanRender(texture_ref));
EXPECT_FALSE(manager.HaveUnrenderableTextures());
manager.Destroy(false);
}
TEST_F(TextureTest, POTCubeMap) {
- manager_->SetTarget(texture_, GL_TEXTURE_CUBE_MAP);
- EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), texture_->target());
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_CUBE_MAP);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), texture->target());
// Check Setting level 0 each face to POT
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
- EXPECT_FALSE(manager_->CanRender(texture_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
- EXPECT_FALSE(manager_->CanRender(texture_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
- EXPECT_FALSE(manager_->CanRender(texture_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_FALSE(manager_->CanRender(texture_));
- EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
+ EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
- EXPECT_FALSE(manager_->CanRender(texture_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
- EXPECT_FALSE(manager_->CanRender(texture_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
// Make mips.
- EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_TRUE(manager_->CanRender(texture_));
+ EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_));
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_TRUE(manager_->CanRender(texture_ref_));
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
// Change a mip.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_FALSE(TextureTestHelper::IsNPOT(texture_));
- EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture_));
- EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture));
+ EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_));
// Set a level past the number of mips that would get generated.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
3, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
+ EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_));
// Make mips.
- EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture_));
- EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture_));
+ EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_));
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture));
}
TEST_F(TextureTest, GetLevelSize) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- manager_->SetLevelInfo(texture_,
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
GLsizei width = -1;
GLsizei height = -1;
- EXPECT_FALSE(texture_->GetLevelSize(GL_TEXTURE_2D, -1, &width, &height));
- EXPECT_FALSE(texture_->GetLevelSize(GL_TEXTURE_2D, 1000, &width, &height));
- EXPECT_FALSE(texture_->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height));
- EXPECT_TRUE(texture_->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height));
+ Texture* texture = texture_ref_->texture();
+ EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, -1, &width, &height));
+ EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 1000, &width, &height));
+ EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height));
+ EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height));
EXPECT_EQ(4, width);
EXPECT_EQ(5, height);
manager_->RemoveTexture(kClient1Id);
- EXPECT_TRUE(texture_->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height));
+ EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height));
EXPECT_EQ(4, width);
EXPECT_EQ(5, height);
}
TEST_F(TextureTest, GetLevelType) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- manager_->SetLevelInfo(texture_,
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
GLenum type = -1;
GLenum format = -1;
- EXPECT_FALSE(texture_->GetLevelType(GL_TEXTURE_2D, -1, &type, &format));
- EXPECT_FALSE(texture_->GetLevelType(GL_TEXTURE_2D, 1000, &type, &format));
- EXPECT_FALSE(texture_->GetLevelType(GL_TEXTURE_2D, 0, &type, &format));
- EXPECT_TRUE(texture_->GetLevelType(GL_TEXTURE_2D, 1, &type, &format));
+ Texture* texture = texture_ref_->texture();
+ EXPECT_FALSE(texture->GetLevelType(GL_TEXTURE_2D, -1, &type, &format));
+ EXPECT_FALSE(texture->GetLevelType(GL_TEXTURE_2D, 1000, &type, &format));
+ EXPECT_FALSE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &format));
+ EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &format));
EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type);
EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format);
manager_->RemoveTexture(kClient1Id);
- EXPECT_TRUE(texture_->GetLevelType(GL_TEXTURE_2D, 1, &type, &format));
+ EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &format));
EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type);
EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format);
}
TEST_F(TextureTest, ValidForTexture) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- manager_->SetLevelInfo(texture_,
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
// Check bad face.
- EXPECT_FALSE(texture_->ValidForTexture(
+ Texture* texture = texture_ref_->texture();
+ EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
// Check bad level.
- EXPECT_FALSE(texture_->ValidForTexture(
+ EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_2D, 0, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
// Check bad xoffset.
- EXPECT_FALSE(texture_->ValidForTexture(
+ EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, -1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
// Check bad xoffset + width > width.
- EXPECT_FALSE(texture_->ValidForTexture(
+ EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, 1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
// Check bad yoffset.
- EXPECT_FALSE(texture_->ValidForTexture(
+ EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, 0, -1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
// Check bad yoffset + height > height.
- EXPECT_FALSE(texture_->ValidForTexture(
+ EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, 0, 1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
// Check bad width.
- EXPECT_FALSE(texture_->ValidForTexture(
+ EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, 0, 0, 5, 5, GL_RGBA, GL_UNSIGNED_BYTE));
// Check bad height.
- EXPECT_FALSE(texture_->ValidForTexture(
+ EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, 0, 0, 4, 6, GL_RGBA, GL_UNSIGNED_BYTE));
// Check bad format.
- EXPECT_FALSE(texture_->ValidForTexture(
+ EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGB, GL_UNSIGNED_BYTE));
// Check bad type.
- EXPECT_FALSE(texture_->ValidForTexture(
+ EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4));
// Check valid full size
- EXPECT_TRUE(texture_->ValidForTexture(
+ EXPECT_TRUE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
// Check valid particial size.
- EXPECT_TRUE(texture_->ValidForTexture(
+ EXPECT_TRUE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, 1, 1, 2, 3, GL_RGBA, GL_UNSIGNED_BYTE));
manager_->RemoveTexture(kClient1Id);
- EXPECT_TRUE(texture_->ValidForTexture(
+ EXPECT_TRUE(texture->ValidForTexture(
GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
}
@@ -847,20 +873,21 @@
TextureManager manager(
NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
manager.CreateTexture(kClient1Id, kService1Id);
- Texture* texture = manager.GetTexture(kClient1Id);
- ASSERT_TRUE(texture != NULL);
- manager.SetTarget(texture, GL_TEXTURE_2D);
+ TextureRef* texture_ref = manager.GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref != NULL);
+ manager.SetTarget(texture_ref, GL_TEXTURE_2D);
+ Texture* texture = texture_ref->texture();
EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
- manager.SetLevelInfo(texture,
+ manager.SetLevelInfo(texture_ref,
GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, true);
EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
TestHelper::SetTexParameterWithExpectations(
gl_.get(), error_state_.get(), &manager,
- texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
+ texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
TestHelper::SetTexParameterWithExpectations(
- gl_.get(), error_state_.get(), &manager,
- texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR);
+ gl_.get(), error_state_.get(), &manager, texture_ref,
+ GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR);
EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
manager.Destroy(false);
}
@@ -873,11 +900,12 @@
TextureManager manager(
NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
manager.CreateTexture(kClient1Id, kService1Id);
- Texture* texture = manager.GetTexture(kClient1Id);
- ASSERT_TRUE(texture != NULL);
- manager.SetTarget(texture, GL_TEXTURE_2D);
+ TextureRef* texture_ref = manager.GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref != NULL);
+ manager.SetTarget(texture_ref, GL_TEXTURE_2D);
+ Texture* texture = texture_ref->texture();
EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
- manager.SetLevelInfo(texture,
+ manager.SetLevelInfo(texture_ref,
GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, true);
EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
manager.Destroy(false);
@@ -891,20 +919,21 @@
TextureManager manager(
NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
manager.CreateTexture(kClient1Id, kService1Id);
- Texture* texture = manager.GetTexture(kClient1Id);
- ASSERT_TRUE(texture != NULL);
- manager.SetTarget(texture, GL_TEXTURE_2D);
+ TextureRef* texture_ref = manager.GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref != NULL);
+ manager.SetTarget(texture_ref, GL_TEXTURE_2D);
+ Texture* texture = texture_ref->texture();
EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
- manager.SetLevelInfo(texture,
+ manager.SetLevelInfo(texture_ref,
GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES, true);
EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
TestHelper::SetTexParameterWithExpectations(
gl_.get(), error_state_.get(), &manager,
- texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
+ texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
TestHelper::SetTexParameterWithExpectations(
- gl_.get(), error_state_.get(), &manager,
- texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR);
+ gl_.get(), error_state_.get(), &manager, texture_ref,
+ GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR);
EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
manager.Destroy(false);
}
@@ -917,11 +946,12 @@
TextureManager manager(
NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
manager.CreateTexture(kClient1Id, kService1Id);
- Texture* texture = manager.GetTexture(kClient1Id);
- ASSERT_TRUE(texture != NULL);
- manager.SetTarget(texture, GL_TEXTURE_2D);
+ TextureRef* texture_ref = manager.GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref != NULL);
+ manager.SetTarget(texture_ref, GL_TEXTURE_2D);
+ Texture* texture = texture_ref->texture();
EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
- manager.SetLevelInfo(texture,
+ manager.SetLevelInfo(texture_ref,
GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES, true);
EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
manager.Destroy(false);
@@ -935,11 +965,12 @@
TextureManager manager(
NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
manager.CreateTexture(kClient1Id, kService1Id);
- Texture* texture = manager.GetTexture(kClient1Id);
- ASSERT_TRUE(texture != NULL);
- manager.SetTarget(texture, GL_TEXTURE_EXTERNAL_OES);
+ TextureRef* texture_ref = manager.GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref != NULL);
+ manager.SetTarget(texture_ref, GL_TEXTURE_EXTERNAL_OES);
+ Texture* texture = texture_ref->texture();
EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), texture->target());
- EXPECT_FALSE(manager.CanGenerateMipmaps(texture));
+ EXPECT_FALSE(manager.CanGenerateMipmaps(texture_ref));
manager.Destroy(false);
}
@@ -951,13 +982,13 @@
TextureManager manager(
NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
manager.CreateTexture(kClient1Id, kService1Id);
- Texture* texture = manager.GetTexture(kClient1Id);
- ASSERT_TRUE(texture != NULL);
- manager.SetTarget(texture, GL_TEXTURE_2D);
+ TextureRef* texture_ref = manager.GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref != NULL);
+ manager.SetTarget(texture_ref, GL_TEXTURE_2D);
manager.SetLevelInfo(
- texture, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 4, 4, 1, 0,
+ texture_ref, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 4, 4, 1, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false);
- EXPECT_FALSE(manager.CanGenerateMipmaps(texture));
+ EXPECT_FALSE(manager.CanGenerateMipmaps(texture_ref));
manager.Destroy(false);
}
@@ -967,101 +998,104 @@
static const GLuint kClient3Id = 3;
static const GLuint kService3Id = 13;
EXPECT_FALSE(manager_->HaveUnclearedMips());
- EXPECT_EQ(0, texture_->num_uncleared_mips());
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- manager_->SetLevelInfo(texture_,
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(0, texture->num_uncleared_mips());
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- EXPECT_FALSE(texture_->SafeToRenderFrom());
+ EXPECT_FALSE(texture->SafeToRenderFrom());
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
- EXPECT_EQ(1, texture_->num_uncleared_mips());
- manager_->SetLevelCleared(texture_, GL_TEXTURE_2D, 0, true);
- EXPECT_TRUE(texture_->SafeToRenderFrom());
+ EXPECT_EQ(1, texture->num_uncleared_mips());
+ manager_->SetLevelCleared(texture_ref_, GL_TEXTURE_2D, 0, true);
+ EXPECT_TRUE(texture->SafeToRenderFrom());
EXPECT_FALSE(manager_->HaveUnsafeTextures());
EXPECT_FALSE(manager_->HaveUnclearedMips());
- EXPECT_EQ(0, texture_->num_uncleared_mips());
- manager_->SetLevelInfo(texture_,
+ EXPECT_EQ(0, texture->num_uncleared_mips());
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- EXPECT_FALSE(texture_->SafeToRenderFrom());
+ EXPECT_FALSE(texture->SafeToRenderFrom());
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
- EXPECT_EQ(1, texture_->num_uncleared_mips());
- manager_->SetLevelCleared(texture_, GL_TEXTURE_2D, 1, true);
- EXPECT_TRUE(texture_->SafeToRenderFrom());
+ EXPECT_EQ(1, texture->num_uncleared_mips());
+ manager_->SetLevelCleared(texture_ref_, GL_TEXTURE_2D, 1, true);
+ EXPECT_TRUE(texture->SafeToRenderFrom());
EXPECT_FALSE(manager_->HaveUnsafeTextures());
EXPECT_FALSE(manager_->HaveUnclearedMips());
- EXPECT_EQ(0, texture_->num_uncleared_mips());
- manager_->SetLevelInfo(texture_,
+ EXPECT_EQ(0, texture->num_uncleared_mips());
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- EXPECT_FALSE(texture_->SafeToRenderFrom());
+ EXPECT_FALSE(texture->SafeToRenderFrom());
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
- EXPECT_EQ(2, texture_->num_uncleared_mips());
- manager_->SetLevelCleared(texture_, GL_TEXTURE_2D, 0, true);
- EXPECT_FALSE(texture_->SafeToRenderFrom());
+ EXPECT_EQ(2, texture->num_uncleared_mips());
+ manager_->SetLevelCleared(texture_ref_, GL_TEXTURE_2D, 0, true);
+ EXPECT_FALSE(texture->SafeToRenderFrom());
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
- EXPECT_EQ(1, texture_->num_uncleared_mips());
- manager_->SetLevelCleared(texture_, GL_TEXTURE_2D, 1, true);
- EXPECT_TRUE(texture_->SafeToRenderFrom());
+ EXPECT_EQ(1, texture->num_uncleared_mips());
+ manager_->SetLevelCleared(texture_ref_, GL_TEXTURE_2D, 1, true);
+ EXPECT_TRUE(texture->SafeToRenderFrom());
EXPECT_FALSE(manager_->HaveUnsafeTextures());
EXPECT_FALSE(manager_->HaveUnclearedMips());
- EXPECT_EQ(0, texture_->num_uncleared_mips());
- manager_->SetLevelInfo(texture_,
+ EXPECT_EQ(0, texture->num_uncleared_mips());
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- EXPECT_FALSE(texture_->SafeToRenderFrom());
+ EXPECT_FALSE(texture->SafeToRenderFrom());
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
- EXPECT_EQ(1, texture_->num_uncleared_mips());
- manager_->MarkMipmapsGenerated(texture_);
- EXPECT_TRUE(texture_->SafeToRenderFrom());
+ EXPECT_EQ(1, texture->num_uncleared_mips());
+ manager_->MarkMipmapsGenerated(texture_ref_);
+ EXPECT_TRUE(texture->SafeToRenderFrom());
EXPECT_FALSE(manager_->HaveUnsafeTextures());
EXPECT_FALSE(manager_->HaveUnclearedMips());
- EXPECT_EQ(0, texture_->num_uncleared_mips());
+ EXPECT_EQ(0, texture->num_uncleared_mips());
manager_->CreateTexture(kClient2Id, kService2Id);
- scoped_refptr<Texture> texture2(
+ scoped_refptr<TextureRef> texture_ref2(
manager_->GetTexture(kClient2Id));
- ASSERT_TRUE(texture2.get() != NULL);
- manager_->SetTarget(texture2, GL_TEXTURE_2D);
+ ASSERT_TRUE(texture_ref2.get() != NULL);
+ manager_->SetTarget(texture_ref2, GL_TEXTURE_2D);
EXPECT_FALSE(manager_->HaveUnsafeTextures());
EXPECT_FALSE(manager_->HaveUnclearedMips());
+ Texture* texture2 = texture_ref2->texture();
EXPECT_EQ(0, texture2->num_uncleared_mips());
- manager_->SetLevelInfo(texture2,
+ manager_->SetLevelInfo(texture_ref2,
GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
EXPECT_FALSE(manager_->HaveUnsafeTextures());
EXPECT_FALSE(manager_->HaveUnclearedMips());
EXPECT_EQ(0, texture2->num_uncleared_mips());
- manager_->SetLevelInfo(texture2,
+ manager_->SetLevelInfo(texture_ref2,
GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
EXPECT_EQ(1, texture2->num_uncleared_mips());
manager_->CreateTexture(kClient3Id, kService3Id);
- scoped_refptr<Texture> texture3(
+ scoped_refptr<TextureRef> texture_ref3(
manager_->GetTexture(kClient3Id));
- ASSERT_TRUE(texture3.get() != NULL);
- manager_->SetTarget(texture3, GL_TEXTURE_2D);
- manager_->SetLevelInfo(texture3,
+ ASSERT_TRUE(texture_ref3.get() != NULL);
+ manager_->SetTarget(texture_ref3, GL_TEXTURE_2D);
+ manager_->SetLevelInfo(texture_ref3,
GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
+ Texture* texture3 = texture_ref3->texture();
EXPECT_EQ(1, texture3->num_uncleared_mips());
- manager_->SetLevelCleared(texture2, GL_TEXTURE_2D, 0, true);
+ manager_->SetLevelCleared(texture_ref2, GL_TEXTURE_2D, 0, true);
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
EXPECT_EQ(0, texture2->num_uncleared_mips());
- manager_->SetLevelCleared(texture3, GL_TEXTURE_2D, 0, true);
+ manager_->SetLevelCleared(texture_ref3, GL_TEXTURE_2D, 0, true);
EXPECT_FALSE(manager_->HaveUnsafeTextures());
EXPECT_FALSE(manager_->HaveUnclearedMips());
EXPECT_EQ(0, texture3->num_uncleared_mips());
- manager_->SetLevelInfo(texture2,
+ manager_->SetLevelInfo(texture_ref2,
GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- manager_->SetLevelInfo(texture3,
+ manager_->SetLevelInfo(texture_ref3,
GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
@@ -1076,13 +1110,13 @@
EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService2Id)))
.Times(1)
.RetiresOnSaturation();
- texture2 = NULL;
+ texture_ref2 = NULL;
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService3Id)))
.Times(1)
.RetiresOnSaturation();
- texture3 = NULL;
+ texture_ref3 = NULL;
EXPECT_FALSE(manager_->HaveUnsafeTextures());
EXPECT_FALSE(manager_->HaveUnclearedMips());
}
@@ -1090,88 +1124,90 @@
TEST_F(TextureTest, ClearTexture) {
EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _))
.WillRepeatedly(Return(true));
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- manager_->SetLevelInfo(texture_,
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- EXPECT_FALSE(texture_->SafeToRenderFrom());
+ Texture* texture = texture_ref_->texture();
+ EXPECT_FALSE(texture->SafeToRenderFrom());
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
- EXPECT_EQ(2, texture_->num_uncleared_mips());
- manager_->ClearRenderableLevels(decoder_.get(), texture_);
- EXPECT_TRUE(texture_->SafeToRenderFrom());
+ EXPECT_EQ(2, texture->num_uncleared_mips());
+ manager_->ClearRenderableLevels(decoder_.get(), texture_ref_);
+ EXPECT_TRUE(texture->SafeToRenderFrom());
EXPECT_FALSE(manager_->HaveUnsafeTextures());
EXPECT_FALSE(manager_->HaveUnclearedMips());
- EXPECT_EQ(0, texture_->num_uncleared_mips());
- manager_->SetLevelInfo(texture_,
+ EXPECT_EQ(0, texture->num_uncleared_mips());
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- EXPECT_FALSE(texture_->SafeToRenderFrom());
+ EXPECT_FALSE(texture->SafeToRenderFrom());
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
- EXPECT_EQ(2, texture_->num_uncleared_mips());
- manager_->ClearTextureLevel(decoder_.get(), texture_, GL_TEXTURE_2D, 0);
- EXPECT_FALSE(texture_->SafeToRenderFrom());
+ EXPECT_EQ(2, texture->num_uncleared_mips());
+ manager_->ClearTextureLevel(decoder_.get(), texture_ref_, GL_TEXTURE_2D, 0);
+ EXPECT_FALSE(texture->SafeToRenderFrom());
EXPECT_TRUE(manager_->HaveUnsafeTextures());
EXPECT_TRUE(manager_->HaveUnclearedMips());
- EXPECT_EQ(1, texture_->num_uncleared_mips());
- manager_->ClearTextureLevel(decoder_.get(), texture_, GL_TEXTURE_2D, 1);
- EXPECT_TRUE(texture_->SafeToRenderFrom());
+ EXPECT_EQ(1, texture->num_uncleared_mips());
+ manager_->ClearTextureLevel(decoder_.get(), texture_ref_, GL_TEXTURE_2D, 1);
+ EXPECT_TRUE(texture->SafeToRenderFrom());
EXPECT_FALSE(manager_->HaveUnsafeTextures());
EXPECT_FALSE(manager_->HaveUnclearedMips());
- EXPECT_EQ(0, texture_->num_uncleared_mips());
+ EXPECT_EQ(0, texture->num_uncleared_mips());
}
TEST_F(TextureTest, UseDeletedTexture) {
static const GLuint kClient2Id = 2;
static const GLuint kService2Id = 12;
// Make the default texture renderable
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- manager_->SetLevelInfo(texture_,
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
// Make a new texture
manager_->CreateTexture(kClient2Id, kService2Id);
- scoped_refptr<Texture> texture(
+ scoped_refptr<TextureRef> texture_ref(
manager_->GetTexture(kClient2Id));
- manager_->SetTarget(texture, GL_TEXTURE_2D);
- EXPECT_FALSE(manager_->CanRender(texture));
+ manager_->SetTarget(texture_ref, GL_TEXTURE_2D);
+ EXPECT_FALSE(manager_->CanRender(texture_ref));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
// Remove it.
manager_->RemoveTexture(kClient2Id);
- EXPECT_FALSE(manager_->CanRender(texture));
+ EXPECT_FALSE(manager_->CanRender(texture_ref));
EXPECT_TRUE(manager_->HaveUnrenderableTextures());
// Check that we can still manipulate it and it effects the manager.
- manager_->SetLevelInfo(texture,
+ manager_->SetLevelInfo(texture_ref,
GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
- EXPECT_TRUE(manager_->CanRender(texture));
+ EXPECT_TRUE(manager_->CanRender(texture_ref));
EXPECT_FALSE(manager_->HaveUnrenderableTextures());
EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService2Id)))
.Times(1)
.RetiresOnSaturation();
- texture = NULL;
+ texture_ref = NULL;
}
TEST_F(TextureTest, GetLevelImage) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- manager_->SetLevelInfo(texture_,
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_TRUE(texture_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
// Set image.
- manager_->SetLevelImage(texture_,
+ manager_->SetLevelImage(texture_ref_,
GL_TEXTURE_2D, 1, gfx::GLImage::CreateGLImage(0));
- EXPECT_FALSE(texture_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
+ EXPECT_FALSE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
// Remove it.
- manager_->SetLevelImage(texture_, GL_TEXTURE_2D, 1, NULL);
- EXPECT_TRUE(texture_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
- manager_->SetLevelImage(texture_,
+ manager_->SetLevelImage(texture_ref_, GL_TEXTURE_2D, 1, NULL);
+ EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
+ manager_->SetLevelImage(texture_ref_,
GL_TEXTURE_2D, 1, gfx::GLImage::CreateGLImage(0));
// Image should be reset when SetLevelInfo is called.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- EXPECT_TRUE(texture_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
+ EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
}
namespace {
@@ -1185,105 +1221,105 @@
} // anonymous namespace
TEST_F(TextureTest, AddToSignature) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- manager_->SetLevelInfo(texture_,
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
std::string signature1;
std::string signature2;
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature1);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature1);
std::set<std::string> string_set;
EXPECT_FALSE(InSet(&string_set, signature1));
// check changing 1 thing makes a different signature.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 4, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_FALSE(InSet(&string_set, signature2));
// check putting it back makes the same signature.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_EQ(signature1, signature2);
// Check setting cleared status does not change signature.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_EQ(signature1, signature2);
// Check changing other settings changes signature.
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_FALSE(InSet(&string_set, signature2));
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_FALSE(InSet(&string_set, signature2));
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, false);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_FALSE(InSet(&string_set, signature2));
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, false);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_FALSE(InSet(&string_set, signature2));
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_FLOAT,
false);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_FALSE(InSet(&string_set, signature2));
// put it back
- manager_->SetLevelInfo(texture_,
+ manager_->SetLevelInfo(texture_ref_,
GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
false);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_EQ(signature1, signature2);
// check changing parameters changes signature.
- SetParameter(texture_, GL_TEXTURE_MIN_FILTER, GL_NEAREST, GL_NO_ERROR);
+ SetParameter(texture_ref_, GL_TEXTURE_MIN_FILTER, GL_NEAREST, GL_NO_ERROR);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_FALSE(InSet(&string_set, signature2));
- SetParameter(
- texture_, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR, GL_NO_ERROR);
- SetParameter(texture_, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
+ SetParameter(texture_ref_, GL_TEXTURE_MIN_FILTER,
+ GL_NEAREST_MIPMAP_LINEAR, GL_NO_ERROR);
+ SetParameter(texture_ref_, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_FALSE(InSet(&string_set, signature2));
- SetParameter(texture_, GL_TEXTURE_MAG_FILTER, GL_LINEAR, GL_NO_ERROR);
- SetParameter(texture_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
+ SetParameter(texture_ref_, GL_TEXTURE_MAG_FILTER, GL_LINEAR, GL_NO_ERROR);
+ SetParameter(texture_ref_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_FALSE(InSet(&string_set, signature2));
- SetParameter(texture_, GL_TEXTURE_WRAP_S, GL_REPEAT, GL_NO_ERROR);
- SetParameter(texture_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
+ SetParameter(texture_ref_, GL_TEXTURE_WRAP_S, GL_REPEAT, GL_NO_ERROR);
+ SetParameter(texture_ref_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_FALSE(InSet(&string_set, signature2));
// Check putting it back genenerates the same signature
- SetParameter(texture_, GL_TEXTURE_WRAP_T, GL_REPEAT, GL_NO_ERROR);
+ SetParameter(texture_ref_, GL_TEXTURE_WRAP_T, GL_REPEAT, GL_NO_ERROR);
signature2.clear();
- manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
+ manager_->AddToSignature(texture_ref_, GL_TEXTURE_2D, 1, &signature2);
EXPECT_EQ(signature1, signature2);
// Check the set was acutally getting different signatures.
@@ -1364,8 +1400,10 @@
bool cleared;
};
- void SetLevelInfo(Texture* texture, GLint level, const LevelInfo& info) {
- manager_->SetLevelInfo(texture,
+ void SetLevelInfo(TextureRef* texture_ref,
+ GLint level,
+ const LevelInfo& info) {
+ manager_->SetLevelInfo(texture_ref,
info.target,
level,
info.format,
@@ -1378,9 +1416,10 @@
info.cleared);
}
- static LevelInfo GetLevelInfo(const Texture* texture,
+ static LevelInfo GetLevelInfo(const TextureRef* texture_ref,
GLint target,
GLint level) {
+ const Texture* texture = texture_ref->texture();
LevelInfo info;
info.target = target;
EXPECT_TRUE(texture->GetLevelSize(target, level, &info.width,
@@ -1391,27 +1430,27 @@
return info;
}
- TextureDefinition* Save(Texture* texture) {
+ TextureDefinition* Save(TextureRef* texture_ref) {
EXPECT_CALL(*gl_, GenTextures(_, _))
.WillOnce(SetArgumentPointee<1>(kEmptyTextureServiceId));
- TextureDefinition* definition = manager_->Save(texture);
+ TextureDefinition* definition = manager_->Save(texture_ref);
EXPECT_TRUE(definition != NULL);
return definition;
}
- void Restore(Texture* texture, TextureDefinition* definition) {
- EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(texture->service_id())))
+ void Restore(TextureRef* texture_ref, TextureDefinition* definition) {
+ EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(texture_ref->service_id())))
.Times(1).RetiresOnSaturation();
EXPECT_CALL(*gl_,
BindTexture(definition->target(), definition->service_id()))
.Times(1).RetiresOnSaturation();
EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(AtLeast(1));
- EXPECT_TRUE(
- manager_->Restore("TextureTest", decoder_.get(), texture, definition));
+ EXPECT_TRUE(manager_->Restore("TextureTest", decoder_.get(),
+ texture_ref, definition));
}
- scoped_refptr<Texture> texture2_;
+ scoped_refptr<TextureRef> texture2_;
private:
static const GLuint kEmptyTextureServiceId;
@@ -1424,16 +1463,17 @@
const GLuint SaveRestoreTextureTest::kEmptyTextureServiceId = 13;
TEST_F(SaveRestoreTextureTest, SaveRestore2D) {
- manager_->SetTarget(texture_, GL_TEXTURE_2D);
- EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture_->target());
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_2D);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
LevelInfo level0(
GL_TEXTURE_2D, GL_RGBA, 4, 4, 1, 0, GL_UNSIGNED_BYTE, true);
- SetLevelInfo(texture_, 0, level0);
- EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture_));
- LevelInfo level1 = GetLevelInfo(texture_.get(), GL_TEXTURE_2D, 1);
- LevelInfo level2 = GetLevelInfo(texture_.get(), GL_TEXTURE_2D, 2);
- scoped_ptr<TextureDefinition> definition(Save(texture_));
+ SetLevelInfo(texture_ref_, 0, level0);
+ EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_));
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ LevelInfo level1 = GetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1);
+ LevelInfo level2 = GetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 2);
+ scoped_ptr<TextureDefinition> definition(Save(texture_ref_));
const TextureDefinition::LevelInfos& infos = definition->level_infos();
EXPECT_EQ(1U, infos.size());
EXPECT_EQ(3U, infos[0].size());
@@ -1446,27 +1486,29 @@
0,
LevelInfo(GL_TEXTURE_2D, GL_RGBA, 16, 16, 1, 0, GL_UNSIGNED_BYTE, false));
EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture2_));
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture2_));
- EXPECT_EQ(1024U + 256U + 64U + 16U + 4U, texture2_->estimated_size());
+ texture = texture2_->texture();
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_EQ(1024U + 256U + 64U + 16U + 4U, texture->estimated_size());
Restore(texture2_, definition.release());
EXPECT_EQ(level0, GetLevelInfo(texture2_.get(), GL_TEXTURE_2D, 0));
EXPECT_EQ(level1, GetLevelInfo(texture2_.get(), GL_TEXTURE_2D, 1));
EXPECT_EQ(level2, GetLevelInfo(texture2_.get(), GL_TEXTURE_2D, 2));
- EXPECT_EQ(64U + 16U + 4U, texture2_->estimated_size());
+ EXPECT_EQ(64U + 16U + 4U, texture->estimated_size());
GLint w, h;
- EXPECT_TRUE(texture2_->GetLevelSize(GL_TEXTURE_2D, 3, &w, &h));
+ EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 3, &w, &h));
EXPECT_EQ(0, w);
EXPECT_EQ(0, h);
}
TEST_F(SaveRestoreTextureTest, SaveRestoreClearRectangle) {
- manager_->SetTarget(texture_, GL_TEXTURE_RECTANGLE_ARB);
- EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_RECTANGLE_ARB), texture_->target());
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_RECTANGLE_ARB);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_RECTANGLE_ARB), texture->target());
LevelInfo level0(
GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, 1, 1, 1, 0, GL_UNSIGNED_BYTE, false);
- SetLevelInfo(texture_, 0, level0);
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture_));
- scoped_ptr<TextureDefinition> definition(Save(texture_));
+ SetLevelInfo(texture_ref_, 0, level0);
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ scoped_ptr<TextureDefinition> definition(Save(texture_ref_));
const TextureDefinition::LevelInfos& infos = definition->level_infos();
EXPECT_EQ(1U, infos.size());
EXPECT_EQ(1U, infos[0].size());
@@ -1483,22 +1525,24 @@
}
TEST_F(SaveRestoreTextureTest, SaveRestoreStreamTexture) {
- manager_->SetTarget(texture_, GL_TEXTURE_EXTERNAL_OES);
- EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), texture_->target());
- texture_->SetStreamTexture(true);
- GLuint service_id = texture_->service_id();
- scoped_ptr<TextureDefinition> definition(Save(texture_));
- EXPECT_FALSE(texture_->IsStreamTexture());
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_EXTERNAL_OES);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), texture->target());
+ manager_->SetStreamTexture(texture_ref_, true);
+ GLuint service_id = texture->service_id();
+ scoped_ptr<TextureDefinition> definition(Save(texture_ref_));
+ EXPECT_FALSE(texture->IsStreamTexture());
manager_->SetTarget(texture2_, GL_TEXTURE_EXTERNAL_OES);
Restore(texture2_, definition.release());
- EXPECT_TRUE(texture2_->IsStreamTexture());
- EXPECT_TRUE(texture2_->IsImmutable());
+ EXPECT_TRUE(texture2_->texture()->IsStreamTexture());
+ EXPECT_TRUE(texture2_->texture()->IsImmutable());
EXPECT_EQ(service_id, texture2_->service_id());
}
TEST_F(SaveRestoreTextureTest, SaveRestoreCube) {
- manager_->SetTarget(texture_, GL_TEXTURE_CUBE_MAP);
- EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), texture_->target());
+ manager_->SetTarget(texture_ref_, GL_TEXTURE_CUBE_MAP);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), texture->target());
LevelInfo face0(GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_RGBA,
1,
@@ -1515,10 +1559,10 @@
0,
GL_UNSIGNED_BYTE,
true);
- SetLevelInfo(texture_, 0, face0);
- SetLevelInfo(texture_, 0, face5);
- EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture_));
- scoped_ptr<TextureDefinition> definition(Save(texture_));
+ SetLevelInfo(texture_ref_, 0, face0);
+ SetLevelInfo(texture_ref_, 0, face5);
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ scoped_ptr<TextureDefinition> definition(Save(texture_ref_));
const TextureDefinition::LevelInfos& infos = definition->level_infos();
EXPECT_EQ(6U, infos.size());
EXPECT_EQ(1U, infos[0].size());
@@ -1530,7 +1574,250 @@
GetLevelInfo(texture2_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0));
}
+class CountingMemoryTracker : public MemoryTracker {
+ public:
+ CountingMemoryTracker() {
+ current_size_[0] = 0;
+ current_size_[1] = 0;
+ }
+
+ virtual void TrackMemoryAllocatedChange(size_t old_size,
+ size_t new_size,
+ Pool pool) OVERRIDE {
+ DCHECK_LT(static_cast<size_t>(pool), arraysize(current_size_));
+ current_size_[pool] += new_size - old_size;
+ }
+
+ virtual bool EnsureGPUMemoryAvailable(size_t size_needed) OVERRIDE {
+ return true;
+ }
+
+ size_t GetSize(Pool pool) {
+ DCHECK_LT(static_cast<size_t>(pool), arraysize(current_size_));
+ return current_size_[pool];
+ }
+
+ private:
+ virtual ~CountingMemoryTracker() {}
+
+ size_t current_size_[2];
+ DISALLOW_COPY_AND_ASSIGN(CountingMemoryTracker);
+};
+
+class SharedTextureTest : public testing::Test {
+ public:
+ SharedTextureTest()
+ : feature_info_(new FeatureInfo()) {
+ }
+
+ virtual ~SharedTextureTest() {
+ }
+
+ virtual void SetUp() {
+ gl_.reset(new ::gfx::MockGLInterface());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
+
+ memory_tracker1_ = new CountingMemoryTracker;
+ texture_manager1_.reset(new TextureManager(
+ memory_tracker1_, feature_info_.get(),
+ TextureManagerTest::kMaxTextureSize,
+ TextureManagerTest::kMaxCubeMapTextureSize));
+ memory_tracker2_ = new CountingMemoryTracker;
+ texture_manager2_.reset(new TextureManager(
+ memory_tracker2_, feature_info_.get(),
+ TextureManagerTest::kMaxTextureSize,
+ TextureManagerTest::kMaxCubeMapTextureSize));
+ TestHelper::SetupTextureManagerInitExpectations(gl_.get(), "");
+ texture_manager1_->Initialize();
+ TestHelper::SetupTextureManagerInitExpectations(gl_.get(), "");
+ texture_manager2_->Initialize();
+ }
+
+ virtual void TearDown() {
+ texture_manager2_->Destroy(false);
+ texture_manager2_.reset();
+ texture_manager1_->Destroy(false);
+ texture_manager1_.reset();
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
+ }
+
+ protected:
+ scoped_ptr< ::gfx::MockGLInterface > gl_;
+ scoped_refptr<FeatureInfo> feature_info_;
+ scoped_refptr<CountingMemoryTracker> memory_tracker1_;
+ scoped_ptr<TextureManager> texture_manager1_;
+ scoped_refptr<CountingMemoryTracker> memory_tracker2_;
+ scoped_ptr<TextureManager> texture_manager2_;
+};
+
+TEST_F(SharedTextureTest, DeleteTextures) {
+ scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10);
+ scoped_refptr<TextureRef> ref2 = new TextureRef(texture_manager2_.get(),
+ ref1->texture());
+ EXPECT_CALL(*gl_, DeleteTextures(1, _))
+ .Times(0);
+ ref1 = NULL;
+ texture_manager1_->RemoveTexture(10);
+ testing::Mock::VerifyAndClearExpectations(gl_.get());
+
+ EXPECT_CALL(*gl_, DeleteTextures(1, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ ref2 = NULL;
+ testing::Mock::VerifyAndClearExpectations(gl_.get());
+}
+
+TEST_F(SharedTextureTest, TextureSafetyAccounting) {
+ EXPECT_FALSE(texture_manager1_->HaveUnrenderableTextures());
+ EXPECT_FALSE(texture_manager1_->HaveUnsafeTextures());
+ EXPECT_FALSE(texture_manager1_->HaveUnclearedMips());
+ EXPECT_FALSE(texture_manager2_->HaveUnrenderableTextures());
+ EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures());
+ EXPECT_FALSE(texture_manager2_->HaveUnclearedMips());
+
+ // Newly created texture is unrenderable.
+ scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10);
+ EXPECT_FALSE(texture_manager1_->HaveUnrenderableTextures());
+ EXPECT_FALSE(texture_manager1_->HaveUnsafeTextures());
+ EXPECT_FALSE(texture_manager1_->HaveUnclearedMips());
+
+ // Associate new texture ref to other texture manager, should account for it
+ // too.
+ scoped_refptr<TextureRef> ref2 = new TextureRef(texture_manager2_.get(),
+ ref1->texture());
+ EXPECT_FALSE(texture_manager2_->HaveUnrenderableTextures());
+ EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures());
+ EXPECT_FALSE(texture_manager2_->HaveUnclearedMips());
+
+ // Make texture renderable but uncleared on one texture manager, should affect
+ // other one.
+ texture_manager1_->SetTarget(ref1, GL_TEXTURE_2D);
+ EXPECT_TRUE(texture_manager1_->HaveUnrenderableTextures());
+ EXPECT_FALSE(texture_manager1_->HaveUnsafeTextures());
+ EXPECT_FALSE(texture_manager1_->HaveUnclearedMips());
+ EXPECT_TRUE(texture_manager2_->HaveUnrenderableTextures());
+ EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures());
+ EXPECT_FALSE(texture_manager2_->HaveUnclearedMips());
+
+ texture_manager1_->SetLevelInfo(ref1, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, false);
+ EXPECT_FALSE(texture_manager1_->HaveUnrenderableTextures());
+ EXPECT_TRUE(texture_manager1_->HaveUnsafeTextures());
+ EXPECT_TRUE(texture_manager1_->HaveUnclearedMips());
+ EXPECT_FALSE(texture_manager2_->HaveUnrenderableTextures());
+ EXPECT_TRUE(texture_manager2_->HaveUnsafeTextures());
+ EXPECT_TRUE(texture_manager2_->HaveUnclearedMips());
+
+ // Make texture cleared on one texture manager, should affect other one.
+ texture_manager1_->SetLevelCleared(ref1, GL_TEXTURE_2D, 0, true);
+ EXPECT_FALSE(texture_manager1_->HaveUnsafeTextures());
+ EXPECT_FALSE(texture_manager1_->HaveUnclearedMips());
+ EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures());
+ EXPECT_FALSE(texture_manager2_->HaveUnclearedMips());
+
+ EXPECT_CALL(*gl_, DeleteTextures(1, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ texture_manager1_->RemoveTexture(10);
+}
+
+TEST_F(SharedTextureTest, FBOCompletenessCheck) {
+ const GLenum kCompleteValue = GL_FRAMEBUFFER_COMPLETE;
+ FramebufferManager framebuffer_manager1(1, 1);
+ texture_manager1_->set_framebuffer_manager(&framebuffer_manager1);
+ FramebufferManager framebuffer_manager2(1, 1);
+ texture_manager2_->set_framebuffer_manager(&framebuffer_manager2);
+
+ scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10);
+ framebuffer_manager1.CreateFramebuffer(10, 10);
+ scoped_refptr<Framebuffer> framebuffer1 =
+ framebuffer_manager1.GetFramebuffer(10);
+ framebuffer1->AttachTexture(GL_COLOR_ATTACHMENT0, ref1, GL_TEXTURE_2D, 0);
+ EXPECT_FALSE(framebuffer_manager1.IsComplete(framebuffer1));
+ EXPECT_NE(kCompleteValue, framebuffer1->IsPossiblyComplete());
+
+ // Make FBO complete in manager 1.
+ texture_manager1_->SetTarget(ref1, GL_TEXTURE_2D);
+ texture_manager1_->SetLevelInfo(ref1, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, true);
+ EXPECT_EQ(kCompleteValue, framebuffer1->IsPossiblyComplete());
+ framebuffer_manager1.MarkAsComplete(framebuffer1);
+ EXPECT_TRUE(framebuffer_manager1.IsComplete(framebuffer1));
+
+ // Share texture with manager 2.
+ scoped_refptr<TextureRef> ref2 = new TextureRef(texture_manager2_.get(),
+ ref1->texture());
+ framebuffer_manager2.CreateFramebuffer(20, 20);
+ scoped_refptr<Framebuffer> framebuffer2 =
+ framebuffer_manager2.GetFramebuffer(20);
+ framebuffer2->AttachTexture(GL_COLOR_ATTACHMENT0, ref2, GL_TEXTURE_2D, 0);
+ EXPECT_FALSE(framebuffer_manager2.IsComplete(framebuffer2));
+ EXPECT_EQ(kCompleteValue, framebuffer2->IsPossiblyComplete());
+ framebuffer_manager2.MarkAsComplete(framebuffer2);
+ EXPECT_TRUE(framebuffer_manager2.IsComplete(framebuffer2));
+
+ // Change level for texture, both FBOs should be marked incomplete
+ texture_manager1_->SetLevelInfo(ref1, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, true);
+ EXPECT_FALSE(framebuffer_manager1.IsComplete(framebuffer1));
+ EXPECT_EQ(kCompleteValue, framebuffer1->IsPossiblyComplete());
+ framebuffer_manager1.MarkAsComplete(framebuffer1);
+ EXPECT_TRUE(framebuffer_manager1.IsComplete(framebuffer1));
+ EXPECT_FALSE(framebuffer_manager2.IsComplete(framebuffer2));
+ EXPECT_EQ(kCompleteValue, framebuffer2->IsPossiblyComplete());
+ framebuffer_manager2.MarkAsComplete(framebuffer2);
+ EXPECT_TRUE(framebuffer_manager2.IsComplete(framebuffer2));
+
+ EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, _))
+ .Times(2)
+ .RetiresOnSaturation();
+ framebuffer_manager1.RemoveFramebuffer(10);
+ framebuffer_manager2.RemoveFramebuffer(20);
+ EXPECT_CALL(*gl_, DeleteTextures(1, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ texture_manager1_->RemoveTexture(10);
+}
+
+TEST_F(SharedTextureTest, Memory) {
+ size_t initial_memory1 = memory_tracker1_->GetSize(MemoryTracker::kUnmanaged);
+ size_t initial_memory2 = memory_tracker2_->GetSize(MemoryTracker::kUnmanaged);
+
+ // Newly created texture is unrenderable.
+ scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10);
+ texture_manager1_->SetTarget(ref1, GL_TEXTURE_2D);
+ texture_manager1_->SetLevelInfo(ref1, GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 1, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, false);
+
+ EXPECT_LT(0u, ref1->texture()->estimated_size());
+ EXPECT_EQ(initial_memory1 + ref1->texture()->estimated_size(),
+ memory_tracker1_->GetSize(MemoryTracker::kUnmanaged));
+
+ // Associate new texture ref to other texture manager, it doesn't account for
+ // the texture memory, the first memory tracker still has it.
+ scoped_refptr<TextureRef> ref2 = new TextureRef(texture_manager2_.get(),
+ ref1->texture());
+ EXPECT_EQ(initial_memory1 + ref1->texture()->estimated_size(),
+ memory_tracker1_->GetSize(MemoryTracker::kUnmanaged));
+ EXPECT_EQ(initial_memory2,
+ memory_tracker2_->GetSize(MemoryTracker::kUnmanaged));
+
+ // Delete the texture, memory should go to the remaining tracker.
+ texture_manager1_->RemoveTexture(10);
+ ref1 = NULL;
+ EXPECT_EQ(initial_memory1,
+ memory_tracker1_->GetSize(MemoryTracker::kUnmanaged));
+ EXPECT_EQ(initial_memory2 + ref2->texture()->estimated_size(),
+ memory_tracker2_->GetSize(MemoryTracker::kUnmanaged));
+
+ EXPECT_CALL(*gl_, DeleteTextures(1, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ ref2 = NULL;
+ EXPECT_EQ(initial_memory2,
+ memory_tracker2_->GetSize(MemoryTracker::kUnmanaged));
+}
+
} // namespace gles2
} // namespace gpu
-
-
diff --git a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittests.cc b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittests.cc
new file mode 100644
index 0000000..ae2ec10
--- /dev/null
+++ b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittests.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2chromium.h>
+#include <GLES2/gl2ext.h>
+#include <GLES2/gl2extchromium.h>
+
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_mock.h"
+#include "gpu/command_buffer/client/image_factory_mock.h"
+#include "gpu/command_buffer/service/image_manager.h"
+#include "gpu/command_buffer/tests/gl_manager.h"
+#include "gpu/command_buffer/tests/gl_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/gl_image.h"
+#include "ui/gl/gl_image_mock.h"
+
+using testing::_;
+using testing::IgnoreResult;
+using testing::InvokeWithoutArgs;
+using testing::Invoke;
+using testing::Return;
+using testing::SetArgPointee;
+using testing::StrictMock;
+
+namespace gpu {
+namespace gles2 {
+
+static const int kImageWidth = 256;
+static const int kImageHeight = 256;
+static const int kImageBytesPerPixel = 4;
+
+class MockGpuMemoryBufferTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ GLManager::Options options;
+ image_manager_ = new ImageManager;
+ image_factory_.reset(
+ new StrictMock<ImageFactoryMock>(image_manager_));
+ options.image_manager = image_manager_;
+ options.image_factory = image_factory_.get();
+
+ gl_.Initialize(options);
+ gl_.MakeCurrent();
+ }
+
+ virtual void TearDown() {
+ gl_.Destroy();
+ }
+
+ scoped_ptr<StrictMock<ImageFactoryMock> > image_factory_;
+ scoped_refptr<ImageManager> image_manager_;
+ GLManager gl_;
+};
+
+// An end to end test that tests the whole GpuMemoryBuffer lifecycle.
+TEST_F(MockGpuMemoryBufferTest, Lifecycle) {
+ // Create a client texture id.
+ GLuint texture_id;
+ glGenTextures(1, &texture_id);
+
+ // Buffer is owned and freed by GpuMemoryBufferTracker.
+ StrictMock<GpuMemoryBufferMock>* gpu_memory_buffer =
+ new StrictMock<GpuMemoryBufferMock>(kImageWidth, kImageHeight);
+
+ const GLuint kImageId = 345u;
+
+ EXPECT_CALL(*image_factory_.get(), CreateGpuMemoryBufferMock(
+ kImageWidth, kImageHeight, GL_RGBA8_OES, _))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<3>(kImageId),
+ Return(gpu_memory_buffer)))
+ .RetiresOnSaturation();
+
+ // Create the GLImage and insert it into the ImageManager, which
+ // would be done within CreateGpuMemoryBufferMock if it weren't a mock.
+ GLuint image_id = glCreateImageCHROMIUM(
+ kImageWidth, kImageHeight, GL_RGBA8_OES);
+ EXPECT_EQ(kImageId, image_id);
+
+ gfx::Size size(kImageWidth, kImageHeight);
+ scoped_refptr<gfx::GLImageMock> gl_image(
+ new gfx::GLImageMock(gpu_memory_buffer, size));
+ image_manager_->AddImage(gl_image.get(), image_id);
+
+ EXPECT_CALL(*gpu_memory_buffer, IsMapped())
+ .WillOnce(Return(false))
+ .RetiresOnSaturation();
+
+ scoped_ptr<uint8[]> buffer_pixels(new uint8[
+ kImageWidth * kImageHeight * kImageBytesPerPixel]);
+
+ EXPECT_CALL(*gpu_memory_buffer, Map(_, _))
+ .Times(1)
+ .WillOnce(SetArgPointee<1>(buffer_pixels.get()))
+ .RetiresOnSaturation();
+ void* mapped_buffer =
+ glMapImageCHROMIUM(image_id, GL_WRITE_ONLY);
+ EXPECT_EQ(buffer_pixels.get(), mapped_buffer);
+
+ EXPECT_CALL(*gpu_memory_buffer, IsMapped())
+ .WillOnce(Return(true))
+ .RetiresOnSaturation();
+
+ // Unmap the image.
+ EXPECT_CALL(*gpu_memory_buffer, Unmap())
+ .Times(1)
+ .RetiresOnSaturation();
+ glUnmapImageCHROMIUM(image_id);
+
+ // Bind the texture and the image.
+ glBindTexture(GL_TEXTURE_2D, texture_id);
+ EXPECT_CALL(*gl_image, BindTexImage())
+ .Times(1)
+ .WillOnce(Return(true))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_image, GetSize())
+ .Times(1)
+ .WillOnce(Return(size))
+ .RetiresOnSaturation();
+ glBindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id);
+
+ // Destroy the image.
+ EXPECT_CALL(*gpu_memory_buffer, Die())
+ .Times(1)
+ .RetiresOnSaturation();
+
+ EXPECT_CALL(*image_factory_.get(), DeleteGpuMemoryBuffer(image_id))
+ .Times(1)
+ .RetiresOnSaturation();
+
+ glDestroyImageCHROMIUM(image_id);
+
+ // Delete the texture.
+ glDeleteTextures(1, &texture_id);
+}
+
+} // namespace gles2
+} // namespace gpu
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index 75a254a..3e55384 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -16,6 +16,7 @@
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gl_context_virtual.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
+#include "gpu/command_buffer/service/image_manager.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_context.h"
@@ -35,7 +36,9 @@
share_mailbox_manager(NULL),
virtual_manager(NULL),
bind_generates_resource(false),
- context_lost_allowed(false) {
+ context_lost_allowed(false),
+ image_manager(NULL),
+ image_factory(NULL) {
}
GLManager::GLManager()
@@ -127,7 +130,7 @@
if (!context_group) {
context_group = new gles2::ContextGroup(mailbox_manager_.get(),
- NULL,
+ options.image_manager,
NULL,
options.bind_generates_resource);
}
@@ -196,7 +199,8 @@
client_share_group,
transfer_buffer_.get(),
kShareResources,
- options.bind_generates_resource));
+ options.bind_generates_resource,
+ options.image_factory));
ASSERT_TRUE(gles2_implementation_->Initialize(
kStartTransferBufferSize,
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h
index 2ebe695..15fc9ef 100644
--- a/gpu/command_buffer/tests/gl_manager.h
+++ b/gpu/command_buffer/tests/gl_manager.h
@@ -30,6 +30,8 @@
class GLES2Decoder;
class GLES2CmdHelper;
class GLES2Implementation;
+class ImageFactory;
+class ImageManager;
class ShareGroup;
};
@@ -50,6 +52,10 @@
bool bind_generates_resource;
// Whether or not it's ok to lose the context.
bool context_lost_allowed;
+ // Image manager to be used.
+ gles2::ImageManager* image_manager;
+ // Image factory to be used.
+ gles2::ImageFactory* image_factory;
};
GLManager();
~GLManager();
diff --git a/gpu/command_buffer/tests/gl_pointcoord_unittest.cc b/gpu/command_buffer/tests/gl_pointcoord_unittest.cc
index 5073ad3..fe71eed 100644
--- a/gpu/command_buffer/tests/gl_pointcoord_unittest.cc
+++ b/gpu/command_buffer/tests/gl_pointcoord_unittest.cc
@@ -101,7 +101,7 @@
GLint position_loc = glGetAttribLocation(program, "a_position");
GLint pointsize_loc = glGetUniformLocation(program, "u_pointsize");
- GLint range[2] = { 0, };
+ GLint range[2] = { 0, 0 };
glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, &range[0]);
GLint max_point_size = range[1];
EXPECT_GE(max_point_size, 1);
diff --git a/gpu/command_buffer/tests/gl_tests_main.cc b/gpu/command_buffer/tests/gl_tests_main.cc
index a3a406d..7931cb8 100644
--- a/gpu/command_buffer/tests/gl_tests_main.cc
+++ b/gpu/command_buffer/tests/gl_tests_main.cc
@@ -10,6 +10,7 @@
#endif
#include "gpu/command_buffer/client/gles2_lib.h"
#include "gpu/command_buffer/tests/gl_test_utils.h"
+#include "gpu/config/gpu_util.h"
#include "ui/gl/gl_surface.h"
#if defined(OS_ANDROID)
@@ -36,6 +37,7 @@
#endif
gfx::GLSurface::InitializeOneOff();
::gles2::Initialize();
+ gpu::ApplyGpuDriverBugWorkarounds(CommandLine::ForCurrentProcess());
base::MessageLoop::Type message_loop_type = base::MessageLoop::TYPE_UI;
base::MessageLoop main_message_loop(message_loop_type);
return GLTestHelper::RunTests(argc, argv);
diff --git a/gpu/command_buffer_client.target.darwin-arm.mk b/gpu/command_buffer_client.target.darwin-arm.mk
index 8459b33..21565a5 100644
--- a/gpu/command_buffer_client.target.darwin-arm.mk
+++ b/gpu/command_buffer_client.target.darwin-arm.mk
@@ -73,6 +73,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -98,9 +99,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_client.target.darwin-x86.mk b/gpu/command_buffer_client.target.darwin-x86.mk
index 7d9eae5..bb1f905 100644
--- a/gpu/command_buffer_client.target.darwin-x86.mk
+++ b/gpu/command_buffer_client.target.darwin-x86.mk
@@ -75,6 +75,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -100,9 +101,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_client.target.linux-arm.mk b/gpu/command_buffer_client.target.linux-arm.mk
index 8459b33..21565a5 100644
--- a/gpu/command_buffer_client.target.linux-arm.mk
+++ b/gpu/command_buffer_client.target.linux-arm.mk
@@ -73,6 +73,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -98,9 +99,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_client.target.linux-x86.mk b/gpu/command_buffer_client.target.linux-x86.mk
index 7d9eae5..bb1f905 100644
--- a/gpu/command_buffer_client.target.linux-x86.mk
+++ b/gpu/command_buffer_client.target.linux-x86.mk
@@ -75,6 +75,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -100,9 +101,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_common.target.darwin-arm.mk b/gpu/command_buffer_common.target.darwin-arm.mk
index 87d0397..8379f7c 100644
--- a/gpu/command_buffer_common.target.darwin-arm.mk
+++ b/gpu/command_buffer_common.target.darwin-arm.mk
@@ -72,6 +72,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -97,9 +98,9 @@
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
$(LOCAL_PATH) \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_common.target.darwin-x86.mk b/gpu/command_buffer_common.target.darwin-x86.mk
index 3ba9232..2e39ae3 100644
--- a/gpu/command_buffer_common.target.darwin-x86.mk
+++ b/gpu/command_buffer_common.target.darwin-x86.mk
@@ -74,6 +74,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -99,9 +100,9 @@
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
$(LOCAL_PATH) \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_common.target.linux-arm.mk b/gpu/command_buffer_common.target.linux-arm.mk
index 87d0397..8379f7c 100644
--- a/gpu/command_buffer_common.target.linux-arm.mk
+++ b/gpu/command_buffer_common.target.linux-arm.mk
@@ -72,6 +72,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -97,9 +98,9 @@
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
$(LOCAL_PATH) \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_common.target.linux-x86.mk b/gpu/command_buffer_common.target.linux-x86.mk
index 3ba9232..2e39ae3 100644
--- a/gpu/command_buffer_common.target.linux-x86.mk
+++ b/gpu/command_buffer_common.target.linux-x86.mk
@@ -74,6 +74,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -99,9 +100,9 @@
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
$(LOCAL_PATH) \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi
index c31e8f2..9e291da 100644
--- a/gpu/command_buffer_service.gypi
+++ b/gpu/command_buffer_service.gypi
@@ -32,6 +32,8 @@
'command_buffer/service/async_pixel_transfer_delegate_idle.h',
'command_buffer/service/async_pixel_transfer_delegate_linux.cc',
'command_buffer/service/async_pixel_transfer_delegate_mac.cc',
+ 'command_buffer/service/async_pixel_transfer_delegate_share_group.cc',
+ 'command_buffer/service/async_pixel_transfer_delegate_share_group.h',
'command_buffer/service/async_pixel_transfer_delegate_stub.cc',
'command_buffer/service/async_pixel_transfer_delegate_stub.h',
'command_buffer/service/async_pixel_transfer_delegate_sync.cc',
@@ -72,7 +74,6 @@
'command_buffer/service/gl_state_restorer_impl.cc',
'command_buffer/service/gl_state_restorer_impl.h',
'command_buffer/service/gl_utils.h',
- 'command_buffer/service/gpu_driver_bug_workaround_type.h',
'command_buffer/service/gpu_scheduler.h',
'command_buffer/service/gpu_scheduler.cc',
'command_buffer/service/gpu_scheduler_mock.h',
diff --git a/gpu/command_buffer_service.target.darwin-arm.mk b/gpu/command_buffer_service.target.darwin-arm.mk
index f1b7273..270bdfe 100644
--- a/gpu/command_buffer_service.target.darwin-arm.mk
+++ b/gpu/command_buffer_service.target.darwin-arm.mk
@@ -30,6 +30,7 @@
gpu/command_buffer/service/async_pixel_transfer_delegate.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_android.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_idle.cc \
+ gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_stub.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_sync.cc \
gpu/command_buffer/service/buffer_manager.cc \
@@ -112,6 +113,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -147,14 +149,14 @@
$(gyp_shared_intermediate_dir)/protoc_out \
$(gyp_shared_intermediate_dir)/ui/gl \
$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+ $(PWD)/external/icu4c/common \
+ $(PWD)/external/icu4c/i18n \
$(LOCAL_PATH)/third_party/protobuf \
$(LOCAL_PATH)/third_party/protobuf/src \
$(LOCAL_PATH)/third_party/re2 \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_service.target.darwin-x86.mk b/gpu/command_buffer_service.target.darwin-x86.mk
index e752daf..7c911ab 100644
--- a/gpu/command_buffer_service.target.darwin-x86.mk
+++ b/gpu/command_buffer_service.target.darwin-x86.mk
@@ -30,6 +30,7 @@
gpu/command_buffer/service/async_pixel_transfer_delegate.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_android.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_idle.cc \
+ gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_stub.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_sync.cc \
gpu/command_buffer/service/buffer_manager.cc \
@@ -114,6 +115,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -148,14 +150,14 @@
$(gyp_shared_intermediate_dir)/protoc_out \
$(gyp_shared_intermediate_dir)/ui/gl \
$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+ $(PWD)/external/icu4c/common \
+ $(PWD)/external/icu4c/i18n \
$(LOCAL_PATH)/third_party/protobuf \
$(LOCAL_PATH)/third_party/protobuf/src \
$(LOCAL_PATH)/third_party/re2 \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_service.target.linux-arm.mk b/gpu/command_buffer_service.target.linux-arm.mk
index f1b7273..270bdfe 100644
--- a/gpu/command_buffer_service.target.linux-arm.mk
+++ b/gpu/command_buffer_service.target.linux-arm.mk
@@ -30,6 +30,7 @@
gpu/command_buffer/service/async_pixel_transfer_delegate.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_android.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_idle.cc \
+ gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_stub.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_sync.cc \
gpu/command_buffer/service/buffer_manager.cc \
@@ -112,6 +113,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -147,14 +149,14 @@
$(gyp_shared_intermediate_dir)/protoc_out \
$(gyp_shared_intermediate_dir)/ui/gl \
$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+ $(PWD)/external/icu4c/common \
+ $(PWD)/external/icu4c/i18n \
$(LOCAL_PATH)/third_party/protobuf \
$(LOCAL_PATH)/third_party/protobuf/src \
$(LOCAL_PATH)/third_party/re2 \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/command_buffer_service.target.linux-x86.mk b/gpu/command_buffer_service.target.linux-x86.mk
index e752daf..7c911ab 100644
--- a/gpu/command_buffer_service.target.linux-x86.mk
+++ b/gpu/command_buffer_service.target.linux-x86.mk
@@ -30,6 +30,7 @@
gpu/command_buffer/service/async_pixel_transfer_delegate.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_android.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_idle.cc \
+ gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_stub.cc \
gpu/command_buffer/service/async_pixel_transfer_delegate_sync.cc \
gpu/command_buffer/service/buffer_manager.cc \
@@ -114,6 +115,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -148,14 +150,14 @@
$(gyp_shared_intermediate_dir)/protoc_out \
$(gyp_shared_intermediate_dir)/ui/gl \
$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+ $(PWD)/external/icu4c/common \
+ $(PWD)/external/icu4c/i18n \
$(LOCAL_PATH)/third_party/protobuf \
$(LOCAL_PATH)/third_party/protobuf/src \
$(LOCAL_PATH)/third_party/re2 \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/config/DEPS b/gpu/config/DEPS
new file mode 100644
index 0000000..39b325a
--- /dev/null
+++ b/gpu/config/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+third_party/libxml", # For parsing WinSAT results files.
+ "+third_party/libXNVCtrl", # For NV driver version query.
+]
diff --git a/gpu/config/OWNERS b/gpu/config/OWNERS
new file mode 100644
index 0000000..fed3782
--- /dev/null
+++ b/gpu/config/OWNERS
@@ -0,0 +1,5 @@
+apatrick@chromium.org
+kbr@chromium.org
+gman@chromium.org
+piman@chromium.org
+zmo@chromium.org
diff --git a/gpu/config/dx_diag_node.cc b/gpu/config/dx_diag_node.cc
new file mode 100644
index 0000000..e0902ca
--- /dev/null
+++ b/gpu/config/dx_diag_node.cc
@@ -0,0 +1,13 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/dx_diag_node.h"
+
+namespace gpu {
+
+DxDiagNode::DxDiagNode() {}
+
+DxDiagNode::~DxDiagNode() {}
+
+} // namespace gpu
diff --git a/gpu/config/dx_diag_node.h b/gpu/config/dx_diag_node.h
new file mode 100644
index 0000000..33d29b3
--- /dev/null
+++ b/gpu/config/dx_diag_node.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// A tree of name value pairs that report contain DirectX diagnostic
+// information.
+
+#ifndef GPU_CONFIG_DX_DIAG_NODE_H_
+#define GPU_CONFIG_DX_DIAG_NODE_H_
+
+#include <map>
+#include <string>
+
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+
+struct GPU_EXPORT DxDiagNode {
+ DxDiagNode();
+ ~DxDiagNode();
+ std::map<std::string, std::string> values;
+ std::map<std::string, DxDiagNode> children;
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_DX_DIAG_NODE_H_
diff --git a/gpu/config/gpu_blacklist.cc b/gpu/config/gpu_blacklist.cc
new file mode 100644
index 0000000..39946b0
--- /dev/null
+++ b/gpu/config/gpu_blacklist.cc
@@ -0,0 +1,51 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_blacklist.h"
+
+#include "gpu/config/gpu_feature_type.h"
+
+namespace gpu {
+
+GpuBlacklist::GpuBlacklist()
+ : GpuControlList() {
+}
+
+GpuBlacklist::~GpuBlacklist() {
+}
+
+// static
+GpuBlacklist* GpuBlacklist::Create() {
+ GpuBlacklist* list = new GpuBlacklist();
+ list->AddSupportedFeature("accelerated_2d_canvas",
+ GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);
+ list->AddSupportedFeature("accelerated_compositing",
+ GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);
+ list->AddSupportedFeature("webgl",
+ GPU_FEATURE_TYPE_WEBGL);
+ list->AddSupportedFeature("multisampling",
+ GPU_FEATURE_TYPE_MULTISAMPLING);
+ list->AddSupportedFeature("flash_3d",
+ GPU_FEATURE_TYPE_FLASH3D);
+ list->AddSupportedFeature("flash_stage3d",
+ GPU_FEATURE_TYPE_FLASH_STAGE3D);
+ list->AddSupportedFeature("flash_stage3d_baseline",
+ GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE);
+ list->AddSupportedFeature("texture_sharing",
+ GPU_FEATURE_TYPE_TEXTURE_SHARING);
+ list->AddSupportedFeature("accelerated_video_decode",
+ GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE);
+ list->AddSupportedFeature("3d_css",
+ GPU_FEATURE_TYPE_3D_CSS);
+ list->AddSupportedFeature("accelerated_video",
+ GPU_FEATURE_TYPE_ACCELERATED_VIDEO);
+ list->AddSupportedFeature("panel_fitting",
+ GPU_FEATURE_TYPE_PANEL_FITTING);
+ list->AddSupportedFeature("force_compositing_mode",
+ GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE);
+ list->set_supports_feature_type_all(true);
+ return list;
+}
+
+} // namespace gpu
diff --git a/gpu/config/gpu_blacklist.h b/gpu/config/gpu_blacklist.h
new file mode 100644
index 0000000..4311212
--- /dev/null
+++ b/gpu/config/gpu_blacklist.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_BLACKLIST_H_
+#define GPU_CONFIG_GPU_BLACKLIST_H_
+
+#include <string>
+
+#include "gpu/config/gpu_control_list.h"
+
+namespace gpu {
+
+class GPU_EXPORT GpuBlacklist : public GpuControlList {
+ public:
+ virtual ~GpuBlacklist();
+
+ static GpuBlacklist* Create();
+
+ private:
+ GpuBlacklist();
+
+ DISALLOW_COPY_AND_ASSIGN(GpuBlacklist);
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_BLACKLIST_H_
diff --git a/gpu/config/gpu_blacklist_unittest.cc b/gpu/config/gpu_blacklist_unittest.cc
new file mode 100644
index 0000000..3282437
--- /dev/null
+++ b/gpu/config/gpu_blacklist_unittest.cc
@@ -0,0 +1,143 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "gpu/config/gpu_blacklist.h"
+#include "gpu/config/gpu_control_list_jsons.h"
+#include "gpu/config/gpu_feature_type.h"
+#include "gpu/config/gpu_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+const char kOsVersion[] = "10.6.4";
+
+namespace gpu {
+
+class GpuBlacklistTest : public testing::Test {
+ public:
+ GpuBlacklistTest() { }
+
+ virtual ~GpuBlacklistTest() { }
+
+ const GPUInfo& gpu_info() const {
+ return gpu_info_;
+ }
+
+ void RunFeatureTest(
+ const std::string feature_name, GpuFeatureType feature_type) {
+ const std::string json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"macosx\"\n"
+ " },\n"
+ " \"vendor_id\": \"0x10de\",\n"
+ " \"device_id\": [\"0x0640\"],\n"
+ " \"features\": [\n"
+ " \"" +
+ feature_name +
+ "\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+
+ scoped_ptr<GpuBlacklist> blacklist(GpuBlacklist::Create());
+ EXPECT_TRUE(blacklist->LoadList(json, GpuBlacklist::kAllOs));
+ std::set<int> type = blacklist->MakeDecision(
+ GpuBlacklist::kOsMacosx, kOsVersion, gpu_info());
+ EXPECT_EQ(1u, type.size());
+ EXPECT_EQ(1u, type.count(feature_type));
+ }
+
+ protected:
+ virtual void SetUp() {
+ gpu_info_.gpu.vendor_id = 0x10de;
+ gpu_info_.gpu.device_id = 0x0640;
+ gpu_info_.driver_vendor = "NVIDIA";
+ gpu_info_.driver_version = "1.6.18";
+ gpu_info_.driver_date = "7-14-2009";
+ gpu_info_.machine_model = "MacBookPro 7.1";
+ gpu_info_.gl_vendor = "NVIDIA Corporation";
+ gpu_info_.gl_renderer = "NVIDIA GeForce GT 120 OpenGL Engine";
+ gpu_info_.performance_stats.graphics = 5.0;
+ gpu_info_.performance_stats.gaming = 5.0;
+ gpu_info_.performance_stats.overall = 5.0;
+ }
+
+ virtual void TearDown() {
+ }
+
+ private:
+ GPUInfo gpu_info_;
+};
+
+TEST_F(GpuBlacklistTest, CurrentBlacklistValidation) {
+ scoped_ptr<GpuBlacklist> blacklist(GpuBlacklist::Create());
+ EXPECT_TRUE(blacklist->LoadList(
+ kSoftwareRenderingListJson, GpuBlacklist::kAllOs));
+ EXPECT_FALSE(blacklist->contains_unknown_fields());
+}
+
+#define GPU_BLACKLIST_FEATURE_TEST(test_name, feature_name, feature_type) \
+TEST_F(GpuBlacklistTest, test_name) { \
+ RunFeatureTest(feature_name, feature_type); \
+}
+
+GPU_BLACKLIST_FEATURE_TEST(Accelerated2DCanvas,
+ "accelerated_2d_canvas",
+ GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
+
+GPU_BLACKLIST_FEATURE_TEST(AcceleratedCompositing,
+ "accelerated_compositing",
+ GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)
+
+GPU_BLACKLIST_FEATURE_TEST(WebGL,
+ "webgl",
+ GPU_FEATURE_TYPE_WEBGL)
+
+GPU_BLACKLIST_FEATURE_TEST(Multisampling,
+ "multisampling",
+ GPU_FEATURE_TYPE_MULTISAMPLING)
+
+GPU_BLACKLIST_FEATURE_TEST(Flash3D,
+ "flash_3d",
+ GPU_FEATURE_TYPE_FLASH3D)
+
+GPU_BLACKLIST_FEATURE_TEST(FlashStage3D,
+ "flash_stage3d",
+ GPU_FEATURE_TYPE_FLASH_STAGE3D)
+
+GPU_BLACKLIST_FEATURE_TEST(FlashStage3DBaseline,
+ "flash_stage3d_baseline",
+ GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE)
+
+GPU_BLACKLIST_FEATURE_TEST(TextureSharing,
+ "texture_sharing",
+ GPU_FEATURE_TYPE_TEXTURE_SHARING)
+
+GPU_BLACKLIST_FEATURE_TEST(AcceleratedVideoDecode,
+ "accelerated_video_decode",
+ GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE)
+
+GPU_BLACKLIST_FEATURE_TEST(Css3D,
+ "3d_css",
+ GPU_FEATURE_TYPE_3D_CSS)
+
+GPU_BLACKLIST_FEATURE_TEST(AcceleratedVideo,
+ "accelerated_video",
+ GPU_FEATURE_TYPE_ACCELERATED_VIDEO)
+
+GPU_BLACKLIST_FEATURE_TEST(PanelFitting,
+ "panel_fitting",
+ GPU_FEATURE_TYPE_PANEL_FITTING)
+
+GPU_BLACKLIST_FEATURE_TEST(ForceCompositingMode,
+ "force_compositing_mode",
+ GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE)
+
+} // namespace gpu
diff --git a/gpu/config/gpu_control_list.cc b/gpu/config/gpu_control_list.cc
new file mode 100644
index 0000000..670ccff
--- /dev/null
+++ b/gpu/config/gpu_control_list.cc
@@ -0,0 +1,1415 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_control_list.h"
+
+#include "base/cpu.h"
+#include "base/json/json_reader.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/sys_info.h"
+#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_util.h"
+
+namespace gpu {
+namespace {
+
+// Break a version string into segments. Return true if each segment is
+// a valid number.
+bool ProcessVersionString(const std::string& version_string,
+ char splitter,
+ std::vector<std::string>* version) {
+ DCHECK(version);
+ base::SplitString(version_string, splitter, version);
+ if (version->size() == 0)
+ return false;
+ // If the splitter is '-', we assume it's a date with format "mm-dd-yyyy";
+ // we split it into the order of "yyyy", "mm", "dd".
+ if (splitter == '-') {
+ std::string year = (*version)[version->size() - 1];
+ for (int i = version->size() - 1; i > 0; --i) {
+ (*version)[i] = (*version)[i - 1];
+ }
+ (*version)[0] = year;
+ }
+ for (size_t i = 0; i < version->size(); ++i) {
+ unsigned num = 0;
+ if (!base::StringToUint((*version)[i], &num))
+ return false;
+ }
+ return true;
+}
+
+// Compare two number strings using numerical ordering.
+// Return 0 if number = number_ref,
+// 1 if number > number_ref,
+// -1 if number < number_ref.
+int CompareNumericalNumberStrings(
+ const std::string& number, const std::string& number_ref) {
+ unsigned value1 = 0;
+ unsigned value2 = 0;
+ bool valid = base::StringToUint(number, &value1);
+ DCHECK(valid);
+ valid = base::StringToUint(number_ref, &value2);
+ DCHECK(valid);
+ if (value1 == value2)
+ return 0;
+ if (value1 > value2)
+ return 1;
+ return -1;
+}
+
+// Compare two number strings using lexical ordering.
+// Return 0 if number = number_ref,
+// 1 if number > number_ref,
+// -1 if number < number_ref.
+// We only compare as many digits as number_ref contains.
+// If number_ref is xxx, it's considered as xxx*
+// For example: CompareLexicalNumberStrings("121", "12") returns 0,
+// CompareLexicalNumberStrings("12", "121") returns -1.
+int CompareLexicalNumberStrings(
+ const std::string& number, const std::string& number_ref) {
+ for (size_t i = 0; i < number_ref.length(); ++i) {
+ unsigned value1 = 0;
+ if (i < number.length())
+ value1 = number[i] - '0';
+ unsigned value2 = number_ref[i] - '0';
+ if (value1 > value2)
+ return 1;
+ if (value1 < value2)
+ return -1;
+ }
+ return 0;
+}
+
+bool GpuUnmatched(uint32 vendor_id, const std::vector<uint32>& device_id_list,
+ const GPUInfo::GPUDevice& gpu) {
+ if (vendor_id == 0)
+ return false;
+ if (vendor_id != gpu.vendor_id)
+ return true;
+ bool device_specified = false;
+ for (size_t i = 0; i < device_id_list.size(); ++i) {
+ if (device_id_list[i] == 0)
+ continue;
+ if (device_id_list[i] == gpu.device_id)
+ return false;
+ device_specified = true;
+ }
+ return device_specified;
+}
+
+const char kMultiGpuStyleStringAMDSwitchable[] = "amd_switchable";
+const char kMultiGpuStyleStringOptimus[] = "optimus";
+
+const char kMultiGpuCategoryStringPrimary[] = "primary";
+const char kMultiGpuCategoryStringSecondary[] = "secondary";
+const char kMultiGpuCategoryStringAny[] = "any";
+
+const char kVersionStyleStringNumerical[] = "numerical";
+const char kVersionStyleStringLexical[] = "lexical";
+
+const char kOp[] = "op";
+
+} // namespace anonymous
+
+GpuControlList::VersionInfo::VersionInfo(
+ const std::string& version_op,
+ const std::string& version_style,
+ const std::string& version_string,
+ const std::string& version_string2)
+ : version_style_(kVersionStyleNumerical) {
+ op_ = StringToNumericOp(version_op);
+ if (op_ == kUnknown || op_ == kAny)
+ return;
+ version_style_ = StringToVersionStyle(version_style);
+ if (!ProcessVersionString(version_string, '.', &version_)) {
+ op_ = kUnknown;
+ return;
+ }
+ if (op_ == kBetween) {
+ if (!ProcessVersionString(version_string2, '.', &version2_))
+ op_ = kUnknown;
+ }
+}
+
+GpuControlList::VersionInfo::~VersionInfo() {
+}
+
+bool GpuControlList::VersionInfo::Contains(
+ const std::string& version_string) const {
+ return Contains(version_string, '.');
+}
+
+bool GpuControlList::VersionInfo::Contains(
+ const std::string& version_string, char splitter) const {
+ if (op_ == kUnknown)
+ return false;
+ if (op_ == kAny)
+ return true;
+ std::vector<std::string> version;
+ if (!ProcessVersionString(version_string, splitter, &version))
+ return false;
+ int relation = Compare(version, version_, version_style_);
+ if (op_ == kEQ)
+ return (relation == 0);
+ else if (op_ == kLT)
+ return (relation < 0);
+ else if (op_ == kLE)
+ return (relation <= 0);
+ else if (op_ == kGT)
+ return (relation > 0);
+ else if (op_ == kGE)
+ return (relation >= 0);
+ // op_ == kBetween
+ if (relation < 0)
+ return false;
+ return Compare(version, version2_, version_style_) <= 0;
+}
+
+bool GpuControlList::VersionInfo::IsValid() const {
+ return (op_ != kUnknown && version_style_ != kVersionStyleUnknown);
+}
+
+bool GpuControlList::VersionInfo::IsLexical() const {
+ return version_style_ == kVersionStyleLexical;
+}
+
+// static
+int GpuControlList::VersionInfo::Compare(
+ const std::vector<std::string>& version,
+ const std::vector<std::string>& version_ref,
+ VersionStyle version_style) {
+ DCHECK(version.size() > 0 && version_ref.size() > 0);
+ DCHECK(version_style != kVersionStyleUnknown);
+ for (size_t i = 0; i < version_ref.size(); ++i) {
+ if (i >= version.size())
+ return 0;
+ int ret = 0;
+ // We assume both versions are checked by ProcessVersionString().
+ if (i > 0 && version_style == kVersionStyleLexical)
+ ret = CompareLexicalNumberStrings(version[i], version_ref[i]);
+ else
+ ret = CompareNumericalNumberStrings(version[i], version_ref[i]);
+ if (ret != 0)
+ return ret;
+ }
+ return 0;
+}
+
+// static
+GpuControlList::VersionInfo::VersionStyle
+GpuControlList::VersionInfo::StringToVersionStyle(
+ const std::string& version_style) {
+ if (version_style.empty() || version_style == kVersionStyleStringNumerical)
+ return kVersionStyleNumerical;
+ if (version_style == kVersionStyleStringLexical)
+ return kVersionStyleLexical;
+ return kVersionStyleUnknown;
+}
+
+GpuControlList::OsInfo::OsInfo(const std::string& os,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2) {
+ type_ = StringToOsType(os);
+ if (type_ != kOsUnknown) {
+ version_info_.reset(new VersionInfo(
+ version_op, std::string(), version_string, version_string2));
+ }
+}
+
+GpuControlList::OsInfo::~OsInfo() {}
+
+bool GpuControlList::OsInfo::Contains(OsType type,
+ const std::string& version) const {
+ if (!IsValid())
+ return false;
+ if (type_ != type && type_ != kOsAny)
+ return false;
+ return version_info_->Contains(version);
+}
+
+bool GpuControlList::OsInfo::IsValid() const {
+ return type_ != kOsUnknown && version_info_->IsValid();
+}
+
+GpuControlList::OsType GpuControlList::OsInfo::type() const {
+ return type_;
+}
+
+GpuControlList::OsType GpuControlList::OsInfo::StringToOsType(
+ const std::string& os) {
+ if (os == "win")
+ return kOsWin;
+ else if (os == "macosx")
+ return kOsMacosx;
+ else if (os == "android")
+ return kOsAndroid;
+ else if (os == "linux")
+ return kOsLinux;
+ else if (os == "chromeos")
+ return kOsChromeOS;
+ else if (os == "any")
+ return kOsAny;
+ return kOsUnknown;
+}
+
+GpuControlList::MachineModelInfo::MachineModelInfo(
+ const std::string& name_op,
+ const std::string& name_value,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2) {
+ name_info_.reset(new StringInfo(name_op, name_value));
+ version_info_.reset(new VersionInfo(
+ version_op, std::string(), version_string, version_string2));
+}
+
+GpuControlList::MachineModelInfo::~MachineModelInfo() {}
+
+bool GpuControlList::MachineModelInfo::Contains(
+ const std::string& name, const std::string& version) const {
+ if (!IsValid())
+ return false;
+ if (!name_info_->Contains(name))
+ return false;
+ return version_info_->Contains(version);
+}
+
+bool GpuControlList::MachineModelInfo::IsValid() const {
+ return name_info_->IsValid() && version_info_->IsValid();
+}
+
+GpuControlList::StringInfo::StringInfo(const std::string& string_op,
+ const std::string& string_value) {
+ op_ = StringToOp(string_op);
+ value_ = StringToLowerASCII(string_value);
+}
+
+bool GpuControlList::StringInfo::Contains(const std::string& value) const {
+ std::string my_value = StringToLowerASCII(value);
+ switch (op_) {
+ case kContains:
+ return strstr(my_value.c_str(), value_.c_str()) != NULL;
+ case kBeginWith:
+ return StartsWithASCII(my_value, value_, false);
+ case kEndWith:
+ return EndsWith(my_value, value_, false);
+ case kEQ:
+ return value_ == my_value;
+ default:
+ return false;
+ }
+}
+
+bool GpuControlList::StringInfo::IsValid() const {
+ return op_ != kUnknown;
+}
+
+GpuControlList::StringInfo::Op GpuControlList::StringInfo::StringToOp(
+ const std::string& string_op) {
+ if (string_op == "=")
+ return kEQ;
+ else if (string_op == "contains")
+ return kContains;
+ else if (string_op == "beginwith")
+ return kBeginWith;
+ else if (string_op == "endwith")
+ return kEndWith;
+ return kUnknown;
+}
+
+GpuControlList::FloatInfo::FloatInfo(const std::string& float_op,
+ const std::string& float_value,
+ const std::string& float_value2)
+ : op_(kUnknown),
+ value_(0.f),
+ value2_(0.f) {
+ op_ = StringToNumericOp(float_op);
+ if (op_ == kAny)
+ return;
+ double dvalue = 0;
+ if (!base::StringToDouble(float_value, &dvalue)) {
+ op_ = kUnknown;
+ return;
+ }
+ value_ = static_cast<float>(dvalue);
+ if (op_ == kBetween) {
+ if (!base::StringToDouble(float_value2, &dvalue)) {
+ op_ = kUnknown;
+ return;
+ }
+ value2_ = static_cast<float>(dvalue);
+ }
+}
+
+bool GpuControlList::FloatInfo::Contains(float value) const {
+ if (op_ == kUnknown)
+ return false;
+ if (op_ == kAny)
+ return true;
+ if (op_ == kEQ)
+ return (value == value_);
+ if (op_ == kLT)
+ return (value < value_);
+ if (op_ == kLE)
+ return (value <= value_);
+ if (op_ == kGT)
+ return (value > value_);
+ if (op_ == kGE)
+ return (value >= value_);
+ DCHECK(op_ == kBetween);
+ return ((value_ <= value && value <= value2_) ||
+ (value2_ <= value && value <= value_));
+}
+
+bool GpuControlList::FloatInfo::IsValid() const {
+ return op_ != kUnknown;
+}
+
+GpuControlList::IntInfo::IntInfo(const std::string& int_op,
+ const std::string& int_value,
+ const std::string& int_value2)
+ : op_(kUnknown),
+ value_(0),
+ value2_(0) {
+ op_ = StringToNumericOp(int_op);
+ if (op_ == kAny)
+ return;
+ if (!base::StringToInt(int_value, &value_)) {
+ op_ = kUnknown;
+ return;
+ }
+ if (op_ == kBetween &&
+ !base::StringToInt(int_value2, &value2_))
+ op_ = kUnknown;
+}
+
+bool GpuControlList::IntInfo::Contains(int value) const {
+ if (op_ == kUnknown)
+ return false;
+ if (op_ == kAny)
+ return true;
+ if (op_ == kEQ)
+ return (value == value_);
+ if (op_ == kLT)
+ return (value < value_);
+ if (op_ == kLE)
+ return (value <= value_);
+ if (op_ == kGT)
+ return (value > value_);
+ if (op_ == kGE)
+ return (value >= value_);
+ DCHECK(op_ == kBetween);
+ return ((value_ <= value && value <= value2_) ||
+ (value2_ <= value && value <= value_));
+}
+
+bool GpuControlList::IntInfo::IsValid() const {
+ return op_ != kUnknown;
+}
+
+// static
+GpuControlList::ScopedGpuControlListEntry
+GpuControlList::GpuControlListEntry::GetEntryFromValue(
+ const base::DictionaryValue* value, bool top_level,
+ const FeatureMap& feature_map,
+ bool supports_feature_type_all) {
+ DCHECK(value);
+ ScopedGpuControlListEntry entry(new GpuControlListEntry());
+
+ size_t dictionary_entry_count = 0;
+
+ if (top_level) {
+ uint32 id;
+ if (!value->GetInteger("id", reinterpret_cast<int*>(&id)) ||
+ !entry->SetId(id)) {
+ LOG(WARNING) << "Malformed id entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+
+ bool disabled;
+ if (value->GetBoolean("disabled", &disabled)) {
+ entry->SetDisabled(disabled);
+ dictionary_entry_count++;
+ }
+ }
+
+ std::string description;
+ if (value->GetString("description", &description)) {
+ entry->description_ = description;
+ dictionary_entry_count++;
+ } else {
+ entry->description_ = "The GPU is unavailable for an unexplained reason.";
+ }
+
+ const base::ListValue* cr_bugs;
+ if (value->GetList("cr_bugs", &cr_bugs)) {
+ for (size_t i = 0; i < cr_bugs->GetSize(); ++i) {
+ int bug_id;
+ if (cr_bugs->GetInteger(i, &bug_id)) {
+ entry->cr_bugs_.push_back(bug_id);
+ } else {
+ LOG(WARNING) << "Malformed cr_bugs entry " << entry->id();
+ return NULL;
+ }
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::ListValue* webkit_bugs;
+ if (value->GetList("webkit_bugs", &webkit_bugs)) {
+ for (size_t i = 0; i < webkit_bugs->GetSize(); ++i) {
+ int bug_id;
+ if (webkit_bugs->GetInteger(i, &bug_id)) {
+ entry->webkit_bugs_.push_back(bug_id);
+ } else {
+ LOG(WARNING) << "Malformed webkit_bugs entry " << entry->id();
+ return NULL;
+ }
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* os_value = NULL;
+ if (value->GetDictionary("os", &os_value)) {
+ std::string os_type;
+ std::string os_version_op = "any";
+ std::string os_version_string;
+ std::string os_version_string2;
+ os_value->GetString("type", &os_type);
+ const base::DictionaryValue* os_version_value = NULL;
+ if (os_value->GetDictionary("version", &os_version_value)) {
+ os_version_value->GetString(kOp, &os_version_op);
+ os_version_value->GetString("number", &os_version_string);
+ os_version_value->GetString("number2", &os_version_string2);
+ }
+ if (!entry->SetOsInfo(os_type, os_version_op, os_version_string,
+ os_version_string2)) {
+ LOG(WARNING) << "Malformed os entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ std::string vendor_id;
+ if (value->GetString("vendor_id", &vendor_id)) {
+ if (!entry->SetVendorId(vendor_id)) {
+ LOG(WARNING) << "Malformed vendor_id entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::ListValue* device_id_list;
+ if (value->GetList("device_id", &device_id_list)) {
+ for (size_t i = 0; i < device_id_list->GetSize(); ++i) {
+ std::string device_id;
+ if (!device_id_list->GetString(i, &device_id) ||
+ !entry->AddDeviceId(device_id)) {
+ LOG(WARNING) << "Malformed device_id entry " << entry->id();
+ return NULL;
+ }
+ }
+ dictionary_entry_count++;
+ }
+
+ std::string multi_gpu_style;
+ if (value->GetString("multi_gpu_style", &multi_gpu_style)) {
+ if (!entry->SetMultiGpuStyle(multi_gpu_style)) {
+ LOG(WARNING) << "Malformed multi_gpu_style entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ std::string multi_gpu_category;
+ if (value->GetString("multi_gpu_category", &multi_gpu_category)) {
+ if (!entry->SetMultiGpuCategory(multi_gpu_category)) {
+ LOG(WARNING) << "Malformed multi_gpu_category entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* driver_vendor_value = NULL;
+ if (value->GetDictionary("driver_vendor", &driver_vendor_value)) {
+ std::string vendor_op;
+ std::string vendor_value;
+ driver_vendor_value->GetString(kOp, &vendor_op);
+ driver_vendor_value->GetString("value", &vendor_value);
+ if (!entry->SetDriverVendorInfo(vendor_op, vendor_value)) {
+ LOG(WARNING) << "Malformed driver_vendor entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* driver_version_value = NULL;
+ if (value->GetDictionary("driver_version", &driver_version_value)) {
+ std::string driver_version_op = "any";
+ std::string driver_version_style;
+ std::string driver_version_string;
+ std::string driver_version_string2;
+ driver_version_value->GetString(kOp, &driver_version_op);
+ driver_version_value->GetString("style", &driver_version_style);
+ driver_version_value->GetString("number", &driver_version_string);
+ driver_version_value->GetString("number2", &driver_version_string2);
+ if (!entry->SetDriverVersionInfo(driver_version_op,
+ driver_version_style,
+ driver_version_string,
+ driver_version_string2)) {
+ LOG(WARNING) << "Malformed driver_version entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* driver_date_value = NULL;
+ if (value->GetDictionary("driver_date", &driver_date_value)) {
+ std::string driver_date_op = "any";
+ std::string driver_date_string;
+ std::string driver_date_string2;
+ driver_date_value->GetString(kOp, &driver_date_op);
+ driver_date_value->GetString("number", &driver_date_string);
+ driver_date_value->GetString("number2", &driver_date_string2);
+ if (!entry->SetDriverDateInfo(driver_date_op, driver_date_string,
+ driver_date_string2)) {
+ LOG(WARNING) << "Malformed driver_date entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* gl_vendor_value = NULL;
+ if (value->GetDictionary("gl_vendor", &gl_vendor_value)) {
+ std::string vendor_op;
+ std::string vendor_value;
+ gl_vendor_value->GetString(kOp, &vendor_op);
+ gl_vendor_value->GetString("value", &vendor_value);
+ if (!entry->SetGLVendorInfo(vendor_op, vendor_value)) {
+ LOG(WARNING) << "Malformed gl_vendor entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* gl_renderer_value = NULL;
+ if (value->GetDictionary("gl_renderer", &gl_renderer_value)) {
+ std::string renderer_op;
+ std::string renderer_value;
+ gl_renderer_value->GetString(kOp, &renderer_op);
+ gl_renderer_value->GetString("value", &renderer_value);
+ if (!entry->SetGLRendererInfo(renderer_op, renderer_value)) {
+ LOG(WARNING) << "Malformed gl_renderer entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* gl_extensions_value = NULL;
+ if (value->GetDictionary("gl_extensions", &gl_extensions_value)) {
+ std::string extensions_op;
+ std::string extensions_value;
+ gl_extensions_value->GetString(kOp, &extensions_op);
+ gl_extensions_value->GetString("value", &extensions_value);
+ if (!entry->SetGLExtensionsInfo(extensions_op, extensions_value)) {
+ LOG(WARNING) << "Malformed gl_extensions entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* cpu_brand_value = NULL;
+ if (value->GetDictionary("cpu_info", &cpu_brand_value)) {
+ std::string cpu_op;
+ std::string cpu_value;
+ cpu_brand_value->GetString(kOp, &cpu_op);
+ cpu_brand_value->GetString("value", &cpu_value);
+ if (!entry->SetCpuBrand(cpu_op, cpu_value)) {
+ LOG(WARNING) << "Malformed cpu_brand entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* perf_graphics_value = NULL;
+ if (value->GetDictionary("perf_graphics", &perf_graphics_value)) {
+ std::string op;
+ std::string float_value;
+ std::string float_value2;
+ perf_graphics_value->GetString(kOp, &op);
+ perf_graphics_value->GetString("value", &float_value);
+ perf_graphics_value->GetString("value2", &float_value2);
+ if (!entry->SetPerfGraphicsInfo(op, float_value, float_value2)) {
+ LOG(WARNING) << "Malformed perf_graphics entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* perf_gaming_value = NULL;
+ if (value->GetDictionary("perf_gaming", &perf_gaming_value)) {
+ std::string op;
+ std::string float_value;
+ std::string float_value2;
+ perf_gaming_value->GetString(kOp, &op);
+ perf_gaming_value->GetString("value", &float_value);
+ perf_gaming_value->GetString("value2", &float_value2);
+ if (!entry->SetPerfGamingInfo(op, float_value, float_value2)) {
+ LOG(WARNING) << "Malformed perf_gaming entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* perf_overall_value = NULL;
+ if (value->GetDictionary("perf_overall", &perf_overall_value)) {
+ std::string op;
+ std::string float_value;
+ std::string float_value2;
+ perf_overall_value->GetString(kOp, &op);
+ perf_overall_value->GetString("value", &float_value);
+ perf_overall_value->GetString("value2", &float_value2);
+ if (!entry->SetPerfOverallInfo(op, float_value, float_value2)) {
+ LOG(WARNING) << "Malformed perf_overall entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* machine_model_value = NULL;
+ if (value->GetDictionary("machine_model", &machine_model_value)) {
+ std::string name_op;
+ std::string name_value;
+ const base::DictionaryValue* name = NULL;
+ if (machine_model_value->GetDictionary("name", &name)) {
+ name->GetString(kOp, &name_op);
+ name->GetString("value", &name_value);
+ }
+
+ std::string version_op = "any";
+ std::string version_string;
+ std::string version_string2;
+ const base::DictionaryValue* version_value = NULL;
+ if (machine_model_value->GetDictionary("version", &version_value)) {
+ version_value->GetString(kOp, &version_op);
+ version_value->GetString("number", &version_string);
+ version_value->GetString("number2", &version_string2);
+ }
+ if (!entry->SetMachineModelInfo(
+ name_op, name_value, version_op, version_string, version_string2)) {
+ LOG(WARNING) << "Malformed machine_model entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* gpu_count_value = NULL;
+ if (value->GetDictionary("gpu_count", &gpu_count_value)) {
+ std::string op;
+ std::string int_value;
+ std::string int_value2;
+ gpu_count_value->GetString(kOp, &op);
+ gpu_count_value->GetString("value", &int_value);
+ gpu_count_value->GetString("value2", &int_value2);
+ if (!entry->SetGpuCountInfo(op, int_value, int_value2)) {
+ LOG(WARNING) << "Malformed gpu_count entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ if (top_level) {
+ const base::ListValue* feature_value = NULL;
+ if (value->GetList("features", &feature_value)) {
+ std::vector<std::string> feature_list;
+ for (size_t i = 0; i < feature_value->GetSize(); ++i) {
+ std::string feature;
+ if (feature_value->GetString(i, &feature)) {
+ feature_list.push_back(feature);
+ } else {
+ LOG(WARNING) << "Malformed feature entry " << entry->id();
+ return NULL;
+ }
+ }
+ if (!entry->SetFeatures(
+ feature_list, feature_map, supports_feature_type_all)) {
+ LOG(WARNING) << "Malformed feature entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+ }
+
+ if (top_level) {
+ const base::ListValue* exception_list_value = NULL;
+ if (value->GetList("exceptions", &exception_list_value)) {
+ for (size_t i = 0; i < exception_list_value->GetSize(); ++i) {
+ const base::DictionaryValue* exception_value = NULL;
+ if (!exception_list_value->GetDictionary(i, &exception_value)) {
+ LOG(WARNING) << "Malformed exceptions entry " << entry->id();
+ return NULL;
+ }
+ ScopedGpuControlListEntry exception(GetEntryFromValue(
+ exception_value, false, feature_map, supports_feature_type_all));
+ if (exception == NULL) {
+ LOG(WARNING) << "Malformed exceptions entry " << entry->id();
+ return NULL;
+ }
+ if (exception->contains_unknown_fields_) {
+ LOG(WARNING) << "Exception with unknown fields " << entry->id();
+ entry->contains_unknown_fields_ = true;
+ } else {
+ entry->AddException(exception);
+ }
+ }
+ dictionary_entry_count++;
+ }
+
+ const base::DictionaryValue* browser_version_value = NULL;
+ // browser_version is processed in LoadGpuControlList().
+ if (value->GetDictionary("browser_version", &browser_version_value))
+ dictionary_entry_count++;
+ }
+
+ if (value->size() != dictionary_entry_count) {
+ LOG(WARNING) << "Entry with unknown fields " << entry->id();
+ entry->contains_unknown_fields_ = true;
+ }
+ return entry;
+}
+
+GpuControlList::GpuControlListEntry::GpuControlListEntry()
+ : id_(0),
+ disabled_(false),
+ vendor_id_(0),
+ multi_gpu_style_(kMultiGpuStyleNone),
+ multi_gpu_category_(kMultiGpuCategoryPrimary),
+ contains_unknown_fields_(false),
+ contains_unknown_features_(false) {
+}
+
+GpuControlList::GpuControlListEntry::~GpuControlListEntry() { }
+
+bool GpuControlList::GpuControlListEntry::SetId(uint32 id) {
+ if (id != 0) {
+ id_ = id;
+ return true;
+ }
+ return false;
+}
+
+void GpuControlList::GpuControlListEntry::SetDisabled(bool disabled) {
+ disabled_ = disabled;
+}
+
+bool GpuControlList::GpuControlListEntry::SetOsInfo(
+ const std::string& os,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2) {
+ os_info_.reset(new OsInfo(os, version_op, version_string, version_string2));
+ return os_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetVendorId(
+ const std::string& vendor_id_string) {
+ vendor_id_ = 0;
+ return base::HexStringToInt(vendor_id_string,
+ reinterpret_cast<int*>(&vendor_id_));
+}
+
+bool GpuControlList::GpuControlListEntry::AddDeviceId(
+ const std::string& device_id_string) {
+ uint32 device_id = 0;
+ if (base::HexStringToInt(device_id_string,
+ reinterpret_cast<int*>(&device_id))) {
+ device_id_list_.push_back(device_id);
+ return true;
+ }
+ return false;
+}
+
+bool GpuControlList::GpuControlListEntry::SetMultiGpuStyle(
+ const std::string& multi_gpu_style_string) {
+ MultiGpuStyle style = StringToMultiGpuStyle(multi_gpu_style_string);
+ if (style == kMultiGpuStyleNone)
+ return false;
+ multi_gpu_style_ = style;
+ return true;
+}
+
+bool GpuControlList::GpuControlListEntry::SetMultiGpuCategory(
+ const std::string& multi_gpu_category_string) {
+ MultiGpuCategory category =
+ StringToMultiGpuCategory(multi_gpu_category_string);
+ if (category == kMultiGpuCategoryNone)
+ return false;
+ multi_gpu_category_ = category;
+ return true;
+}
+
+bool GpuControlList::GpuControlListEntry::SetDriverVendorInfo(
+ const std::string& vendor_op,
+ const std::string& vendor_value) {
+ driver_vendor_info_.reset(new StringInfo(vendor_op, vendor_value));
+ return driver_vendor_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetDriverVersionInfo(
+ const std::string& version_op,
+ const std::string& version_style,
+ const std::string& version_string,
+ const std::string& version_string2) {
+ driver_version_info_.reset(new VersionInfo(
+ version_op, version_style, version_string, version_string2));
+ return driver_version_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetDriverDateInfo(
+ const std::string& date_op,
+ const std::string& date_string,
+ const std::string& date_string2) {
+ driver_date_info_.reset(
+ new VersionInfo(date_op, std::string(), date_string, date_string2));
+ return driver_date_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetGLVendorInfo(
+ const std::string& vendor_op,
+ const std::string& vendor_value) {
+ gl_vendor_info_.reset(new StringInfo(vendor_op, vendor_value));
+ return gl_vendor_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetGLRendererInfo(
+ const std::string& renderer_op,
+ const std::string& renderer_value) {
+ gl_renderer_info_.reset(new StringInfo(renderer_op, renderer_value));
+ return gl_renderer_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetGLExtensionsInfo(
+ const std::string& extensions_op,
+ const std::string& extensions_value) {
+ gl_extensions_info_.reset(new StringInfo(extensions_op, extensions_value));
+ return gl_extensions_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetCpuBrand(
+ const std::string& cpu_op,
+ const std::string& cpu_value) {
+ cpu_brand_.reset(new StringInfo(cpu_op, cpu_value));
+ return cpu_brand_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetPerfGraphicsInfo(
+ const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2) {
+ perf_graphics_info_.reset(new FloatInfo(op, float_string, float_string2));
+ return perf_graphics_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetPerfGamingInfo(
+ const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2) {
+ perf_gaming_info_.reset(new FloatInfo(op, float_string, float_string2));
+ return perf_gaming_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetPerfOverallInfo(
+ const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2) {
+ perf_overall_info_.reset(new FloatInfo(op, float_string, float_string2));
+ return perf_overall_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetMachineModelInfo(
+ const std::string& name_op,
+ const std::string& name_value,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2) {
+ machine_model_info_.reset(new MachineModelInfo(
+ name_op, name_value, version_op, version_string, version_string2));
+ return machine_model_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetGpuCountInfo(
+ const std::string& op,
+ const std::string& int_string,
+ const std::string& int_string2) {
+ gpu_count_info_.reset(new IntInfo(op, int_string, int_string2));
+ return gpu_count_info_->IsValid();
+}
+
+bool GpuControlList::GpuControlListEntry::SetFeatures(
+ const std::vector<std::string>& feature_strings,
+ const FeatureMap& feature_map,
+ bool supports_feature_type_all) {
+ size_t size = feature_strings.size();
+ if (size == 0)
+ return false;
+ features_.clear();
+ for (size_t i = 0; i < size; ++i) {
+ int feature = 0;
+ if (supports_feature_type_all && feature_strings[i] == "all") {
+ for (FeatureMap::const_iterator iter = feature_map.begin();
+ iter != feature_map.end(); ++iter)
+ features_.insert(iter->second);
+ continue;
+ }
+ if (StringToFeature(feature_strings[i], &feature, feature_map))
+ features_.insert(feature);
+ else
+ contains_unknown_features_ = true;
+ }
+ return true;
+}
+
+void GpuControlList::GpuControlListEntry::AddException(
+ ScopedGpuControlListEntry exception) {
+ exceptions_.push_back(exception);
+}
+
+// static
+GpuControlList::GpuControlListEntry::MultiGpuStyle
+GpuControlList::GpuControlListEntry::StringToMultiGpuStyle(
+ const std::string& style) {
+ if (style == kMultiGpuStyleStringOptimus)
+ return kMultiGpuStyleOptimus;
+ if (style == kMultiGpuStyleStringAMDSwitchable)
+ return kMultiGpuStyleAMDSwitchable;
+ return kMultiGpuStyleNone;
+}
+
+// static
+GpuControlList::GpuControlListEntry::MultiGpuCategory
+GpuControlList::GpuControlListEntry::StringToMultiGpuCategory(
+ const std::string& category) {
+ if (category == kMultiGpuCategoryStringPrimary)
+ return kMultiGpuCategoryPrimary;
+ if (category == kMultiGpuCategoryStringSecondary)
+ return kMultiGpuCategorySecondary;
+ if (category == kMultiGpuCategoryStringAny)
+ return kMultiGpuCategoryAny;
+ return kMultiGpuCategoryNone;
+}
+
+bool GpuControlList::GpuControlListEntry::Contains(
+ OsType os_type, const std::string& os_version,
+ const GPUInfo& gpu_info) const {
+ DCHECK(os_type != kOsAny);
+ if (os_info_.get() != NULL && !os_info_->Contains(os_type, os_version))
+ return false;
+ bool is_not_primary_gpu =
+ GpuUnmatched(vendor_id_, device_id_list_, gpu_info.gpu);
+ bool is_not_secondary_gpu = true;
+ for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) {
+ is_not_secondary_gpu = is_not_secondary_gpu &&
+ GpuUnmatched(vendor_id_, device_id_list_, gpu_info.secondary_gpus[i]);
+ }
+ switch (multi_gpu_category_) {
+ case kMultiGpuCategoryPrimary:
+ if (is_not_primary_gpu)
+ return false;
+ break;
+ case kMultiGpuCategorySecondary:
+ if (is_not_secondary_gpu)
+ return false;
+ break;
+ case kMultiGpuCategoryAny:
+ if (is_not_primary_gpu && is_not_secondary_gpu)
+ return false;
+ break;
+ case kMultiGpuCategoryNone:
+ break;
+ }
+ switch (multi_gpu_style_) {
+ case kMultiGpuStyleOptimus:
+ if (!gpu_info.optimus)
+ return false;
+ break;
+ case kMultiGpuStyleAMDSwitchable:
+ if (!gpu_info.amd_switchable)
+ return false;
+ break;
+ case kMultiGpuStyleNone:
+ break;
+ }
+ if (driver_vendor_info_.get() != NULL && !gpu_info.driver_vendor.empty() &&
+ !driver_vendor_info_->Contains(gpu_info.driver_vendor))
+ return false;
+ if (driver_version_info_.get() != NULL && !gpu_info.driver_version.empty()) {
+ if (!driver_version_info_->Contains(gpu_info.driver_version))
+ return false;
+ }
+ if (driver_date_info_.get() != NULL && !gpu_info.driver_date.empty()) {
+ if (!driver_date_info_->Contains(gpu_info.driver_date, '-'))
+ return false;
+ }
+ if (gl_vendor_info_.get() != NULL && !gpu_info.gl_vendor.empty() &&
+ !gl_vendor_info_->Contains(gpu_info.gl_vendor))
+ return false;
+ if (gl_renderer_info_.get() != NULL && !gpu_info.gl_renderer.empty() &&
+ !gl_renderer_info_->Contains(gpu_info.gl_renderer))
+ return false;
+ if (gl_extensions_info_.get() != NULL && !gpu_info.gl_extensions.empty() &&
+ !gl_extensions_info_->Contains(gpu_info.gl_extensions))
+ return false;
+ if (perf_graphics_info_.get() != NULL &&
+ (gpu_info.performance_stats.graphics == 0.0 ||
+ !perf_graphics_info_->Contains(gpu_info.performance_stats.graphics)))
+ return false;
+ if (perf_gaming_info_.get() != NULL &&
+ (gpu_info.performance_stats.gaming == 0.0 ||
+ !perf_gaming_info_->Contains(gpu_info.performance_stats.gaming)))
+ return false;
+ if (perf_overall_info_.get() != NULL &&
+ (gpu_info.performance_stats.overall == 0.0 ||
+ !perf_overall_info_->Contains(gpu_info.performance_stats.overall)))
+ return false;
+ if (machine_model_info_.get() != NULL) {
+ std::vector<std::string> name_version;
+ base::SplitString(gpu_info.machine_model, ' ', &name_version);
+ if (name_version.size() == 2 &&
+ !machine_model_info_->Contains(name_version[0], name_version[1]))
+ return false;
+ }
+ if (gpu_count_info_.get() != NULL &&
+ !gpu_count_info_->Contains(gpu_info.secondary_gpus.size() + 1))
+ return false;
+ if (cpu_brand_.get() != NULL) {
+ base::CPU cpu_info;
+ if (!cpu_brand_->Contains(cpu_info.cpu_brand()))
+ return false;
+ }
+
+ for (size_t i = 0; i < exceptions_.size(); ++i) {
+ if (exceptions_[i]->Contains(os_type, os_version, gpu_info) &&
+ !exceptions_[i]->NeedsMoreInfo(gpu_info))
+ return false;
+ }
+ return true;
+}
+
+bool GpuControlList::GpuControlListEntry::NeedsMoreInfo(
+ const GPUInfo& gpu_info) const {
+ // We only check for missing info that might be collected with a gl context.
+ // If certain info is missing due to some error, say, we fail to collect
+ // vendor_id/device_id, then even if we launch GPU process and create a gl
+ // context, we won't gather such missing info, so we still return false.
+ if (driver_vendor_info_.get() && gpu_info.driver_vendor.empty())
+ return true;
+ if (driver_version_info_.get() && gpu_info.driver_version.empty())
+ return true;
+ if (gl_vendor_info_.get() && gpu_info.gl_vendor.empty())
+ return true;
+ if (gl_renderer_info_.get() && gpu_info.gl_renderer.empty())
+ return true;
+ for (size_t i = 0; i < exceptions_.size(); ++i) {
+ if (exceptions_[i]->NeedsMoreInfo(gpu_info))
+ return true;
+ }
+ return false;
+}
+
+GpuControlList::OsType GpuControlList::GpuControlListEntry::GetOsType() const {
+ if (os_info_.get() == NULL)
+ return kOsAny;
+ return os_info_->type();
+}
+
+uint32 GpuControlList::GpuControlListEntry::id() const {
+ return id_;
+}
+
+bool GpuControlList::GpuControlListEntry::disabled() const {
+ return disabled_;
+}
+
+const std::set<int>& GpuControlList::GpuControlListEntry::features() const {
+ return features_;
+}
+
+// static
+bool GpuControlList::GpuControlListEntry::StringToFeature(
+ const std::string& feature_name, int* feature_id,
+ const FeatureMap& feature_map) {
+ FeatureMap::const_iterator iter = feature_map.find(feature_name);
+ if (iter != feature_map.end()) {
+ *feature_id = iter->second;
+ return true;
+ }
+ return false;
+}
+
+GpuControlList::GpuControlList()
+ : max_entry_id_(0),
+ contains_unknown_fields_(false),
+ needs_more_info_(false),
+ supports_feature_type_all_(false) {
+}
+
+GpuControlList::~GpuControlList() {
+ Clear();
+}
+
+bool GpuControlList::LoadList(
+ const std::string& json_context, GpuControlList::OsFilter os_filter) {
+ const std::string browser_version_string = "0";
+ return LoadList(browser_version_string, json_context, os_filter);
+}
+
+bool GpuControlList::LoadList(
+ const std::string& browser_version_string,
+ const std::string& json_context,
+ GpuControlList::OsFilter os_filter) {
+ std::vector<std::string> pieces;
+ if (!ProcessVersionString(browser_version_string, '.', &pieces))
+ return false;
+ browser_version_ = browser_version_string;
+
+ scoped_ptr<base::Value> root;
+ root.reset(base::JSONReader::Read(json_context));
+ if (root.get() == NULL || !root->IsType(base::Value::TYPE_DICTIONARY))
+ return false;
+
+ base::DictionaryValue* root_dictionary =
+ static_cast<DictionaryValue*>(root.get());
+ DCHECK(root_dictionary);
+ return LoadList(*root_dictionary, os_filter);
+}
+
+bool GpuControlList::LoadList(const base::DictionaryValue& parsed_json,
+ GpuControlList::OsFilter os_filter) {
+ std::vector<ScopedGpuControlListEntry> entries;
+
+ parsed_json.GetString("version", &version_);
+ std::vector<std::string> pieces;
+ if (!ProcessVersionString(version_, '.', &pieces))
+ return false;
+
+ const base::ListValue* list = NULL;
+ if (!parsed_json.GetList("entries", &list))
+ return false;
+
+ uint32 max_entry_id = 0;
+ bool contains_unknown_fields = false;
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ const base::DictionaryValue* list_item = NULL;
+ bool valid = list->GetDictionary(i, &list_item);
+ if (!valid || list_item == NULL)
+ return false;
+ // Check browser version compatibility: if the entry is not for the
+ // current browser version, don't process it.
+ BrowserVersionSupport browser_version_support =
+ IsEntrySupportedByCurrentBrowserVersion(list_item);
+ if (browser_version_support == kMalformed)
+ return false;
+ if (browser_version_support == kUnsupported)
+ continue;
+ DCHECK(browser_version_support == kSupported);
+ ScopedGpuControlListEntry entry(GpuControlListEntry::GetEntryFromValue(
+ list_item, true, feature_map_, supports_feature_type_all_));
+ if (entry == NULL)
+ return false;
+ if (entry->id() > max_entry_id)
+ max_entry_id = entry->id();
+ // If an unknown field is encountered, skip the entry; if an unknown
+ // feature is encountered, ignore the feature, but keep the entry.
+ if (entry->contains_unknown_fields()) {
+ contains_unknown_fields = true;
+ continue;
+ }
+ if (entry->contains_unknown_features())
+ contains_unknown_fields = true;
+ entries.push_back(entry);
+ }
+
+ Clear();
+ OsType my_os = GetOsType();
+ for (size_t i = 0; i < entries.size(); ++i) {
+ OsType entry_os = entries[i]->GetOsType();
+ if (os_filter == GpuControlList::kAllOs ||
+ entry_os == kOsAny || entry_os == my_os)
+ entries_.push_back(entries[i]);
+ }
+ max_entry_id_ = max_entry_id;
+ contains_unknown_fields_ = contains_unknown_fields;
+ return true;
+}
+
+std::set<int> GpuControlList::MakeDecision(
+ GpuControlList::OsType os,
+ std::string os_version,
+ const GPUInfo& gpu_info) {
+ active_entries_.clear();
+ std::set<int> features;
+
+ needs_more_info_ = false;
+ std::set<int> possible_features;
+
+ if (os == kOsAny)
+ os = GetOsType();
+ if (os_version.empty()) {
+ os_version = base::SysInfo::OperatingSystemVersion();
+ size_t pos = os_version.find_first_not_of("0123456789.");
+ if (pos != std::string::npos)
+ os_version = os_version.substr(0, pos);
+ }
+ std::vector<std::string> pieces;
+ if (!ProcessVersionString(os_version, '.', &pieces))
+ os_version = "0";
+
+ for (size_t i = 0; i < entries_.size(); ++i) {
+ if (entries_[i]->Contains(os, os_version, gpu_info)) {
+ if (!entries_[i]->disabled()) {
+ MergeFeatureSets(&possible_features, entries_[i]->features());
+ if (!entries_[i]->NeedsMoreInfo(gpu_info))
+ MergeFeatureSets(&features, entries_[i]->features());
+ }
+ active_entries_.push_back(entries_[i]);
+ }
+ }
+
+ if (possible_features.size() > features.size())
+ needs_more_info_ = true;
+
+ return features;
+}
+
+void GpuControlList::GetDecisionEntries(
+ std::vector<uint32>* entry_ids, bool disabled) const {
+ DCHECK(entry_ids);
+ entry_ids->clear();
+ for (size_t i = 0; i < active_entries_.size(); ++i) {
+ if (disabled == active_entries_[i]->disabled())
+ entry_ids->push_back(active_entries_[i]->id());
+ }
+}
+
+void GpuControlList::GetReasons(base::ListValue* problem_list) const {
+ DCHECK(problem_list);
+ for (size_t i = 0; i < active_entries_.size(); ++i) {
+ GpuControlListEntry* entry = active_entries_[i];
+ if (entry->disabled())
+ continue;
+ base::DictionaryValue* problem = new base::DictionaryValue();
+
+ problem->SetString("description", entry->description());
+
+ base::ListValue* cr_bugs = new base::ListValue();
+ for (size_t j = 0; j < entry->cr_bugs().size(); ++j)
+ cr_bugs->Append(new base::FundamentalValue(entry->cr_bugs()[j]));
+ problem->Set("crBugs", cr_bugs);
+
+ base::ListValue* webkit_bugs = new base::ListValue();
+ for (size_t j = 0; j < entry->webkit_bugs().size(); ++j) {
+ webkit_bugs->Append(new base::FundamentalValue(entry->webkit_bugs()[j]));
+ }
+ problem->Set("webkitBugs", webkit_bugs);
+
+ problem_list->Append(problem);
+ }
+}
+
+size_t GpuControlList::num_entries() const {
+ return entries_.size();
+}
+
+uint32 GpuControlList::max_entry_id() const {
+ return max_entry_id_;
+}
+
+std::string GpuControlList::version() const {
+ return version_;
+}
+
+GpuControlList::OsType GpuControlList::GetOsType() {
+#if defined(OS_CHROMEOS)
+ return kOsChromeOS;
+#elif defined(OS_WIN)
+ return kOsWin;
+#elif defined(OS_ANDROID)
+ return kOsAndroid;
+#elif defined(OS_LINUX) || defined(OS_OPENBSD)
+ return kOsLinux;
+#elif defined(OS_MACOSX)
+ return kOsMacosx;
+#else
+ return kOsUnknown;
+#endif
+}
+
+void GpuControlList::Clear() {
+ entries_.clear();
+ active_entries_.clear();
+ max_entry_id_ = 0;
+ contains_unknown_fields_ = false;
+}
+
+GpuControlList::BrowserVersionSupport
+GpuControlList::IsEntrySupportedByCurrentBrowserVersion(
+ const base::DictionaryValue* value) {
+ DCHECK(value);
+ const base::DictionaryValue* browser_version_value = NULL;
+ if (value->GetDictionary("browser_version", &browser_version_value)) {
+ std::string version_op = "any";
+ std::string version_string;
+ std::string version_string2;
+ browser_version_value->GetString(kOp, &version_op);
+ browser_version_value->GetString("number", &version_string);
+ browser_version_value->GetString("number2", &version_string2);
+ scoped_ptr<VersionInfo> browser_version_info;
+ browser_version_info.reset(new VersionInfo(
+ version_op, std::string(), version_string, version_string2));
+ if (!browser_version_info->IsValid())
+ return kMalformed;
+ if (browser_version_info->Contains(browser_version_))
+ return kSupported;
+ return kUnsupported;
+ }
+ return kSupported;
+}
+
+// static
+GpuControlList::NumericOp GpuControlList::StringToNumericOp(
+ const std::string& op) {
+ if (op == "=")
+ return kEQ;
+ if (op == "<")
+ return kLT;
+ if (op == "<=")
+ return kLE;
+ if (op == ">")
+ return kGT;
+ if (op == ">=")
+ return kGE;
+ if (op == "any")
+ return kAny;
+ if (op == "between")
+ return kBetween;
+ return kUnknown;
+}
+
+void GpuControlList::AddSupportedFeature(
+ const std::string& feature_name, int feature_id) {
+ feature_map_[feature_name] = feature_id;
+}
+
+void GpuControlList::set_supports_feature_type_all(bool supported) {
+ supports_feature_type_all_ = supported;
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_control_list.h b/gpu/config/gpu_control_list.h
new file mode 100644
index 0000000..eaf7024
--- /dev/null
+++ b/gpu/config/gpu_control_list.h
@@ -0,0 +1,498 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_CONTROL_LIST_H_
+#define GPU_CONFIG_GPU_CONTROL_LIST_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/hash_tables.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+struct GPUInfo;
+
+class GPU_EXPORT GpuControlList {
+ public:
+ enum OsType {
+ kOsLinux,
+ kOsMacosx,
+ kOsWin,
+ kOsChromeOS,
+ kOsAndroid,
+ kOsAny,
+ kOsUnknown
+ };
+
+ enum OsFilter {
+ // In loading, ignore all entries that belong to other OS.
+ kCurrentOsOnly,
+ // In loading, keep all entries. This is for testing only.
+ kAllOs
+ };
+
+ GpuControlList();
+ virtual ~GpuControlList();
+
+ // Loads control list information from a json file.
+ // If failed, the current GpuControlList is un-touched.
+ bool LoadList(const std::string& json_context, OsFilter os_filter);
+ bool LoadList(const std::string& browser_version_string,
+ const std::string& json_context, OsFilter os_filter);
+
+ // Collects system information and combines them with gpu_info and control
+ // list information to decide which entries are applied to the current
+ // system and returns the union of features specified in each entry.
+ // If os is kOsAny, use the current OS; if os_version is empty, use the
+ // current OS version.
+ std::set<int> MakeDecision(
+ OsType os, std::string os_version, const GPUInfo& gpu_info);
+
+ // Collects the active entries from the last MakeDecision() call.
+ // If disabled set to true, return entries that are disabled; otherwise,
+ // return enabled entries.
+ void GetDecisionEntries(std::vector<uint32>* entry_ids,
+ bool disabled) const;
+
+ // Returns the description and bugs from active entries from the last
+ // MakeDecision() call.
+ //
+ // Each problems has:
+ // {
+ // "description": "Your GPU is too old",
+ // "crBugs": [1234],
+ // "webkitBugs": []
+ // }
+ void GetReasons(base::ListValue* problem_list) const;
+
+ // Return the largest entry id. This is used for histogramming.
+ uint32 max_entry_id() const;
+
+ // Returns the version of the control list.
+ std::string version() const;
+
+ // Check if we need more gpu info to make the decisions.
+ // This is computed from the last MakeDecision() call.
+ // If yes, we should create a gl context and do a full gpu info collection.
+ bool needs_more_info() const { return needs_more_info_; }
+
+ // Check if any entries contain unknown fields. This is only for tests.
+ bool contains_unknown_fields() const { return contains_unknown_fields_; }
+
+ // Returns the number of entries. This is only for tests.
+ size_t num_entries() const;
+
+ // Register a feature to FeatureMap - used to construct a GpuControlList.
+ void AddSupportedFeature(const std::string& feature_name, int feature_id);
+ // Register whether "all" is recognized as all features.
+ void set_supports_feature_type_all(bool supported);
+
+ private:
+ friend class GpuControlListEntryTest;
+ friend class MachineModelInfoTest;
+ friend class NumberInfoTest;
+ friend class OsInfoTest;
+ friend class StringInfoTest;
+ friend class VersionInfoTest;
+
+ enum BrowserVersionSupport {
+ kSupported,
+ kUnsupported,
+ kMalformed
+ };
+
+ enum NumericOp {
+ kBetween, // <= * <=
+ kEQ, // =
+ kLT, // <
+ kLE, // <=
+ kGT, // >
+ kGE, // >=
+ kAny,
+ kUnknown // Indicates the data is invalid.
+ };
+
+ class GPU_EXPORT VersionInfo {
+ public:
+ // If version_style is empty, it defaults to kNumerical.
+ VersionInfo(const std::string& version_op,
+ const std::string& version_style,
+ const std::string& version_string,
+ const std::string& version_string2);
+ ~VersionInfo();
+
+ // Determines if a given version is included in the VersionInfo range.
+ // "splitter" divides version string into segments.
+ bool Contains(const std::string& version, char splitter) const;
+ // Same as above, using '.' as splitter.
+ bool Contains(const std::string& version) const;
+
+ // Determine if the version_style is lexical.
+ bool IsLexical() const;
+
+ // Determines if the VersionInfo contains valid information.
+ bool IsValid() const;
+
+ private:
+ enum VersionStyle {
+ kVersionStyleNumerical,
+ kVersionStyleLexical,
+ kVersionStyleUnknown
+ };
+
+ static VersionStyle StringToVersionStyle(const std::string& version_style);
+
+ // Compare two version strings.
+ // Return 1 if version > version_ref,
+ // 0 if version = version_ref,
+ // -1 if version < version_ref.
+ // Note that we only compare as many segments as both versions contain.
+ // For example: Compare("10.3.1", "10.3") returns 0,
+ // Compare("10.3", "10.3.1") returns 0.
+ // If "version_style" is Lexical, the first segment is compared
+ // numerically, all other segments are compared lexically.
+ // Lexical is used for AMD Linux driver versions only.
+ static int Compare(const std::vector<std::string>& version,
+ const std::vector<std::string>& version_ref,
+ VersionStyle version_style);
+
+ NumericOp op_;
+ VersionStyle version_style_;
+ std::vector<std::string> version_;
+ std::vector<std::string> version2_;
+ };
+
+ class GPU_EXPORT OsInfo {
+ public:
+ OsInfo(const std::string& os,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2);
+ ~OsInfo();
+
+ // Determines if a given os/version is included in the OsInfo set.
+ bool Contains(OsType type, const std::string& version) const;
+
+ // Determines if the VersionInfo contains valid information.
+ bool IsValid() const;
+
+ OsType type() const;
+
+ // Maps string to OsType; returns kOsUnknown if it's not a valid os.
+ static OsType StringToOsType(const std::string& os);
+
+ private:
+ OsType type_;
+ scoped_ptr<VersionInfo> version_info_;
+ };
+
+ class GPU_EXPORT StringInfo {
+ public:
+ StringInfo(const std::string& string_op, const std::string& string_value);
+
+ // Determines if a given string is included in the StringInfo.
+ bool Contains(const std::string& value) const;
+
+ // Determines if the StringInfo contains valid information.
+ bool IsValid() const;
+
+ private:
+ enum Op {
+ kContains,
+ kBeginWith,
+ kEndWith,
+ kEQ, // =
+ kUnknown // Indicates StringInfo data is invalid.
+ };
+
+ // Maps string to Op; returns kUnknown if it's not a valid Op.
+ static Op StringToOp(const std::string& string_op);
+
+ Op op_;
+ std::string value_;
+ };
+
+ class GPU_EXPORT FloatInfo {
+ public:
+ FloatInfo(const std::string& float_op,
+ const std::string& float_value,
+ const std::string& float_value2);
+
+ // Determines if a given float is included in the FloatInfo.
+ bool Contains(float value) const;
+
+ // Determines if the FloatInfo contains valid information.
+ bool IsValid() const;
+
+ private:
+ NumericOp op_;
+ float value_;
+ float value2_;
+ };
+
+ class GPU_EXPORT IntInfo {
+ public:
+ IntInfo(const std::string& int_op,
+ const std::string& int_value,
+ const std::string& int_value2);
+
+ // Determines if a given int is included in the IntInfo.
+ bool Contains(int value) const;
+
+ // Determines if the IntInfo contains valid information.
+ bool IsValid() const;
+
+ private:
+ NumericOp op_;
+ int value_;
+ int value2_;
+ };
+
+ class GPU_EXPORT MachineModelInfo {
+ public:
+ MachineModelInfo(const std::string& name_op,
+ const std::string& name_value,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2);
+ ~MachineModelInfo();
+
+ // Determines if a given name/version is included in the MachineModelInfo.
+ bool Contains(const std::string& name, const std::string& version) const;
+
+ // Determines if the MachineModelInfo contains valid information.
+ bool IsValid() const;
+
+ private:
+ scoped_ptr<StringInfo> name_info_;
+ scoped_ptr<VersionInfo> version_info_;
+ };
+
+ class GpuControlListEntry;
+ typedef scoped_refptr<GpuControlListEntry> ScopedGpuControlListEntry;
+
+ typedef base::hash_map<std::string, int> FeatureMap;
+
+ class GPU_EXPORT GpuControlListEntry
+ : public base::RefCounted<GpuControlListEntry> {
+ public:
+ // Constructs GpuControlListEntry from DictionaryValue loaded from json.
+ // Top-level entry must have an id number. Others are exceptions.
+ static ScopedGpuControlListEntry GetEntryFromValue(
+ const base::DictionaryValue* value, bool top_level,
+ const FeatureMap& feature_map,
+ bool supports_feature_type_all);
+
+ // Determines if a given os/gc/machine_model/driver is included in the
+ // Entry set.
+ bool Contains(OsType os_type, const std::string& os_version,
+ const GPUInfo& gpu_info) const;
+
+ // Determines whether we needs more gpu info to make the blacklisting
+ // decision. It should only be checked if Contains() returns true.
+ bool NeedsMoreInfo(const GPUInfo& gpu_info) const;
+
+ // Returns the OsType.
+ OsType GetOsType() const;
+
+ // Returns the entry's unique id. 0 is reserved.
+ uint32 id() const;
+
+ // Returns whether the entry is disabled.
+ bool disabled() const;
+
+ // Returns the description of the entry
+ const std::string& description() const { return description_; }
+
+ // Returns a list of Chromium and Webkit bugs applicable to this entry
+ const std::vector<int>& cr_bugs() const { return cr_bugs_; }
+ const std::vector<int>& webkit_bugs() const { return webkit_bugs_; }
+
+ // Returns the blacklisted features in this entry.
+ const std::set<int>& features() const;
+
+ // Returns true if an unknown field is encountered.
+ bool contains_unknown_fields() const {
+ return contains_unknown_fields_;
+ }
+ // Returns true if an unknown blacklist feature is encountered.
+ bool contains_unknown_features() const {
+ return contains_unknown_features_;
+ }
+
+ private:
+ friend class base::RefCounted<GpuControlListEntry>;
+
+ enum MultiGpuStyle {
+ kMultiGpuStyleOptimus,
+ kMultiGpuStyleAMDSwitchable,
+ kMultiGpuStyleNone
+ };
+
+ enum MultiGpuCategory {
+ kMultiGpuCategoryPrimary,
+ kMultiGpuCategorySecondary,
+ kMultiGpuCategoryAny,
+ kMultiGpuCategoryNone
+ };
+
+ GpuControlListEntry();
+ ~GpuControlListEntry();
+
+ bool SetId(uint32 id);
+
+ void SetDisabled(bool disabled);
+
+ bool SetOsInfo(const std::string& os,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2);
+
+ bool SetVendorId(const std::string& vendor_id_string);
+
+ bool AddDeviceId(const std::string& device_id_string);
+
+ bool SetMultiGpuStyle(const std::string& multi_gpu_style_string);
+
+ bool SetMultiGpuCategory(const std::string& multi_gpu_category_string);
+
+ bool SetDriverVendorInfo(const std::string& vendor_op,
+ const std::string& vendor_value);
+
+ bool SetDriverVersionInfo(const std::string& version_op,
+ const std::string& version_style,
+ const std::string& version_string,
+ const std::string& version_string2);
+
+ bool SetDriverDateInfo(const std::string& date_op,
+ const std::string& date_string,
+ const std::string& date_string2);
+
+ bool SetGLVendorInfo(const std::string& vendor_op,
+ const std::string& vendor_value);
+
+ bool SetGLRendererInfo(const std::string& renderer_op,
+ const std::string& renderer_value);
+
+ bool SetGLExtensionsInfo(const std::string& extensions_op,
+ const std::string& extensions_value);
+
+ bool SetCpuBrand(const std::string& cpu_op,
+ const std::string& cpu_value);
+
+ bool SetPerfGraphicsInfo(const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2);
+
+ bool SetPerfGamingInfo(const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2);
+
+ bool SetPerfOverallInfo(const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2);
+
+ bool SetMachineModelInfo(const std::string& name_op,
+ const std::string& name_value,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2);
+
+ bool SetGpuCountInfo(const std::string& op,
+ const std::string& int_string,
+ const std::string& int_string2);
+
+ bool SetFeatures(const std::vector<std::string>& features,
+ const FeatureMap& feature_map,
+ bool supports_feature_type_all);
+
+ void AddException(ScopedGpuControlListEntry exception);
+
+ static MultiGpuStyle StringToMultiGpuStyle(const std::string& style);
+
+ static MultiGpuCategory StringToMultiGpuCategory(
+ const std::string& category);
+
+ // map a feature_name to feature_id. If the string is not a registered
+ // feature name, return false.
+ static bool StringToFeature(const std::string& feature_name,
+ int* feature_id,
+ const FeatureMap& feature_map);
+
+ uint32 id_;
+ bool disabled_;
+ std::string description_;
+ std::vector<int> cr_bugs_;
+ std::vector<int> webkit_bugs_;
+ scoped_ptr<OsInfo> os_info_;
+ uint32 vendor_id_;
+ std::vector<uint32> device_id_list_;
+ MultiGpuStyle multi_gpu_style_;
+ MultiGpuCategory multi_gpu_category_;
+ scoped_ptr<StringInfo> driver_vendor_info_;
+ scoped_ptr<VersionInfo> driver_version_info_;
+ scoped_ptr<VersionInfo> driver_date_info_;
+ scoped_ptr<StringInfo> gl_vendor_info_;
+ scoped_ptr<StringInfo> gl_renderer_info_;
+ scoped_ptr<StringInfo> gl_extensions_info_;
+ scoped_ptr<StringInfo> cpu_brand_;
+ scoped_ptr<FloatInfo> perf_graphics_info_;
+ scoped_ptr<FloatInfo> perf_gaming_info_;
+ scoped_ptr<FloatInfo> perf_overall_info_;
+ scoped_ptr<MachineModelInfo> machine_model_info_;
+ scoped_ptr<IntInfo> gpu_count_info_;
+ std::set<int> features_;
+ std::vector<ScopedGpuControlListEntry> exceptions_;
+ bool contains_unknown_fields_;
+ bool contains_unknown_features_;
+ };
+
+ // Gets the current OS type.
+ static OsType GetOsType();
+
+ bool LoadList(const base::DictionaryValue& parsed_json, OsFilter os_filter);
+
+ void Clear();
+
+ // Check if the entry is supported by the current version of browser.
+ // By default, if there is no browser version information in the entry,
+ // return kSupported;
+ BrowserVersionSupport IsEntrySupportedByCurrentBrowserVersion(
+ const base::DictionaryValue* value);
+
+ static NumericOp StringToNumericOp(const std::string& op);
+
+ std::string version_;
+ std::vector<ScopedGpuControlListEntry> entries_;
+
+ std::string browser_version_;
+
+ // This records all the blacklist entries that are appliable to the current
+ // user machine. It is updated everytime MakeDecision() is called and is
+ // used later by GetDecisionEntries().
+ std::vector<ScopedGpuControlListEntry> active_entries_;
+
+ uint32 max_entry_id_;
+
+ bool contains_unknown_fields_;
+
+ bool needs_more_info_;
+
+ // The features a GpuControlList recognizes and handles.
+ FeatureMap feature_map_;
+ bool supports_feature_type_all_;
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_CONTROL_LIST_H_
+
diff --git a/gpu/config/gpu_control_list_entry_unittest.cc b/gpu/config/gpu_control_list_entry_unittest.cc
new file mode 100644
index 0000000..b4505bc
--- /dev/null
+++ b/gpu/config/gpu_control_list_entry_unittest.cc
@@ -0,0 +1,748 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/json/json_reader.h"
+#include "gpu/config/gpu_control_list.h"
+#include "gpu/config/gpu_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#define LONG_STRING_CONST(...) #__VA_ARGS__
+
+namespace gpu {
+
+enum TestFeatureType {
+ TEST_FEATURE_0 = 0,
+ TEST_FEATURE_1,
+ TEST_FEATURE_2
+};
+
+class GpuControlListEntryTest : public testing::Test {
+ public:
+ GpuControlListEntryTest() { }
+ virtual ~GpuControlListEntryTest() { }
+
+ const GPUInfo& gpu_info() const {
+ return gpu_info_;
+ }
+
+ typedef GpuControlList::ScopedGpuControlListEntry ScopedEntry;
+
+ static ScopedEntry GetEntryFromString(
+ const std::string& json, bool supports_feature_type_all) {
+ scoped_ptr<base::Value> root;
+ root.reset(base::JSONReader::Read(json));
+ DictionaryValue* value = NULL;
+ if (root.get() == NULL || !root->GetAsDictionary(&value))
+ return NULL;
+
+ GpuControlList::FeatureMap feature_map;
+ feature_map["test_feature_0"] = TEST_FEATURE_0;
+ feature_map["test_feature_1"] = TEST_FEATURE_1;
+ feature_map["test_feature_2"] = TEST_FEATURE_2;
+
+ return GpuControlList::GpuControlListEntry::GetEntryFromValue(
+ value, true, feature_map, supports_feature_type_all);
+ }
+
+ static ScopedEntry GetEntryFromString(const std::string& json) {
+ return GetEntryFromString(json, false);
+ }
+
+ virtual void SetUp() {
+ gpu_info_.gpu.vendor_id = 0x10de;
+ gpu_info_.gpu.device_id = 0x0640;
+ gpu_info_.driver_vendor = "NVIDIA";
+ gpu_info_.driver_version = "1.6.18";
+ gpu_info_.driver_date = "7-14-2009";
+ gpu_info_.machine_model = "MacBookPro 7.1";
+ gpu_info_.gl_vendor = "NVIDIA Corporation";
+ gpu_info_.gl_renderer = "NVIDIA GeForce GT 120 OpenGL Engine";
+ gpu_info_.performance_stats.graphics = 5.0;
+ gpu_info_.performance_stats.gaming = 5.0;
+ gpu_info_.performance_stats.overall = 5.0;
+ }
+
+ private:
+ GPUInfo gpu_info_;
+};
+
+TEST_F(GpuControlListEntryTest, DetailedEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 5,
+ "description": "test entry",
+ "cr_bugs": [1024, 678],
+ "webkit_bugs": [1950],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "=",
+ "number": "10.6.4"
+ }
+ },
+ "vendor_id": "0x10de",
+ "device_id": ["0x0640"],
+ "driver_version": {
+ "op": "=",
+ "number": "1.6.18"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsMacosx, entry->GetOsType());
+ EXPECT_FALSE(entry->disabled());
+ EXPECT_EQ(5u, entry->id());
+ EXPECT_STREQ("test entry", entry->description().c_str());
+ EXPECT_EQ(2u, entry->cr_bugs().size());
+ EXPECT_EQ(1024, entry->cr_bugs()[0]);
+ EXPECT_EQ(678, entry->cr_bugs()[1]);
+ EXPECT_EQ(1u, entry->webkit_bugs().size());
+ EXPECT_EQ(1950, entry->webkit_bugs()[0]);
+ EXPECT_EQ(1u, entry->features().size());
+ EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_0));
+ EXPECT_FALSE(entry->contains_unknown_fields());
+ EXPECT_FALSE(entry->contains_unknown_features());
+ EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info()));
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsMacosx, "10.6.4", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, VendorOnAllOsEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "vendor_id": "0x10de",
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsAny, entry->GetOsType());
+
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsMacosx,
+ GpuControlList::kOsWin,
+ GpuControlList::kOsLinux,
+ GpuControlList::kOsChromeOS,
+ GpuControlList::kOsAndroid
+ };
+ for (size_t i = 0; i < arraysize(os_type); ++i)
+ EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, VendorOnLinuxEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x10de",
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsLinux, entry->GetOsType());
+
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsMacosx,
+ GpuControlList::kOsWin,
+ GpuControlList::kOsChromeOS,
+ GpuControlList::kOsAndroid
+ };
+ for (size_t i = 0; i < arraysize(os_type); ++i)
+ EXPECT_FALSE(entry->Contains(os_type[i], "10.6", gpu_info()));
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsLinux, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, AllExceptNVidiaOnLinuxEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "os": {
+ "type": "linux"
+ },
+ "exceptions": [
+ {
+ "vendor_id": "0x10de"
+ }
+ ],
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsLinux, entry->GetOsType());
+
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsMacosx,
+ GpuControlList::kOsWin,
+ GpuControlList::kOsLinux,
+ GpuControlList::kOsChromeOS,
+ GpuControlList::kOsAndroid
+ };
+ for (size_t i = 0; i < arraysize(os_type); ++i)
+ EXPECT_FALSE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, AllExceptIntelOnLinuxEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "os": {
+ "type": "linux"
+ },
+ "exceptions": [
+ {
+ "vendor_id": "0x8086"
+ }
+ ],
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsLinux, entry->GetOsType());
+
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsMacosx,
+ GpuControlList::kOsWin,
+ GpuControlList::kOsChromeOS,
+ GpuControlList::kOsAndroid
+ };
+ for (size_t i = 0; i < arraysize(os_type); ++i)
+ EXPECT_FALSE(entry->Contains(os_type[i], "10.6", gpu_info()));
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsLinux, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, DateOnWindowsEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "os": {
+ "type": "win"
+ },
+ "driver_date": {
+ "op": "<",
+ "number": "2010.5.8"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsWin, entry->GetOsType());
+
+ GPUInfo gpu_info;
+ gpu_info.driver_date = "4-12-2010";
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsWin, "10.6", gpu_info));
+ gpu_info.driver_date = "5-8-2010";
+ EXPECT_FALSE(entry->Contains(
+ GpuControlList::kOsWin, "10.6", gpu_info));
+ gpu_info.driver_date = "5-9-2010";
+ EXPECT_FALSE(entry->Contains(
+ GpuControlList::kOsWin, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, MultipleDevicesEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "vendor_id": "0x10de",
+ "device_id": ["0x1023", "0x0640"],
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsAny, entry->GetOsType());
+
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsMacosx,
+ GpuControlList::kOsWin,
+ GpuControlList::kOsLinux,
+ GpuControlList::kOsChromeOS,
+ GpuControlList::kOsAndroid
+ };
+ for (size_t i = 0; i < arraysize(os_type); ++i)
+ EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, ChromeOSEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "os": {
+ "type": "chromeos"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsChromeOS, entry->GetOsType());
+
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsMacosx,
+ GpuControlList::kOsWin,
+ GpuControlList::kOsLinux,
+ GpuControlList::kOsAndroid
+ };
+ for (size_t i = 0; i < arraysize(os_type); ++i)
+ EXPECT_FALSE(entry->Contains(os_type[i], "10.6", gpu_info()));
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsChromeOS, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, MalformedVendor) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "vendor_id": "[0x10de]",
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry == NULL);
+}
+
+TEST_F(GpuControlListEntryTest, UnknownFieldEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "unknown_field": 0,
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_TRUE(entry->contains_unknown_fields());
+ EXPECT_FALSE(entry->contains_unknown_features());
+}
+
+TEST_F(GpuControlListEntryTest, UnknownExceptionFieldEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 2,
+ "exceptions": [
+ {
+ "unknown_field": 0
+ }
+ ],
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_TRUE(entry->contains_unknown_fields());
+ EXPECT_FALSE(entry->contains_unknown_features());
+}
+
+TEST_F(GpuControlListEntryTest, UnknownFeatureEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "features": [
+ "some_unknown_feature",
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_FALSE(entry->contains_unknown_fields());
+ EXPECT_TRUE(entry->contains_unknown_features());
+ EXPECT_EQ(1u, entry->features().size());
+ EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_0));
+
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsMacosx,
+ GpuControlList::kOsWin,
+ GpuControlList::kOsLinux,
+ GpuControlList::kOsChromeOS,
+ GpuControlList::kOsAndroid
+ };
+ for (size_t i = 0; i < arraysize(os_type); ++i)
+ EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, GlVendorEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "NVIDIA"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsMacosx,
+ GpuControlList::kOsWin,
+ GpuControlList::kOsLinux,
+ GpuControlList::kOsChromeOS,
+ GpuControlList::kOsAndroid
+ };
+ for (size_t i = 0; i < arraysize(os_type); ++i)
+ EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, GlRendererEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "gl_renderer": {
+ "op": "contains",
+ "value": "GeForce"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsMacosx,
+ GpuControlList::kOsWin,
+ GpuControlList::kOsLinux,
+ GpuControlList::kOsChromeOS,
+ GpuControlList::kOsAndroid
+ };
+ for (size_t i = 0; i < arraysize(os_type); ++i)
+ EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, PerfGraphicsEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "perf_graphics": {
+ "op": "<",
+ "value": "6.0"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsWin, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, PerfGamingEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "perf_graphics": {
+ "op": "<=",
+ "value": "4.0"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_FALSE(entry->Contains(
+ GpuControlList::kOsWin, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, PerfOverallEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "perf_overall": {
+ "op": "between",
+ "value": "1.0",
+ "value2": "9.0"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsWin, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, DisabledEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "disabled": true,
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_TRUE(entry->disabled());
+}
+
+TEST_F(GpuControlListEntryTest, OptimusEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "os": {
+ "type": "linux"
+ },
+ "multi_gpu_style": "optimus",
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ GPUInfo gpu_info;
+ gpu_info.optimus = true;
+
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsLinux, entry->GetOsType());
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsLinux, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, AMDSwitchableEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "os": {
+ "type": "macosx"
+ },
+ "multi_gpu_style": "amd_switchable",
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ GPUInfo gpu_info;
+ gpu_info.amd_switchable = true;
+
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsMacosx, entry->GetOsType());
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsMacosx, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, LexicalDriverVersionEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x1002",
+ "driver_version": {
+ "op": "=",
+ "style": "lexical",
+ "number": "8.76"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x1002;
+
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsLinux, entry->GetOsType());
+
+ gpu_info.driver_version = "8.76";
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsLinux, "10.6", gpu_info));
+
+ gpu_info.driver_version = "8.768";
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsLinux, "10.6", gpu_info));
+
+ gpu_info.driver_version = "8.76.8";
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsLinux, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, MultipleGPUsAnyEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x8086",
+ "device_id": ["0x0166"],
+ "multi_gpu_category": "any",
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsMacosx, entry->GetOsType());
+
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x10de;
+ gpu_info.gpu.device_id = 0x1976;
+ EXPECT_FALSE(entry->Contains(
+ GpuControlList::kOsMacosx, "10.6", gpu_info));
+
+ GPUInfo::GPUDevice gpu_device;
+ gpu_device.vendor_id = 0x8086;
+ gpu_device.device_id = 0x0166;
+ gpu_info.secondary_gpus.push_back(gpu_device);
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsMacosx, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, MultipleGPUsSecondaryEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x8086",
+ "device_id": ["0x0166"],
+ "multi_gpu_category": "secondary",
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(GpuControlList::kOsMacosx, entry->GetOsType());
+
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x10de;
+ gpu_info.gpu.device_id = 0x1976;
+ EXPECT_FALSE(entry->Contains(
+ GpuControlList::kOsMacosx, "10.6", gpu_info));
+
+ GPUInfo::GPUDevice gpu_device;
+ gpu_device.vendor_id = 0x8086;
+ gpu_device.device_id = 0x0166;
+ gpu_info.secondary_gpus.push_back(gpu_device);
+ EXPECT_TRUE(entry->Contains(
+ GpuControlList::kOsMacosx, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, NeedsMoreInfoEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "vendor_id": "0x8086",
+ "driver_version": {
+ "op": "<",
+ "number": "10.7"
+ },
+ "features": [
+ "test_feature_1"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x8086;
+ EXPECT_TRUE(entry->NeedsMoreInfo(gpu_info));
+
+ gpu_info.driver_version = "10.6";
+ EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, NeedsMoreInfoForExceptionsEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "vendor_id": "0x8086",
+ "exceptions": [
+ {
+ "gl_renderer": {
+ "op": "contains",
+ "value": "mesa"
+ }
+ }
+ ],
+ "features": [
+ "test_feature_1"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json));
+ EXPECT_TRUE(entry != NULL);
+
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x8086;
+ EXPECT_TRUE(entry->NeedsMoreInfo(gpu_info));
+
+ gpu_info.gl_renderer = "mesa";
+ EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, FeatureTypeAllEntry) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "id": 1,
+ "features": [
+ "all"
+ ]
+ }
+ );
+ ScopedEntry entry(GetEntryFromString(json, true));
+ EXPECT_TRUE(entry != NULL);
+ EXPECT_EQ(3u, entry->features().size());
+ EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_0));
+ EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_1));
+ EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_2));
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_control_list_jsons.h b/gpu/config/gpu_control_list_jsons.h
new file mode 100644
index 0000000..671aa9e
--- /dev/null
+++ b/gpu/config/gpu_control_list_jsons.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_CONTROL_LIST_JSONS_H_
+#define GPU_CONFIG_GPU_CONTROL_LIST_JSONS_H_
+
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+
+GPU_EXPORT extern const char kGpuDriverBugListJson[];
+GPU_EXPORT extern const char kGpuSwitchingListJson[];
+GPU_EXPORT extern const char kSoftwareRenderingListJson[];
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_CONTROL_LIST_JSONS_H_
+
diff --git a/gpu/config/gpu_control_list_machine_model_info_unittest.cc b/gpu/config/gpu_control_list_machine_model_info_unittest.cc
new file mode 100644
index 0000000..9c681a9
--- /dev/null
+++ b/gpu/config/gpu_control_list_machine_model_info_unittest.cc
@@ -0,0 +1,57 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_control_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+class MachineModelInfoTest : public testing::Test {
+ public:
+ MachineModelInfoTest() { }
+ virtual ~MachineModelInfoTest() { }
+
+ typedef GpuControlList::MachineModelInfo MachineModelInfo;
+};
+
+TEST_F(MachineModelInfoTest, ValidModelInfo) {
+ const std::string name_op[] = {
+ "contains",
+ "beginwith",
+ "endwith",
+ "="
+ };
+ const std::string version_op[] = {
+ "=",
+ "<",
+ "<=",
+ ">",
+ ">=",
+ "any",
+ "between"
+ };
+ for (size_t i = 0; i < arraysize(name_op); ++i) {
+ for (size_t j = 0; j < arraysize(version_op); ++j) {
+ std::string version1;
+ std::string version2;
+ if (version_op[j] != "any")
+ version1 = "3.14";
+ if (version_op[j] == "between")
+ version2 = "5.4";
+ MachineModelInfo info(name_op[i], "model",
+ version_op[j], version1, version2);
+ EXPECT_TRUE(info.IsValid());
+ }
+ }
+}
+
+TEST_F(MachineModelInfoTest, ModelComparison) {
+ MachineModelInfo info("=", "model_a", ">", "3.4", std::string());
+ EXPECT_TRUE(info.Contains("model_a", "4"));
+ EXPECT_FALSE(info.Contains("model_b", "4"));
+ EXPECT_FALSE(info.Contains("model_a", "3.2"));
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_control_list_number_info_unittest.cc b/gpu/config/gpu_control_list_number_info_unittest.cc
new file mode 100644
index 0000000..5bd732c
--- /dev/null
+++ b/gpu/config/gpu_control_list_number_info_unittest.cc
@@ -0,0 +1,210 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_control_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+class NumberInfoTest : public testing::Test {
+ public:
+ NumberInfoTest() { }
+ virtual ~NumberInfoTest() { }
+
+ typedef GpuControlList::FloatInfo FloatInfo;
+ typedef GpuControlList::IntInfo IntInfo;
+};
+
+TEST_F(NumberInfoTest, ValidFloatInfo) {
+ const std::string op[] = {
+ "=",
+ "<",
+ "<=",
+ ">",
+ ">=",
+ "any",
+ "between"
+ };
+ for (size_t i = 0; i < arraysize(op); ++i) {
+ std::string value1;
+ std::string value2;
+ if (op[i] != "any")
+ value1 = "3.14";
+ if (op[i] == "between")
+ value2 = "4.21";
+ FloatInfo info(op[i], value1, value2);
+ EXPECT_TRUE(info.IsValid());
+ }
+
+ const std::string value[] = {
+ "1.0E12",
+ "1.0e12",
+ "2013",
+ "1.0e-12",
+ "2.1400",
+ "-2.14",
+ };
+ for (size_t i = 0; i < arraysize(value); ++i) {
+ FloatInfo info("=", value[i], std::string());
+ EXPECT_TRUE(info.IsValid());
+ }
+}
+
+TEST_F(NumberInfoTest, InvalidFloatInfo) {
+ const std::string op[] = {
+ "=",
+ "<",
+ "<=",
+ ">",
+ ">=",
+ };
+ for (size_t i = 0; i < arraysize(op); ++i) {
+ FloatInfo info(op[i], std::string(), std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+ {
+ FloatInfo info("between", "3.14", std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+ const std::string value[] = {
+ "1.0 E12",
+ "1.0e 12",
+ " 2013",
+ "2013 ",
+ "- 2.14",
+ };
+ for (size_t i = 0; i < arraysize(value); ++i) {
+ FloatInfo info("=", value[i], std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+}
+
+TEST_F(NumberInfoTest, FloatComparison) {
+ {
+ FloatInfo info("=", "3.14", std::string());
+ EXPECT_TRUE(info.Contains(3.14f));
+ EXPECT_TRUE(info.Contains(3.1400f));
+ EXPECT_FALSE(info.Contains(3.1f));
+ EXPECT_FALSE(info.Contains(3));
+ }
+ {
+ FloatInfo info(">", "3.14", std::string());
+ EXPECT_FALSE(info.Contains(3.14f));
+ EXPECT_TRUE(info.Contains(3.141f));
+ EXPECT_FALSE(info.Contains(3.1f));
+ }
+ {
+ FloatInfo info("<=", "3.14", std::string());
+ EXPECT_TRUE(info.Contains(3.14f));
+ EXPECT_FALSE(info.Contains(3.141f));
+ EXPECT_TRUE(info.Contains(3.1f));
+ }
+ {
+ FloatInfo info("any", std::string(), std::string());
+ EXPECT_TRUE(info.Contains(3.14f));
+ }
+ {
+ FloatInfo info("between", "3.14", "5.4");
+ EXPECT_TRUE(info.Contains(3.14f));
+ EXPECT_TRUE(info.Contains(5.4f));
+ EXPECT_TRUE(info.Contains(4));
+ EXPECT_FALSE(info.Contains(5.6f));
+ EXPECT_FALSE(info.Contains(3.12f));
+ }
+}
+
+TEST_F(NumberInfoTest, ValidIntInfo) {
+ const std::string op[] = {
+ "=",
+ "<",
+ "<=",
+ ">",
+ ">=",
+ "any",
+ "between"
+ };
+ for (size_t i = 0; i < arraysize(op); ++i) {
+ std::string value1;
+ std::string value2;
+ if (op[i] != "any")
+ value1 = "3";
+ if (op[i] == "between")
+ value2 = "9";
+ IntInfo info(op[i], value1, value2);
+ EXPECT_TRUE(info.IsValid());
+ }
+
+ const std::string value[] = {
+ "12",
+ "-12",
+ };
+ for (size_t i = 0; i < arraysize(value); ++i) {
+ IntInfo info("=", value[i], std::string());
+ EXPECT_TRUE(info.IsValid());
+ }
+}
+
+TEST_F(NumberInfoTest, InvalidIntInfo) {
+ const std::string op[] = {
+ "=",
+ "<",
+ "<=",
+ ">",
+ ">=",
+ };
+ for (size_t i = 0; i < arraysize(op); ++i) {
+ IntInfo info(op[i], std::string(), std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+ {
+ IntInfo info("between", "3", std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+ const std::string value[] = {
+ " 12",
+ "12 ",
+ "- 12",
+ " -12",
+ "3.14"
+ };
+ for (size_t i = 0; i < arraysize(value); ++i) {
+ IntInfo info("=", value[i], std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+}
+
+TEST_F(NumberInfoTest, IntComparison) {
+ {
+ IntInfo info("=", "3", std::string());
+ EXPECT_TRUE(info.Contains(3));
+ EXPECT_FALSE(info.Contains(4));
+ }
+ {
+ IntInfo info(">", "3", std::string());
+ EXPECT_FALSE(info.Contains(2));
+ EXPECT_FALSE(info.Contains(3));
+ EXPECT_TRUE(info.Contains(4));
+ }
+ {
+ IntInfo info("<=", "3", std::string());
+ EXPECT_TRUE(info.Contains(2));
+ EXPECT_TRUE(info.Contains(3));
+ EXPECT_FALSE(info.Contains(4));
+ }
+ {
+ IntInfo info("any", std::string(), std::string());
+ EXPECT_TRUE(info.Contains(3));
+ }
+ {
+ IntInfo info("between", "3", "5");
+ EXPECT_TRUE(info.Contains(3));
+ EXPECT_TRUE(info.Contains(5));
+ EXPECT_TRUE(info.Contains(4));
+ EXPECT_FALSE(info.Contains(6));
+ EXPECT_FALSE(info.Contains(2));
+ }
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_control_list_os_info_unittest.cc b/gpu/config/gpu_control_list_os_info_unittest.cc
new file mode 100644
index 0000000..851f991
--- /dev/null
+++ b/gpu/config/gpu_control_list_os_info_unittest.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_control_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+class OsInfoTest : public testing::Test {
+ public:
+ OsInfoTest() { }
+ virtual ~OsInfoTest() { }
+
+ typedef GpuControlList::OsInfo OsInfo;
+};
+
+TEST_F(OsInfoTest, ValidOsInfo) {
+ const std::string os[] = {
+ "win",
+ "linux",
+ "macosx",
+ "chromeos",
+ "android",
+ "any"
+ };
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsWin,
+ GpuControlList::kOsLinux,
+ GpuControlList::kOsMacosx,
+ GpuControlList::kOsChromeOS,
+ GpuControlList::kOsAndroid,
+ GpuControlList::kOsAny
+ };
+ for (size_t i = 0; i < arraysize(os); ++i) {
+ OsInfo info(os[i], "=", "10.6", std::string());
+ EXPECT_TRUE(info.IsValid());
+ EXPECT_EQ(os_type[i], info.type());
+ }
+ {
+ OsInfo info("any", "any", std::string(), std::string());
+ EXPECT_TRUE(info.IsValid());
+ }
+}
+
+TEST_F(OsInfoTest, InvalidOsInfo) {
+ const std::string os[] = {
+ "win",
+ "linux",
+ "macosx",
+ "chromeos",
+ "android",
+ "any"
+ };
+ for (size_t i = 0; i < arraysize(os); ++i) {
+ {
+ OsInfo info(os[i], std::string(), std::string(), std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+ {
+ OsInfo info(os[i], "=", std::string(), std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+ {
+ OsInfo info(os[i], std::string(), "10.6", std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+ }
+ const std::string os_cap[] = {
+ "Win",
+ "Linux",
+ "MacOSX",
+ "ChromeOS",
+ "Android",
+ };
+ for (size_t i = 0; i < arraysize(os_cap); ++i) {
+ OsInfo info(os_cap[i], "=", "10.6", std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+}
+
+TEST_F(OsInfoTest, OsComparison) {
+ {
+ OsInfo info("any", "any", std::string(), std::string());
+ const GpuControlList::OsType os_type[] = {
+ GpuControlList::kOsWin, GpuControlList::kOsLinux,
+ GpuControlList::kOsMacosx, GpuControlList::kOsChromeOS,
+ GpuControlList::kOsAndroid,
+ };
+ for (size_t i = 0; i < arraysize(os_type); ++i) {
+ EXPECT_TRUE(info.Contains(os_type[i], std::string()));
+ EXPECT_TRUE(info.Contains(os_type[i], "7.8"));
+ }
+ }
+ {
+ OsInfo info("win", ">=", "6", std::string());
+ EXPECT_FALSE(info.Contains(GpuControlList::kOsMacosx, "10.8.3"));
+ EXPECT_FALSE(info.Contains(GpuControlList::kOsLinux, "10"));
+ EXPECT_FALSE(info.Contains(GpuControlList::kOsChromeOS, "13"));
+ EXPECT_FALSE(info.Contains(GpuControlList::kOsAndroid, "7"));
+ EXPECT_FALSE(info.Contains(GpuControlList::kOsAny, "7"));
+ EXPECT_FALSE(info.Contains(GpuControlList::kOsWin, std::string()));
+ EXPECT_TRUE(info.Contains(GpuControlList::kOsWin, "6"));
+ EXPECT_TRUE(info.Contains(GpuControlList::kOsWin, "6.1"));
+ EXPECT_TRUE(info.Contains(GpuControlList::kOsWin, "7"));
+ EXPECT_FALSE(info.Contains(GpuControlList::kOsWin, "5"));
+ }
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_control_list_string_info_unittest.cc b/gpu/config/gpu_control_list_string_info_unittest.cc
new file mode 100644
index 0000000..39e2f58
--- /dev/null
+++ b/gpu/config/gpu_control_list_string_info_unittest.cc
@@ -0,0 +1,98 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_control_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+class StringInfoTest : public testing::Test {
+ public:
+ StringInfoTest() { }
+ virtual ~StringInfoTest() { }
+
+ typedef GpuControlList::StringInfo StringInfo;
+};
+
+TEST_F(StringInfoTest, ValidStringInfo) {
+ const std::string op[] = {
+ "contains",
+ "beginwith",
+ "endwith",
+ "="
+ };
+ for (size_t i = 0; i < arraysize(op); ++i) {
+ {
+ StringInfo info(op[i], std::string());
+ EXPECT_TRUE(info.IsValid());
+ }
+ {
+ StringInfo info(op[i], "hello");
+ EXPECT_TRUE(info.IsValid());
+ }
+ }
+}
+
+TEST_F(StringInfoTest, InvalidStringInfo) {
+ const std::string op[] = {
+ "Contains",
+ "BeginWith",
+ "EndWith",
+ " =",
+ "= "
+ };
+ for (size_t i = 0; i < arraysize(op); ++i) {
+ StringInfo info(op[i], "hello");
+ EXPECT_FALSE(info.IsValid());
+ }
+}
+
+TEST_F(StringInfoTest, StringComparison) {
+ {
+ StringInfo info("contains", "happy");
+ EXPECT_TRUE(info.Contains("unhappy"));
+ EXPECT_TRUE(info.Contains("happy1"));
+ EXPECT_TRUE(info.Contains("happy"));
+ EXPECT_TRUE(info.Contains("a happy dog"));
+ EXPECT_TRUE(info.Contains("Happy"));
+ EXPECT_TRUE(info.Contains("HAPPY"));
+ EXPECT_FALSE(info.Contains("ha-ppy"));
+ }
+ {
+ StringInfo info("beginwith", "happy");
+ EXPECT_FALSE(info.Contains("unhappy"));
+ EXPECT_TRUE(info.Contains("happy1"));
+ EXPECT_TRUE(info.Contains("happy"));
+ EXPECT_FALSE(info.Contains("a happy dog"));
+ EXPECT_TRUE(info.Contains("Happy"));
+ EXPECT_TRUE(info.Contains("HAPPY"));
+ EXPECT_FALSE(info.Contains("ha-ppy"));
+ }
+ {
+ StringInfo info("endwith", "happy");
+ EXPECT_TRUE(info.Contains("unhappy"));
+ EXPECT_FALSE(info.Contains("happy1"));
+ EXPECT_TRUE(info.Contains("happy"));
+ EXPECT_FALSE(info.Contains("a happy dog"));
+ EXPECT_TRUE(info.Contains("Happy"));
+ EXPECT_TRUE(info.Contains("HAPPY"));
+ EXPECT_FALSE(info.Contains("ha-ppy"));
+ }
+ {
+ StringInfo info("=", "happy");
+ EXPECT_FALSE(info.Contains("unhappy"));
+ EXPECT_FALSE(info.Contains("happy1"));
+ EXPECT_TRUE(info.Contains("happy"));
+ EXPECT_FALSE(info.Contains("a happy dog"));
+ EXPECT_TRUE(info.Contains("Happy"));
+ EXPECT_TRUE(info.Contains("HAPPY"));
+ EXPECT_FALSE(info.Contains("ha-ppy"));
+ EXPECT_FALSE(info.Contains("ha ppy"));
+ EXPECT_FALSE(info.Contains(" happy"));
+ EXPECT_FALSE(info.Contains("happy "));
+ }
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_control_list_unittest.cc b/gpu/config/gpu_control_list_unittest.cc
new file mode 100644
index 0000000..447b684
--- /dev/null
+++ b/gpu/config/gpu_control_list_unittest.cc
@@ -0,0 +1,444 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "gpu/config/gpu_control_list.h"
+#include "gpu/config/gpu_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+const char kOsVersion[] = "10.6.4";
+const uint32 kIntelVendorId = 0x8086;
+const uint32 kIntelDeviceId = 0x0166; // 3rd Gen Core Graphics
+const uint32 kNvidiaVendorId = 0x10de;
+const uint32 kNvidiaDeviceId = 0x0fd5; // GeForce GT 650M
+
+#define LONG_STRING_CONST(...) #__VA_ARGS__
+
+#define EXPECT_EMPTY_SET(feature_set) EXPECT_EQ(0u, feature_set.size())
+#define EXPECT_SINGLE_FEATURE(feature_set, feature) \
+ EXPECT_TRUE(feature_set.size() == 1 && feature_set.count(feature) == 1)
+
+namespace gpu {
+
+enum TestFeatureType {
+ TEST_FEATURE_0 = 1,
+ TEST_FEATURE_1 = 1 << 2,
+ TEST_FEATURE_2 = 1 << 3,
+};
+
+class GpuControlListTest : public testing::Test {
+ public:
+ GpuControlListTest() { }
+
+ virtual ~GpuControlListTest() { }
+
+ const GPUInfo& gpu_info() const {
+ return gpu_info_;
+ }
+
+ GpuControlList* Create() {
+ GpuControlList* rt = new GpuControlList();
+ rt->AddSupportedFeature("test_feature_0", TEST_FEATURE_0);
+ rt->AddSupportedFeature("test_feature_1", TEST_FEATURE_1);
+ rt->AddSupportedFeature("test_feature_2", TEST_FEATURE_2);
+ return rt;
+ }
+
+ protected:
+ virtual void SetUp() {
+ gpu_info_.gpu.vendor_id = kNvidiaVendorId;
+ gpu_info_.gpu.device_id = 0x0640;
+ gpu_info_.driver_vendor = "NVIDIA";
+ gpu_info_.driver_version = "1.6.18";
+ gpu_info_.driver_date = "7-14-2009";
+ gpu_info_.machine_model = "MacBookPro 7.1";
+ gpu_info_.gl_vendor = "NVIDIA Corporation";
+ gpu_info_.gl_renderer = "NVIDIA GeForce GT 120 OpenGL Engine";
+ gpu_info_.performance_stats.graphics = 5.0;
+ gpu_info_.performance_stats.gaming = 5.0;
+ gpu_info_.performance_stats.overall = 5.0;
+ }
+
+ virtual void TearDown() {
+ }
+
+ private:
+ GPUInfo gpu_info_;
+};
+
+TEST_F(GpuControlListTest, DefaultControlListSettings) {
+ scoped_ptr<GpuControlList> control_list(Create());
+ // Default control list settings: all feature are allowed.
+ std::set<int> features = control_list->MakeDecision(
+ GpuControlList::kOsMacosx, kOsVersion, gpu_info());
+ EXPECT_EMPTY_SET(features);
+}
+
+TEST_F(GpuControlListTest, EmptyControlList) {
+ // Empty list: all features are allowed.
+ const std::string empty_list_json = LONG_STRING_CONST(
+ {
+ "name": "gpu control list",
+ "version": "2.5",
+ "entries": [
+ ]
+ }
+ );
+ scoped_ptr<GpuControlList> control_list(Create());
+
+ EXPECT_TRUE(control_list->LoadList(empty_list_json,
+ GpuControlList::kAllOs));
+ EXPECT_EQ("2.5", control_list->version());
+ std::set<int> features = control_list->MakeDecision(
+ GpuControlList::kOsMacosx, kOsVersion, gpu_info());
+ EXPECT_EMPTY_SET(features);
+}
+
+TEST_F(GpuControlListTest, DetailedEntryAndInvalidJson) {
+ // exact setting.
+ const std::string exact_list_json = LONG_STRING_CONST(
+ {
+ "name": "gpu control list",
+ "version": "0.1",
+ "entries": [
+ {
+ "id": 5,
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "=",
+ "number": "10.6.4"
+ }
+ },
+ "vendor_id": "0x10de",
+ "device_id": ["0x0640"],
+ "driver_version": {
+ "op": "=",
+ "number": "1.6.18"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ ]
+ }
+ );
+ scoped_ptr<GpuControlList> control_list(Create());
+
+ EXPECT_TRUE(control_list->LoadList(exact_list_json, GpuControlList::kAllOs));
+ std::set<int> features = control_list->MakeDecision(
+ GpuControlList::kOsMacosx, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+
+ // Invalid json input should not change the current control_list settings.
+ const std::string invalid_json = "invalid";
+
+ EXPECT_FALSE(control_list->LoadList(invalid_json, GpuControlList::kAllOs));
+ features = control_list->MakeDecision(
+ GpuControlList::kOsMacosx, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+ std::vector<uint32> entries;
+ control_list->GetDecisionEntries(&entries, false);
+ ASSERT_EQ(1u, entries.size());
+ EXPECT_EQ(5u, entries[0]);
+ EXPECT_EQ(5u, control_list->max_entry_id());
+}
+
+TEST_F(GpuControlListTest, VendorOnAllOsEntry) {
+ // ControlList a vendor on all OS.
+ const std::string vendor_json = LONG_STRING_CONST(
+ {
+ "name": "gpu control list",
+ "version": "0.1",
+ "entries": [
+ {
+ "id": 1,
+ "vendor_id": "0x10de",
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ ]
+ }
+ );
+ scoped_ptr<GpuControlList> control_list(Create());
+
+ // ControlList entries won't be filtered to the current OS only upon loading.
+ EXPECT_TRUE(control_list->LoadList(vendor_json, GpuControlList::kAllOs));
+ std::set<int> features = control_list->MakeDecision(
+ GpuControlList::kOsMacosx, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+ features = control_list->MakeDecision(
+ GpuControlList::kOsWin, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+ features = control_list->MakeDecision(
+ GpuControlList::kOsLinux, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX) || \
+ defined(OS_OPENBSD)
+ // ControlList entries will be filtered to the current OS only upon loading.
+ EXPECT_TRUE(control_list->LoadList(
+ vendor_json, GpuControlList::kCurrentOsOnly));
+ features = control_list->MakeDecision(
+ GpuControlList::kOsMacosx, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+ features = control_list->MakeDecision(
+ GpuControlList::kOsWin, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+ features = control_list->MakeDecision(
+ GpuControlList::kOsLinux, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+#endif
+}
+
+TEST_F(GpuControlListTest, ChromeVersionEntry) {
+ const std::string browser_version_json = LONG_STRING_CONST(
+ {
+ "name": "gpu control list",
+ "version": "0.1",
+ "entries": [
+ {
+ "id": 1,
+ "browser_version": {
+ "op": ">=",
+ "number": "10"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ ]
+ }
+ );
+ scoped_ptr<GpuControlList> control_list9(Create());
+ EXPECT_TRUE(control_list9->LoadList(
+ "9.0", browser_version_json, GpuControlList::kAllOs));
+ std::set<int> features = control_list9->MakeDecision(
+ GpuControlList::kOsWin, kOsVersion, gpu_info());
+ EXPECT_EMPTY_SET(features);
+
+ scoped_ptr<GpuControlList> control_list10(Create());
+ EXPECT_TRUE(control_list10->LoadList(
+ "10.0", browser_version_json, GpuControlList::kAllOs));
+ features = control_list10->MakeDecision(
+ GpuControlList::kOsWin, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+}
+
+TEST_F(GpuControlListTest, UnknownField) {
+ const std::string unknown_field_json = LONG_STRING_CONST(
+ {
+ "name": "gpu control list",
+ "version": "0.1",
+ "entries": [
+ {
+ "id": 1,
+ "unknown_field": 0,
+ "features": [
+ "test_feature_1"
+ ]
+ },
+ {
+ "id": 2,
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ ]
+ }
+ );
+ scoped_ptr<GpuControlList> control_list(Create());
+
+ EXPECT_TRUE(control_list->LoadList(
+ unknown_field_json, GpuControlList::kAllOs));
+ EXPECT_EQ(1u, control_list->num_entries());
+ EXPECT_TRUE(control_list->contains_unknown_fields());
+ std::set<int> features = control_list->MakeDecision(
+ GpuControlList::kOsWin, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+}
+
+TEST_F(GpuControlListTest, UnknownExceptionField) {
+ const std::string unknown_exception_field_json = LONG_STRING_CONST(
+ {
+ "name": "gpu control list",
+ "version": "0.1",
+ "entries": [
+ {
+ "id": 1,
+ "unknown_field": 0,
+ "features": [
+ "test_feature_2"
+ ]
+ },
+ {
+ "id": 2,
+ "exceptions": [
+ {
+ "unknown_field": 0
+ }
+ ],
+ "features": [
+ "test_feature_1"
+ ]
+ },
+ {
+ "id": 3,
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ ]
+ }
+ );
+ scoped_ptr<GpuControlList> control_list(Create());
+
+ EXPECT_TRUE(control_list->LoadList(
+ unknown_exception_field_json, GpuControlList::kAllOs));
+ EXPECT_EQ(1u, control_list->num_entries());
+ EXPECT_TRUE(control_list->contains_unknown_fields());
+ std::set<int> features = control_list->MakeDecision(
+ GpuControlList::kOsWin, kOsVersion, gpu_info());
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+}
+
+TEST_F(GpuControlListTest, DisabledEntry) {
+ const std::string disabled_json = LONG_STRING_CONST(
+ {
+ "name": "gpu control list",
+ "version": "0.1",
+ "entries": [
+ {
+ "id": 1,
+ "disabled": true,
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ ]
+ }
+ );
+ scoped_ptr<GpuControlList> control_list(Create());
+ EXPECT_TRUE(control_list->LoadList(disabled_json, GpuControlList::kAllOs));
+ std::set<int> features = control_list->MakeDecision(
+ GpuControlList::kOsWin, kOsVersion, gpu_info());
+ EXPECT_EMPTY_SET(features);
+ std::vector<uint32> flag_entries;
+ control_list->GetDecisionEntries(&flag_entries, false);
+ EXPECT_EQ(0u, flag_entries.size());
+ control_list->GetDecisionEntries(&flag_entries, true);
+ EXPECT_EQ(1u, flag_entries.size());
+}
+
+TEST_F(GpuControlListTest, NeedsMoreInfoForExceptions) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "name": "gpu control list",
+ "version": "0.1",
+ "entries": [
+ {
+ "id": 1,
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x8086",
+ "exceptions": [
+ {
+ "gl_renderer": {
+ "op": "contains",
+ "value": "mesa"
+ }
+ }
+ ],
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ ]
+ }
+ );
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = kIntelVendorId;
+
+ scoped_ptr<GpuControlList> control_list(Create());
+ EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
+
+ // The case this entry does not apply.
+ std::set<int> features = control_list->MakeDecision(
+ GpuControlList::kOsMacosx, kOsVersion, gpu_info);
+ EXPECT_EMPTY_SET(features);
+ EXPECT_FALSE(control_list->needs_more_info());
+
+ // The case this entry might apply, but need more info.
+ features = control_list->MakeDecision(
+ GpuControlList::kOsLinux, kOsVersion, gpu_info);
+ EXPECT_EMPTY_SET(features);
+ EXPECT_TRUE(control_list->needs_more_info());
+
+ // The case we have full info, and the exception applies (so the entry
+ // does not apply).
+ gpu_info.gl_renderer = "mesa";
+ features = control_list->MakeDecision(
+ GpuControlList::kOsLinux, kOsVersion, gpu_info);
+ EXPECT_EMPTY_SET(features);
+ EXPECT_FALSE(control_list->needs_more_info());
+
+ // The case we have full info, and this entry applies.
+ gpu_info.gl_renderer = "my renderer";
+ features = control_list->MakeDecision(GpuControlList::kOsLinux, kOsVersion,
+ gpu_info);
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+ EXPECT_FALSE(control_list->needs_more_info());
+}
+
+TEST_F(GpuControlListTest, IgnorableEntries) {
+ // If an entry will not change the control_list decisions, then it should not
+ // trigger the needs_more_info flag.
+ const std::string json = LONG_STRING_CONST(
+ {
+ "name": "gpu control list",
+ "version": "0.1",
+ "entries": [
+ {
+ "id": 1,
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x8086",
+ "features": [
+ "test_feature_0"
+ ]
+ },
+ {
+ "id": 2,
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x8086",
+ "driver_version": {
+ "op": "<",
+ "number": "10.7"
+ },
+ "features": [
+ "test_feature_0"
+ ]
+ }
+ ]
+ }
+ );
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = kIntelVendorId;
+
+ scoped_ptr<GpuControlList> control_list(Create());
+ EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
+ std::set<int> features = control_list->MakeDecision(
+ GpuControlList::kOsLinux, kOsVersion, gpu_info);
+ EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
+ EXPECT_FALSE(control_list->needs_more_info());
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_control_list_version_info_unittest.cc b/gpu/config/gpu_control_list_version_info_unittest.cc
new file mode 100644
index 0000000..39814c8
--- /dev/null
+++ b/gpu/config/gpu_control_list_version_info_unittest.cc
@@ -0,0 +1,258 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_control_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+class VersionInfoTest : public testing::Test {
+ public:
+ VersionInfoTest() { }
+ virtual ~VersionInfoTest() { }
+
+ typedef GpuControlList::VersionInfo VersionInfo;
+};
+
+TEST_F(VersionInfoTest, ValidVersionInfo) {
+ const std::string op[] = {
+ "=",
+ "<",
+ "<=",
+ ">",
+ ">=",
+ "any",
+ "between"
+ };
+ for (size_t i = 0; i < arraysize(op); ++i) {
+ std::string string1;
+ std::string string2;
+ if (op[i] != "any")
+ string1 = "8.9";
+ if (op[i] == "between")
+ string2 = "9.0";
+ VersionInfo info(op[i], std::string(), string1, string2);
+ EXPECT_TRUE(info.IsValid());
+ }
+
+ const std::string style[] = {
+ "lexical",
+ "numerical",
+ "" // Default, same as "numerical"
+ };
+ for (size_t i =0; i < arraysize(style); ++i) {
+ VersionInfo info("=", style[i], "8.9", std::string());
+ EXPECT_TRUE(info.IsValid());
+ if (style[i] == "lexical")
+ EXPECT_TRUE(info.IsLexical());
+ else
+ EXPECT_FALSE(info.IsLexical());
+ }
+
+ const std::string number[] = {
+ "10",
+ "10.9",
+ "10.0",
+ "10.0.9",
+ "0.8",
+ // Leading 0s are valid.
+ "10.09",
+ // Whitespaces are ignored.
+ " 10.9",
+ "10.9 ",
+ "10 .9",
+ "10. 9",
+ };
+ for (size_t i =0; i < arraysize(number); ++i) {
+ VersionInfo info("=", std::string(), number[i], std::string());
+ EXPECT_TRUE(info.IsValid());
+ }
+}
+
+TEST_F(VersionInfoTest, InvalidVersionInfo) {
+ const std::string op[] = {
+ "=",
+ "<",
+ "<=",
+ ">",
+ ">=",
+ "any",
+ "between"
+ };
+ for (size_t i = 0; i < arraysize(op); ++i) {
+ {
+ VersionInfo info(op[i], std::string(), "8.9", std::string());
+ if (op[i] == "between")
+ EXPECT_FALSE(info.IsValid());
+ else
+ EXPECT_TRUE(info.IsValid());
+ }
+ {
+ VersionInfo info(op[i], std::string(), std::string(), std::string());
+ if (op[i] == "any")
+ EXPECT_TRUE(info.IsValid());
+ else
+ EXPECT_FALSE(info.IsValid());
+ }
+ {
+ VersionInfo info(op[i], std::string(), "8.9", "9.0");
+ EXPECT_TRUE(info.IsValid());
+ }
+ }
+
+ const std::string number[] = {
+ "8.E",
+ "8-9",
+ };
+ for (size_t i = 0; i < arraysize(number); ++i) {
+ VersionInfo info("=", std::string(), number[i], std::string());
+ EXPECT_FALSE(info.IsValid());
+ }
+}
+
+TEST_F(VersionInfoTest, VersionComparison) {
+ {
+ VersionInfo info("any", std::string(), std::string(), std::string());
+ EXPECT_TRUE(info.Contains("0"));
+ EXPECT_TRUE(info.Contains("8.9"));
+ EXPECT_TRUE(info.Contains("100"));
+ }
+ {
+ VersionInfo info(">", std::string(), "8.9", std::string());
+ EXPECT_FALSE(info.Contains("7"));
+ EXPECT_FALSE(info.Contains("8.9"));
+ EXPECT_FALSE(info.Contains("8.9.1"));
+ EXPECT_TRUE(info.Contains("9"));
+ }
+ {
+ VersionInfo info(">=", std::string(), "8.9", std::string());
+ EXPECT_FALSE(info.Contains("7"));
+ EXPECT_TRUE(info.Contains("8.9"));
+ EXPECT_TRUE(info.Contains("8.9.1"));
+ EXPECT_TRUE(info.Contains("9"));
+ }
+ {
+ VersionInfo info("=", std::string(), "8.9", std::string());
+ EXPECT_FALSE(info.Contains("7"));
+ EXPECT_TRUE(info.Contains("8"));
+ EXPECT_TRUE(info.Contains("8.9"));
+ EXPECT_TRUE(info.Contains("8.9.1"));
+ EXPECT_FALSE(info.Contains("9"));
+ }
+ {
+ VersionInfo info("<", std::string(), "8.9", std::string());
+ EXPECT_TRUE(info.Contains("7"));
+ EXPECT_TRUE(info.Contains("8.8"));
+ EXPECT_FALSE(info.Contains("8"));
+ EXPECT_FALSE(info.Contains("8.9"));
+ EXPECT_FALSE(info.Contains("8.9.1"));
+ EXPECT_FALSE(info.Contains("9"));
+ }
+ {
+ VersionInfo info("<=", std::string(), "8.9", std::string());
+ EXPECT_TRUE(info.Contains("7"));
+ EXPECT_TRUE(info.Contains("8.8"));
+ EXPECT_TRUE(info.Contains("8"));
+ EXPECT_TRUE(info.Contains("8.9"));
+ EXPECT_TRUE(info.Contains("8.9.1"));
+ EXPECT_FALSE(info.Contains("9"));
+ }
+ {
+ VersionInfo info("between", std::string(), "8.9", "9.1");
+ EXPECT_FALSE(info.Contains("7"));
+ EXPECT_FALSE(info.Contains("8.8"));
+ EXPECT_TRUE(info.Contains("8"));
+ EXPECT_TRUE(info.Contains("8.9"));
+ EXPECT_TRUE(info.Contains("8.9.1"));
+ EXPECT_TRUE(info.Contains("9"));
+ EXPECT_TRUE(info.Contains("9.1"));
+ EXPECT_TRUE(info.Contains("9.1.9"));
+ EXPECT_FALSE(info.Contains("9.2"));
+ EXPECT_FALSE(info.Contains("10"));
+ }
+}
+
+TEST_F(VersionInfoTest, DateComparison) {
+ // When we use '-' as splitter, we assume a format of mm-dd-yyyy
+ // or mm-yyyy, i.e., a date.
+ {
+ VersionInfo info("=", std::string(), "1976.3.21", std::string());
+ EXPECT_TRUE(info.Contains("3-21-1976", '-'));
+ EXPECT_TRUE(info.Contains("3-1976", '-'));
+ EXPECT_TRUE(info.Contains("03-1976", '-'));
+ EXPECT_FALSE(info.Contains("21-3-1976", '-'));
+ }
+ {
+ VersionInfo info(">", std::string(), "1976.3.21", std::string());
+ EXPECT_TRUE(info.Contains("3-22-1976", '-'));
+ EXPECT_TRUE(info.Contains("4-1976", '-'));
+ EXPECT_TRUE(info.Contains("04-1976", '-'));
+ EXPECT_FALSE(info.Contains("3-1976", '-'));
+ EXPECT_FALSE(info.Contains("2-1976", '-'));
+ }
+ {
+ VersionInfo info("between", std::string(), "1976.3.21", "2012.12.25");
+ EXPECT_FALSE(info.Contains("3-20-1976", '-'));
+ EXPECT_TRUE(info.Contains("3-21-1976", '-'));
+ EXPECT_TRUE(info.Contains("3-22-1976", '-'));
+ EXPECT_TRUE(info.Contains("3-1976", '-'));
+ EXPECT_TRUE(info.Contains("4-1976", '-'));
+ EXPECT_TRUE(info.Contains("1-1-2000", '-'));
+ EXPECT_TRUE(info.Contains("1-2000", '-'));
+ EXPECT_TRUE(info.Contains("2000", '-'));
+ EXPECT_TRUE(info.Contains("11-2012", '-'));
+ EXPECT_TRUE(info.Contains("12-2012", '-'));
+ EXPECT_TRUE(info.Contains("12-24-2012", '-'));
+ EXPECT_TRUE(info.Contains("12-25-2012", '-'));
+ EXPECT_FALSE(info.Contains("12-26-2012", '-'));
+ EXPECT_FALSE(info.Contains("1-2013", '-'));
+ EXPECT_FALSE(info.Contains("2013", '-'));
+ }
+}
+
+TEST_F(VersionInfoTest, LexicalComparison) {
+ // When we use lexical style, we assume a format major.minor.*.
+ // We apply numerical comparison to major, lexical comparison to others.
+ {
+ VersionInfo info("<", "lexical", "8.201", std::string());
+ EXPECT_TRUE(info.Contains("8.001.100"));
+ EXPECT_TRUE(info.Contains("8.109"));
+ EXPECT_TRUE(info.Contains("8.10900"));
+ EXPECT_TRUE(info.Contains("8.109.100"));
+ EXPECT_TRUE(info.Contains("8.2"));
+ EXPECT_TRUE(info.Contains("8.20"));
+ EXPECT_TRUE(info.Contains("8.200"));
+ EXPECT_TRUE(info.Contains("8.20.100"));
+ EXPECT_FALSE(info.Contains("8.201"));
+ EXPECT_FALSE(info.Contains("8.2010"));
+ EXPECT_FALSE(info.Contains("8.21"));
+ EXPECT_FALSE(info.Contains("8.21.100"));
+ EXPECT_FALSE(info.Contains("9.002"));
+ EXPECT_FALSE(info.Contains("9.201"));
+ EXPECT_FALSE(info.Contains("12"));
+ EXPECT_FALSE(info.Contains("12.201"));
+ }
+ {
+ VersionInfo info("<", "lexical", "9.002", std::string());
+ EXPECT_TRUE(info.Contains("8.001.100"));
+ EXPECT_TRUE(info.Contains("8.109"));
+ EXPECT_TRUE(info.Contains("8.10900"));
+ EXPECT_TRUE(info.Contains("8.109.100"));
+ EXPECT_TRUE(info.Contains("8.2"));
+ EXPECT_TRUE(info.Contains("8.20"));
+ EXPECT_TRUE(info.Contains("8.200"));
+ EXPECT_TRUE(info.Contains("8.20.100"));
+ EXPECT_TRUE(info.Contains("8.201"));
+ EXPECT_TRUE(info.Contains("8.2010"));
+ EXPECT_TRUE(info.Contains("8.21"));
+ EXPECT_TRUE(info.Contains("8.21.100"));
+ EXPECT_FALSE(info.Contains("9.002"));
+ EXPECT_FALSE(info.Contains("9.201"));
+ EXPECT_FALSE(info.Contains("12"));
+ EXPECT_FALSE(info.Contains("12.201"));
+ }
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_driver_bug_list.cc b/gpu/config/gpu_driver_bug_list.cc
new file mode 100644
index 0000000..68f1b0b
--- /dev/null
+++ b/gpu/config/gpu_driver_bug_list.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_driver_bug_list.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
+
+namespace gpu {
+
+namespace {
+
+struct DriverBugInfo {
+ int feature_type;
+ std::string feature_name;
+};
+
+} // namespace anonymous
+
+GpuDriverBugList::GpuDriverBugList()
+ : GpuControlList() {
+}
+
+GpuDriverBugList::~GpuDriverBugList() {
+}
+
+// static
+GpuDriverBugList* GpuDriverBugList::Create() {
+ GpuDriverBugList* list = new GpuDriverBugList();
+
+ const DriverBugInfo kFeatureList[] = {
+#define GPU_OP(type, name) { type, #name },
+ GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP)
+#undef GPU_OP
+ };
+ DCHECK_EQ(static_cast<int>(arraysize(kFeatureList)),
+ NUMBER_OF_GPU_DRIVER_BUG_WORKAROUND_TYPES);
+ for (int i = 0; i < NUMBER_OF_GPU_DRIVER_BUG_WORKAROUND_TYPES; ++i) {
+ list->AddSupportedFeature(kFeatureList[i].feature_name,
+ kFeatureList[i].feature_type);
+ }
+ return list;
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_driver_bug_list.h b/gpu/config/gpu_driver_bug_list.h
new file mode 100644
index 0000000..9943251
--- /dev/null
+++ b/gpu/config/gpu_driver_bug_list.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_DRIVER_BUG_LIST_H_
+#define GPU_CONFIG_GPU_DRIVER_BUG_LIST_H_
+
+#include <string>
+
+#include "gpu/config/gpu_control_list.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+
+class GPU_EXPORT GpuDriverBugList : public GpuControlList {
+ public:
+ virtual ~GpuDriverBugList();
+
+ static GpuDriverBugList* Create();
+
+ private:
+ GpuDriverBugList();
+
+ DISALLOW_COPY_AND_ASSIGN(GpuDriverBugList);
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_DRIVER_BUG_LIST_H_
+
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
new file mode 100644
index 0000000..dc9e5bf
--- /dev/null
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -0,0 +1,366 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Determines whether a certain driver bug exists in the current system.
+// A valid gpu_driver_bug_list.json file are in the format of
+// {
+// "version": "x.y",
+// "entries": [
+// { // entry 1
+// },
+// ...
+// { // entry n
+// }
+// ]
+// }
+//
+// Each entry contains the following fields (fields are optional unless
+// specifically described as mandatory below):
+// 1. "id" is an integer. 0 is reserved. This field is mandatory.
+// 2. "os" contains "type" and an optional "version". "type" could be "macosx",
+// "linux", "win", "chromeos", or "any". "any" is the same as not specifying
+// "os".
+// "version" is a VERSION structure (defined below).
+// 3. "vendor_id" is a string. 0 is reserved.
+// 4. "device_id" is an array of strings. 0 is reserved.
+// 5. "multi_gpu_style" is a string, valid values include "optimus", and
+// "amd_switchable".
+// 6. "multi_gpu_category" is a string, valid values include "any", "primary",
+// and "secondary". If unspecified, the default value is "primary".
+// 7. "driver_vendor" is a STRING structure (defined below).
+// 8. "driver_version" is a VERSION structure (defined below).
+// 9. "driver_date" is a VERSION structure (defined below).
+// The version is interpreted as "year.month.day".
+// 10. "gl_vendor" is a STRING structure (defined below).
+// 11. "gl_renderer" is a STRING structure (defined below).
+// 12. "gl_extensions" is a STRING structure (defined below).
+// 13. "perf_graphics" is a FLOAT structure (defined below).
+// 14. "perf_gaming" is a FLOAT structure (defined below).
+// 15. "perf_overall" is a FLOAT structure (defined below).
+// 16. "machine_model" contais "name" and an optional "version". "name" is a
+// STRING structure and "version" is a VERSION structure (defined below).
+// 17. "gpu_count" is a INT structure (defined below).
+// 18 "cpu_info" is a STRING structure (defined below).
+// 19. "exceptions" is a list of entries.
+// 20. "features" is a list of driver bug types. For a list of supported types,
+// see src/gpu/command_buffer/service/gpu_driver_bug_workaround_type.h
+// This field is mandatory.
+// 21. "description" has the description of the entry.
+// 22. "webkit_bugs" is an array of associated webkit bug numbers.
+// 23. "cr_bugs" is an array of associated chromium bug numbers.
+// 24. "browser_version" is a VERSION structure (defined below). If this
+// condition is not satisfied, the entry will be ignored. If it is not
+// present, then the entry applies to all versions of the browser.
+// 25. "disabled" is a boolean. If it is present, the entry will be skipped.
+// This can not be used in exceptions.
+//
+// VERSION includes "op", "style", "number", and "number2". "op" can be any of
+// the following values: "=", "<", "<=", ">", ">=", "any", "between". "style"
+// is optional and can be "lexical" or "numerical"; if it's not specified, it
+// defaults to "numerical". "number2" is only used if "op" is "between".
+// "between" is "number <= * <= number2".
+// "number" is used for all "op" values except "any". "number" and "number2"
+// are in the format of x, x.x, x.x.x, etc.
+// Only "driver_version" supports lexical style if the format is major.minor;
+// in that case, major is still numerical, but minor is lexical.
+//
+// STRING includes "op" and "value". "op" can be any of the following values:
+// "contains", "beginwith", "endwith", "=". "value" is a string.
+//
+// FLOAT includes "op" "value", and "value2". "op" can be any of the
+// following values: "=", "<", "<=", ">", ">=", "any", "between". "value2" is
+// only used if "op" is "between". "value" is used for all "op" values except
+// "any". "value" and "value2" are valid float numbers.
+// INT is very much like FLOAT, except that the values need to be integers.
+
+#include "gpu/config/gpu_control_list_jsons.h"
+
+#define LONG_STRING_CONST(...) #__VA_ARGS__
+
+namespace gpu {
+
+const char kGpuDriverBugListJson[] = LONG_STRING_CONST(
+
+{
+ "name": "gpu driver bug list",
+ // Please update the version number whenever you change this file.
+ "version": "2.1",
+ "entries": [
+ {
+ "id": 1,
+ "description": "Imagination driver doesn't like uploading lots of buffer data constantly",
+ "os": {
+ "type": "android"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "Imagination"
+ },
+ "features": [
+ "use_client_side_arrays_for_stream_buffers"
+ ]
+ },
+ {
+ "id": 2,
+ "description": "ARM driver doesn't like uploading lots of buffer data constantly",
+ "os": {
+ "type": "android"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "ARM"
+ },
+ "features": [
+ "use_client_side_arrays_for_stream_buffers"
+ ]
+ },
+ {
+ "id": 3,
+ "features": [
+ "set_texture_filter_before_generating_mipmap"
+ ]
+ },
+ {
+ "id": 4,
+ "description": "Need to set the alpha to 255",
+ "features": [
+ "clear_alpha_in_readpixels"
+ ]
+ },
+ {
+ "id": 5,
+ "vendor_id": "0x10de",
+ "features": [
+ "use_current_program_after_successful_link"
+ ]
+ },
+ {
+ "id": 6,
+ "os": {
+ "type": "android"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "Qualcomm"
+ },
+ "features": [
+ "restore_scissor_on_fbo_change",
+ "flush_on_context_switch",
+ "delete_instead_of_resize_fbo" // Only need this on the ICS driver.
+ ]
+ },
+ {
+ "id": 7,
+ "cr_bugs": [89557],
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x10de",
+ "features": [
+ "needs_offscreen_buffer_workaround"
+ ]
+ },
+ {
+ "id": 8,
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x1002",
+ "features": [
+ "needs_glsl_built_in_function_emulation"
+ ]
+ },
+ {
+ "id": 9,
+ "description": "Mac AMD drivers get gl_PointCoord backward, rdar://problem/11883495",
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x1002",
+ "features": [
+ "reverse_point_sprite_coord_origin"
+ ]
+ },
+ {
+ "id": 10,
+ "description": "Mac Intel drivers get gl_PointCoord backward, rdar://problem/11883495",
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x8086",
+ "features": [
+ "reverse_point_sprite_coord_origin"
+ ]
+ },
+ {
+ "id": 11,
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x8086",
+ "features": [
+ "max_texture_size_limit_4096"
+ ]
+ },
+ {
+ "id": 12,
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x8086",
+ "features": [
+ "max_cube_map_texture_size_limit_1024"
+ ]
+ },
+ {
+ "id": 13,
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "<",
+ "number": "10.7.3"
+ }
+ },
+ "vendor_id": "0x8086",
+ "features": [
+ "max_cube_map_texture_size_limit_512"
+ ]
+ },
+ {
+ "id": 14,
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x1002",
+ "features": [
+ "max_texture_size_limit_4096",
+ "max_cube_map_texture_size_limit_4096"
+ ]
+ },
+ {
+ "id": 15,
+ "description": "Some Android Qualcomm drivers falsely report GL_ANGLE_framebuffer_multisample",
+ "cr_bugs": [165736],
+ "os": {
+ "type": "android"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "Qualcomm"
+ },
+ "features": [
+ "disable_angle_framebuffer_multisample"
+ ]
+ },
+ {
+ "id": 16,
+ "description": "Intel drivers on Linux appear to be buggy",
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x8086",
+ "features": [
+ "disable_ext_occlusion_query"
+ ]
+ },
+ {
+ "id": 17,
+ "description": "Some drivers are unable to reset the D3D device in the GPU process sandbox",
+ "os": {
+ "type": "win"
+ },
+ "features": [
+ "exit_on_context_lost"
+ ]
+ },
+ {
+ "id": 18,
+ "description": "Everything except async + NPOT + multiple-of-8 textures are brutally slow for Imagination drivers",
+ "os": {
+ "type": "android"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "Imagination"
+ },
+ "features": [
+ "enable_chromium_fast_npot_mo8_textures"
+ ]
+ },
+ {
+ "id": 19,
+ "os": {
+ "type": "android"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "Qualcomm"
+ },
+ "features": [
+ "disable_depth_texture"
+ ]
+ },
+ {
+ "id": 20,
+ "description": "Disable EXT_draw_buffers on GeForce GT 650M on Mac OS X due to driver bugs.",
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x10de",
+ "device_id": ["0x0fd5"],
+ "multi_gpu_category": "any",
+ "features": [
+ "disable_ext_draw_buffers"
+ ]
+ },
+ {
+ "id": 21,
+ "description": "Vivante GPUs are buggy with context switching.",
+ "cr_bugs": [179250, 235935],
+ "os": {
+ "type": "android"
+ },
+ "gl_extensions": {
+ "op": "contains",
+ "value": "GL_VIV_shader_binary"
+ },
+ "features": [
+ "unbind_fbo_on_context_switch"
+ ]
+ },
+ {
+ "id": 22,
+ "description": "Imagination drivers are buggy with context switching.",
+ "cr_bugs": [230896],
+ "os": {
+ "type": "android"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "Imagination"
+ },
+ "features": [
+ "unbind_fbo_on_context_switch"
+ ]
+ },
+ {
+ "id": 23,
+ "cr_bugs": [243038],
+ "description": "Disable OES_standard_derivative on Intel Pineview M Gallium drivers.",
+ "os": {
+ "type": "chromeos"
+ },
+ "vendor_id": "0x8086",
+ "device_id": ["0xa011", "0xa012"],
+ "features": [
+ "disable_oes_standard_derivatives"
+ ]
+ }
+ ]
+}
+
+); // LONG_STRING_CONST macro
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_driver_bug_list_unittest.cc b/gpu/config/gpu_driver_bug_list_unittest.cc
new file mode 100644
index 0000000..60bc339
--- /dev/null
+++ b/gpu/config/gpu_driver_bug_list_unittest.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "gpu/config/gpu_control_list_jsons.h"
+#include "gpu/config/gpu_driver_bug_list.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
+#include "gpu/config/gpu_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+const char kOsVersion[] = "10.6.4";
+
+namespace gpu {
+
+class GpuDriverBugListTest : public testing::Test {
+ public:
+ GpuDriverBugListTest() { }
+
+ virtual ~GpuDriverBugListTest() { }
+
+ const GPUInfo& gpu_info() const {
+ return gpu_info_;
+ }
+
+ protected:
+ virtual void SetUp() {
+ gpu_info_.gpu.vendor_id = 0x10de;
+ gpu_info_.gpu.device_id = 0x0640;
+ gpu_info_.driver_vendor = "NVIDIA";
+ gpu_info_.driver_version = "1.6.18";
+ gpu_info_.driver_date = "7-14-2009";
+ gpu_info_.machine_model = "MacBookPro 7.1";
+ gpu_info_.gl_vendor = "NVIDIA Corporation";
+ gpu_info_.gl_renderer = "NVIDIA GeForce GT 120 OpenGL Engine";
+ gpu_info_.performance_stats.graphics = 5.0;
+ gpu_info_.performance_stats.gaming = 5.0;
+ gpu_info_.performance_stats.overall = 5.0;
+ }
+
+ virtual void TearDown() {
+ }
+
+ private:
+ GPUInfo gpu_info_;
+};
+
+TEST_F(GpuDriverBugListTest, CurrentDriverBugListValidation) {
+ scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create());
+ std::string json;
+ EXPECT_TRUE(list->LoadList(kGpuDriverBugListJson, GpuControlList::kAllOs));
+ EXPECT_FALSE(list->contains_unknown_fields());
+}
+
+TEST_F(GpuDriverBugListTest, CurrentListForARM) {
+ scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create());
+ EXPECT_TRUE(list->LoadList(kGpuDriverBugListJson, GpuControlList::kAllOs));
+
+ GPUInfo gpu_info;
+ gpu_info.gl_vendor = "ARM";
+ gpu_info.gl_renderer = "MALi_T604";
+ std::set<int> bugs = list->MakeDecision(
+ GpuControlList::kOsAndroid, "4.1", gpu_info);
+ EXPECT_EQ(1u, bugs.count(USE_CLIENT_SIDE_ARRAYS_FOR_STREAM_BUFFERS));
+}
+
+TEST_F(GpuDriverBugListTest, CurrentListForImagination) {
+ scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create());
+ EXPECT_TRUE(list->LoadList(kGpuDriverBugListJson, GpuControlList::kAllOs));
+
+ GPUInfo gpu_info;
+ gpu_info.gl_vendor = "Imagination Technologies";
+ gpu_info.gl_renderer = "PowerVR SGX 540";
+ std::set<int> bugs = list->MakeDecision(
+ GpuControlList::kOsAndroid, "4.1", gpu_info);
+ EXPECT_EQ(1u, bugs.count(USE_CLIENT_SIDE_ARRAYS_FOR_STREAM_BUFFERS));
+}
+
+} // namespace gpu
+
diff --git a/gpu/command_buffer/service/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
similarity index 91%
rename from gpu/command_buffer/service/gpu_driver_bug_workaround_type.h
rename to gpu/config/gpu_driver_bug_workaround_type.h
index 5580453..1d78c97 100644
--- a/gpu/command_buffer/service/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_DRIVER_BUG_WORDAROUND_TYPE_H_
-#define GPU_COMMAND_BUFFER_SERVICE_GPU_DRIVER_BUG_WORDAROUND_TYPE_H_
+#ifndef GPU_CONFIG_GPU_DRIVER_BUG_WORKAROUND_TYPE_H_
+#define GPU_CONFIG_GPU_DRIVER_BUG_WORKAROUND_TYPE_H_
#include "gpu/gpu_export.h"
@@ -22,6 +22,8 @@
disable_ext_draw_buffers) \
GPU_OP(DISABLE_EXT_OCCLUSION_QUERY, \
disable_ext_occlusion_query) \
+ GPU_OP(DISABLE_OES_STANDARD_DERIVATIVES, \
+ disable_oes_standard_derivatives) \
GPU_OP(ENABLE_CHROMIUM_FAST_NPOT_MO8_TEXTURES, \
enable_chromium_fast_npot_mo8_textures) \
GPU_OP(EXIT_ON_CONTEXT_LOST, \
@@ -65,5 +67,5 @@
} // namespace gpu
-#endif // GPU_COMMAND_BUFFER_SERVICE_GPU_DRIVER_BUG_WORDAROUND_TYPE_H_
+#endif // GPU_CONFIG_GPU_DRIVER_BUG_WORKAROUND_TYPE_H_
diff --git a/gpu/config/gpu_dx_diagnostics_win.cc b/gpu/config/gpu_dx_diagnostics_win.cc
new file mode 100644
index 0000000..ed2fc91
--- /dev/null
+++ b/gpu/config/gpu_dx_diagnostics_win.cc
@@ -0,0 +1,135 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Functions to enumerate the Dx Diagnostic Tool hierarchy and build up
+// a tree of nodes with name / value properties.
+
+#define INITGUID
+#include <dxdiag.h>
+#include <windows.h>
+
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/win/scoped_com_initializer.h"
+#include "gpu/config/gpu_info_collector.h"
+
+namespace gpu {
+
+namespace {
+
+// Traverses the IDxDiagContainer tree and populates a tree of DxDiagNode
+// structures that contains property name / value pairs and subtrees of DirectX
+// diagnostic information.
+void RecurseDiagnosticTree(DxDiagNode* output,
+ IDxDiagContainer* container,
+ int depth) {
+ HRESULT hr;
+
+ VARIANT variant;
+ VariantInit(&variant);
+
+ DWORD prop_count;
+ hr = container->GetNumberOfProps(&prop_count);
+ if (SUCCEEDED(hr)) {
+ for (DWORD i = 0; i < prop_count; i++) {
+ WCHAR prop_name16[256];
+ hr = container->EnumPropNames(i, prop_name16, arraysize(prop_name16));
+ if (SUCCEEDED(hr)) {
+ std::string prop_name8 = WideToUTF8(prop_name16);
+
+ hr = container->GetProp(prop_name16, &variant);
+ if (SUCCEEDED(hr)) {
+ switch (variant.vt) {
+ case VT_UI4:
+ output->values[prop_name8] = base::UintToString(variant.ulVal);
+ break;
+ case VT_I4:
+ output->values[prop_name8] = base::IntToString(variant.lVal);
+ break;
+ case VT_BOOL:
+ output->values[prop_name8] = variant.boolVal ? "true" : "false";
+ break;
+ case VT_BSTR:
+ output->values[prop_name8] = WideToUTF8(variant.bstrVal);
+ break;
+ default:
+ break;
+ }
+
+ // Clear the variant (this is needed to free BSTR memory).
+ VariantClear(&variant);
+ }
+ }
+ }
+ }
+
+ if (depth > 0) {
+ DWORD child_count;
+ hr = container->GetNumberOfChildContainers(&child_count);
+ if (SUCCEEDED(hr)) {
+ for (DWORD i = 0; i < child_count; i++) {
+ WCHAR child_name16[256];
+ hr = container->EnumChildContainerNames(i,
+ child_name16,
+ arraysize(child_name16));
+ if (SUCCEEDED(hr)) {
+ std::string child_name8 = WideToUTF8(child_name16);
+ DxDiagNode* output_child = &output->children[child_name8];
+
+ IDxDiagContainer* child_container = NULL;
+ hr = container->GetChildContainer(child_name16, &child_container);
+ if (SUCCEEDED(hr)) {
+ RecurseDiagnosticTree(output_child, child_container, depth - 1);
+
+ child_container->Release();
+ }
+ }
+ }
+ }
+ }
+}
+} // namespace anonymous
+
+bool GetDxDiagnostics(DxDiagNode* output) {
+ HRESULT hr;
+ bool success = false;
+ base::win::ScopedCOMInitializer com_initializer;
+
+ IDxDiagProvider* provider = NULL;
+ hr = CoCreateInstance(CLSID_DxDiagProvider,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IDxDiagProvider,
+ reinterpret_cast<void**>(&provider));
+ if (SUCCEEDED(hr)) {
+ DXDIAG_INIT_PARAMS params = { sizeof(params) };
+ params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION;
+ params.bAllowWHQLChecks = FALSE;
+ params.pReserved = NULL;
+
+ hr = provider->Initialize(¶ms);
+ if (SUCCEEDED(hr)) {
+ IDxDiagContainer* root = NULL;
+ hr = provider->GetRootContainer(&root);
+ if (SUCCEEDED(hr)) {
+ // Limit to the DisplayDevices subtree. The tree in its entirity is
+ // enormous and only this branch contains useful information.
+ IDxDiagContainer* display_devices = NULL;
+ hr = root->GetChildContainer(L"DxDiag_DisplayDevices",
+ &display_devices);
+ if (SUCCEEDED(hr)) {
+ RecurseDiagnosticTree(output, display_devices, 1);
+ success = true;
+ display_devices->Release();
+ }
+
+ root->Release();
+ }
+ }
+ provider->Release();
+ }
+
+ return success;
+}
+} // namespace gpu
diff --git a/gpu/config/gpu_feature_type.h b/gpu/config/gpu_feature_type.h
new file mode 100644
index 0000000..b082d78
--- /dev/null
+++ b/gpu/config/gpu_feature_type.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_FEATURE_TYPE_H_
+#define GPU_CONFIG_GPU_FEATURE_TYPE_H_
+
+namespace gpu {
+
+// Provides flags indicating which gpu features are blacklisted for the system
+// on which chrome is currently running.
+// If a bit is set to 1, corresponding feature is blacklisted.
+enum GpuFeatureType {
+ GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS = 0,
+ GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING,
+ GPU_FEATURE_TYPE_WEBGL,
+ GPU_FEATURE_TYPE_MULTISAMPLING,
+ GPU_FEATURE_TYPE_FLASH3D,
+ GPU_FEATURE_TYPE_FLASH_STAGE3D,
+ GPU_FEATURE_TYPE_TEXTURE_SHARING,
+ GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE,
+ GPU_FEATURE_TYPE_3D_CSS,
+ GPU_FEATURE_TYPE_ACCELERATED_VIDEO,
+ GPU_FEATURE_TYPE_PANEL_FITTING,
+ GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE,
+ GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE,
+ NUMBER_OF_GPU_FEATURE_TYPES
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_FEATURE_TYPE_H_
diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc
new file mode 100644
index 0000000..8c2f9cc
--- /dev/null
+++ b/gpu/config/gpu_info.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_info.h"
+
+namespace gpu {
+
+GPUInfo::GPUDevice::GPUDevice()
+ : vendor_id(0),
+ device_id(0) {
+}
+
+GPUInfo::GPUDevice::~GPUDevice() { }
+
+GPUInfo::GPUInfo()
+ : finalized(false),
+ optimus(false),
+ amd_switchable(false),
+ lenovo_dcute(false),
+ adapter_luid(0),
+ can_lose_context(false),
+ gpu_accessible(true),
+ software_rendering(false),
+ sandboxed(false) {
+}
+
+GPUInfo::~GPUInfo() { }
+
+} // namespace gpu
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h
new file mode 100644
index 0000000..f8d9b60
--- /dev/null
+++ b/gpu/config/gpu_info.h
@@ -0,0 +1,137 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_INFO_H_
+#define GPU_CONFIG_GPU_INFO_H_
+
+// Provides access to the GPU information for the system
+// on which chrome is currently running.
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/time.h"
+#include "base/version.h"
+#include "build/build_config.h"
+#include "gpu/config/dx_diag_node.h"
+#include "gpu/config/gpu_performance_stats.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+
+struct GPU_EXPORT GPUInfo {
+ struct GPU_EXPORT GPUDevice {
+ GPUDevice();
+ ~GPUDevice();
+
+ // The DWORD (uint32) representing the graphics card vendor id.
+ uint32 vendor_id;
+
+ // The DWORD (uint32) representing the graphics card device id.
+ // Device ids are unique to vendor, not to one another.
+ uint32 device_id;
+
+ // The strings that describe the GPU.
+ // In Linux these strings are obtained through libpci.
+ // In Win/MacOSX, these two strings are not filled at the moment.
+ std::string vendor_string;
+ std::string device_string;
+ };
+
+ GPUInfo();
+ ~GPUInfo();
+
+ // Whether more GPUInfo fields might be collected in the future.
+ bool finalized;
+
+ // The amount of time taken to get from the process starting to the message
+ // loop being pumped.
+ base::TimeDelta initialization_time;
+
+ // Computer has NVIDIA Optimus
+ bool optimus;
+
+ // Computer has AMD Dynamic Switchable Graphics
+ bool amd_switchable;
+
+ // Lenovo dCute is installed. http://crbug.com/181665.
+ bool lenovo_dcute;
+
+ // Version of DisplayLink driver installed. Zero if not installed.
+ // http://crbug.com/177611.
+ Version display_link_version;
+
+ // Primary GPU, for exmaple, the discrete GPU in a dual GPU machine.
+ GPUDevice gpu;
+
+ // Secondary GPUs, for example, the integrated GPU in a dual GPU machine.
+ std::vector<GPUDevice> secondary_gpus;
+
+ // On Windows, the unique identifier of the adapter the GPU process uses.
+ // The default is zero, which makes the browser process create its D3D device
+ // on the primary adapter. Note that the primary adapter can change at any
+ // time so it is better to specify a particular LUID. Note that valid LUIDs
+ // are always non-zero.
+ uint64 adapter_luid;
+
+ // The vendor of the graphics driver currently installed.
+ std::string driver_vendor;
+
+ // The version of the graphics driver currently installed.
+ std::string driver_version;
+
+ // The date of the graphics driver currently installed.
+ std::string driver_date;
+
+ // The version of the pixel/fragment shader used by the gpu.
+ std::string pixel_shader_version;
+
+ // The version of the vertex shader used by the gpu.
+ std::string vertex_shader_version;
+
+ // The machine model identifier with format "name major.minor".
+ // Name should not contain any whitespaces.
+ std::string machine_model;
+
+ // The version of OpenGL we are using.
+ // TODO(zmo): should be able to tell if it's GL or GLES.
+ std::string gl_version;
+
+ // The GL_VERSION string. "" if we are not using OpenGL.
+ std::string gl_version_string;
+
+ // The GL_VENDOR string. "" if we are not using OpenGL.
+ std::string gl_vendor;
+
+ // The GL_RENDERER string. "" if we are not using OpenGL.
+ std::string gl_renderer;
+
+ // The GL_EXTENSIONS string. "" if we are not using OpenGL.
+ std::string gl_extensions;
+
+ // The device semantics, i.e. whether the Vista and Windows 7 specific
+ // semantics are available.
+ bool can_lose_context;
+
+ // Whether gpu or driver is accessible.
+ bool gpu_accessible;
+
+ // By default all values are 0.
+ GpuPerformanceStats performance_stats;
+
+ bool software_rendering;
+
+ // Whether the gpu process is running in a sandbox.
+ bool sandboxed;
+
+#if defined(OS_WIN)
+ // The information returned by the DirectX Diagnostics Tool.
+ DxDiagNode dx_diagnostics;
+#endif
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_INFO_H_
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
new file mode 100644
index 0000000..eb40dfc
--- /dev/null
+++ b/gpu/config/gpu_info_collector.cc
@@ -0,0 +1,140 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_info_collector.h"
+
+#include <string>
+#include <vector>
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+
+namespace {
+
+scoped_refptr<gfx::GLSurface> InitializeGLSurface() {
+ scoped_refptr<gfx::GLSurface> surface(
+ gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)));
+ if (!surface) {
+ LOG(ERROR) << "gfx::GLContext::CreateOffscreenGLSurface failed";
+ return NULL;
+ }
+
+ return surface;
+}
+
+scoped_refptr<gfx::GLContext> InitializeGLContext(gfx::GLSurface* surface) {
+
+ scoped_refptr<gfx::GLContext> context(
+ gfx::GLContext::CreateGLContext(NULL,
+ surface,
+ gfx::PreferIntegratedGpu));
+ if (!context) {
+ LOG(ERROR) << "gfx::GLContext::CreateGLContext failed";
+ return NULL;
+ }
+
+ if (!context->MakeCurrent(surface)) {
+ LOG(ERROR) << "gfx::GLContext::MakeCurrent() failed";
+ return NULL;
+ }
+
+ return context;
+}
+
+std::string GetGLString(unsigned int pname) {
+ const char* gl_string =
+ reinterpret_cast<const char*>(glGetString(pname));
+ if (gl_string)
+ return std::string(gl_string);
+ return std::string();
+}
+
+// Return a version string in the format of "major.minor".
+std::string GetVersionFromString(const std::string& version_string) {
+ size_t begin = version_string.find_first_of("0123456789");
+ if (begin != std::string::npos) {
+ size_t end = version_string.find_first_not_of("01234567890.", begin);
+ std::string sub_string;
+ if (end != std::string::npos)
+ sub_string = version_string.substr(begin, end - begin);
+ else
+ sub_string = version_string.substr(begin);
+ std::vector<std::string> pieces;
+ base::SplitString(sub_string, '.', &pieces);
+ if (pieces.size() >= 2)
+ return pieces[0] + "." + pieces[1];
+ }
+ return std::string();
+}
+
+} // namespace anonymous
+
+namespace gpu {
+
+bool CollectGraphicsInfoGL(GPUInfo* gpu_info) {
+ TRACE_EVENT0("startup", "gpu_info_collector::CollectGraphicsInfoGL");
+ if (!gfx::GLSurface::InitializeOneOff()) {
+ LOG(ERROR) << "gfx::GLSurface::InitializeOneOff() failed";
+ return false;
+ }
+
+ scoped_refptr<gfx::GLSurface> surface(InitializeGLSurface());
+ if (!surface)
+ return false;
+
+ scoped_refptr<gfx::GLContext> context(InitializeGLContext(surface.get()));
+ if (!context)
+ return false;
+
+ gpu_info->gl_renderer = GetGLString(GL_RENDERER);
+ gpu_info->gl_vendor = GetGLString(GL_VENDOR);
+ gpu_info->gl_extensions = GetGLString(GL_EXTENSIONS);
+ gpu_info->gl_version_string = GetGLString(GL_VERSION);
+ std::string glsl_version_string = GetGLString(GL_SHADING_LANGUAGE_VERSION);
+ // TODO(kbr): remove once the destruction of a current context automatically
+ // clears the current context.
+ context->ReleaseCurrent(surface.get());
+
+ gpu_info->gl_version = GetVersionFromString(gpu_info->gl_version_string);
+ std::string glsl_version = GetVersionFromString(glsl_version_string);
+ gpu_info->pixel_shader_version = glsl_version;
+ gpu_info->vertex_shader_version = glsl_version;
+
+ return CollectDriverInfoGL(gpu_info);
+}
+
+void MergeGPUInfoGL(GPUInfo* basic_gpu_info,
+ const GPUInfo& context_gpu_info) {
+ DCHECK(basic_gpu_info);
+ basic_gpu_info->gl_renderer = context_gpu_info.gl_renderer;
+ basic_gpu_info->gl_vendor = context_gpu_info.gl_vendor;
+ basic_gpu_info->gl_version_string = context_gpu_info.gl_version_string;
+ basic_gpu_info->gl_extensions = context_gpu_info.gl_extensions;
+ basic_gpu_info->gl_version = context_gpu_info.gl_version;
+ basic_gpu_info->pixel_shader_version =
+ context_gpu_info.pixel_shader_version;
+ basic_gpu_info->vertex_shader_version =
+ context_gpu_info.vertex_shader_version;
+
+ if (!context_gpu_info.driver_vendor.empty())
+ basic_gpu_info->driver_vendor = context_gpu_info.driver_vendor;
+ if (!context_gpu_info.driver_version.empty())
+ basic_gpu_info->driver_version = context_gpu_info.driver_version;
+
+ basic_gpu_info->can_lose_context = context_gpu_info.can_lose_context;
+ basic_gpu_info->sandboxed = context_gpu_info.sandboxed;
+ basic_gpu_info->gpu_accessible = context_gpu_info.gpu_accessible;
+ basic_gpu_info->finalized = context_gpu_info.finalized;
+ basic_gpu_info->initialization_time = context_gpu_info.initialization_time;
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_info_collector.h b/gpu/config/gpu_info_collector.h
new file mode 100644
index 0000000..e89535a
--- /dev/null
+++ b/gpu/config/gpu_info_collector.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_INFO_COLLECTOR_H_
+#define GPU_CONFIG_GPU_INFO_COLLECTOR_H_
+
+#include "base/basictypes.h"
+#include "build/build_config.h"
+#include "gpu/config/gpu_info.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+
+enum GpuIDResult {
+ kGpuIDFailure,
+ kGpuIDSuccess,
+ kGpuIDNotSupported
+};
+
+// Collect GPU vendor_id and device ID.
+GPU_EXPORT GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id);
+
+// Collects basic GPU info without creating a GL/DirectX context (and without
+// the danger of crashing), including vendor_id and device_id.
+// This is called at browser process startup time.
+// The subset each platform collects may be different.
+GPU_EXPORT bool CollectBasicGraphicsInfo(GPUInfo* gpu_info);
+
+// Create a GL/DirectX context and collect related info.
+// This is called at GPU process startup time.
+// Returns true on success.
+GPU_EXPORT bool CollectContextGraphicsInfo(GPUInfo* gpu_info);
+
+#if defined(OS_WIN)
+// Collect the DirectX Disagnostics information about the attached displays.
+GPU_EXPORT bool GetDxDiagnostics(DxDiagNode* output);
+#endif // OS_WIN
+
+// Create a GL context and collect GL strings and versions.
+GPU_EXPORT bool CollectGraphicsInfoGL(GPUInfo* gpu_info);
+
+// Each platform stores the driver version on the GL_VERSION string differently
+GPU_EXPORT bool CollectDriverInfoGL(GPUInfo* gpu_info);
+
+// Merge GPUInfo from CollectContextGraphicsInfo into basic GPUInfo.
+// This is platform specific, depending on which info are collected at which
+// stage.
+GPU_EXPORT void MergeGPUInfo(GPUInfo* basic_gpu_info,
+ const GPUInfo& context_gpu_info);
+
+// MergeGPUInfo() when GL driver is used.
+GPU_EXPORT void MergeGPUInfoGL(GPUInfo* basic_gpu_info,
+ const GPUInfo& context_gpu_info);
+
+// Advanced Micro Devices has interesting configurations on laptops were
+// there are two videocards that can alternatively a given process output.
+enum AMDVideoCardType {
+ UNKNOWN,
+ STANDALONE,
+ INTEGRATED,
+ SWITCHABLE
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_INFO_COLLECTOR_H_
diff --git a/gpu/config/gpu_info_collector_android.cc b/gpu/config/gpu_info_collector_android.cc
new file mode 100644
index 0000000..905fedf
--- /dev/null
+++ b/gpu/config/gpu_info_collector_android.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_info_collector.h"
+
+#include "base/android/build_info.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+
+namespace {
+
+std::string GetDriverVersionFromString(const std::string& version_string) {
+ // Extract driver version from the second number in a string like:
+ // "OpenGL ES 2.0 V@6.0 AU@ (CL@2946718)"
+
+ // Exclude first "2.0".
+ size_t begin = version_string.find_first_of("0123456789");
+ if (begin == std::string::npos)
+ return "0";
+ size_t end = version_string.find_first_not_of("01234567890.", begin);
+
+ // Extract number of the form "%d.%d"
+ begin = version_string.find_first_of("0123456789", end);
+ if (begin == std::string::npos)
+ return "0";
+ end = version_string.find_first_not_of("01234567890.", begin);
+ std::string sub_string;
+ if (end != std::string::npos)
+ sub_string = version_string.substr(begin, end - begin);
+ else
+ sub_string = version_string.substr(begin);
+ std::vector<std::string> pieces;
+ base::SplitString(sub_string, '.', &pieces);
+ if (pieces.size() < 2)
+ return "0";
+ return pieces[0] + "." + pieces[1];
+}
+
+}
+
+namespace gpu {
+
+bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
+ return CollectBasicGraphicsInfo(gpu_info);
+}
+
+GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
+ DCHECK(vendor_id && device_id);
+ *vendor_id = 0;
+ *device_id = 0;
+ return kGpuIDNotSupported;
+}
+
+bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
+ gpu_info->can_lose_context = false;
+ gpu_info->finalized = true;
+
+ gpu_info->machine_model = base::android::BuildInfo::GetInstance()->model();
+
+ // Create a short-lived context on the UI thread to collect the GL strings.
+ return CollectGraphicsInfoGL(gpu_info);
+}
+
+bool CollectDriverInfoGL(GPUInfo* gpu_info) {
+ gpu_info->driver_version = GetDriverVersionFromString(
+ gpu_info->gl_version_string);
+ return true;
+}
+
+void MergeGPUInfo(GPUInfo* basic_gpu_info,
+ const GPUInfo& context_gpu_info) {
+ MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
+}
+
+} // namespace gpu
diff --git a/gpu/config/gpu_info_collector_mac.mm b/gpu/config/gpu_info_collector_mac.mm
new file mode 100644
index 0000000..9698351
--- /dev/null
+++ b/gpu/config/gpu_info_collector_mac.mm
@@ -0,0 +1,220 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_info_collector.h"
+
+#include <vector>
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/mac/mac_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/sys_string_conversions.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_interface.h"
+
+#import <Cocoa/Cocoa.h>
+#import <Foundation/Foundation.h>
+#import <IOKit/IOKitLib.h>
+
+namespace gpu {
+
+namespace {
+
+const UInt32 kVendorIDIntel = 0x8086;
+const UInt32 kVendorIDNVidia = 0x10de;
+const UInt32 kVendorIDAMD = 0x1002;
+
+// Return 0 if we couldn't find the property.
+// The property values we use should not be 0, so it's OK to use 0 as failure.
+UInt32 GetEntryProperty(io_registry_entry_t entry, CFStringRef property_name) {
+ base::mac::ScopedCFTypeRef<CFDataRef> data_ref(static_cast<CFDataRef>(
+ IORegistryEntrySearchCFProperty(entry,
+ kIOServicePlane,
+ property_name,
+ kCFAllocatorDefault,
+ kIORegistryIterateRecursively |
+ kIORegistryIterateParents)));
+ if (!data_ref)
+ return 0;
+
+ UInt32 value = 0;
+ const UInt32* value_pointer =
+ reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data_ref));
+ if (value_pointer != NULL)
+ value = *value_pointer;
+ return value;
+}
+
+// Find the info of the current GPU.
+GPUInfo::GPUDevice GetActiveGPU() {
+ GPUInfo::GPUDevice gpu;
+ io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay);
+ gpu.vendor_id = GetEntryProperty(dsp_port, CFSTR("vendor-id"));
+ gpu.device_id = GetEntryProperty(dsp_port, CFSTR("device-id"));
+ return gpu;
+}
+
+// Scan IO registry for PCI video cards.
+bool CollectPCIVideoCardInfo(GPUInfo* gpu_info) {
+ DCHECK(gpu_info);
+
+ // Collect all GPUs' info.
+ // match_dictionary will be consumed by IOServiceGetMatchingServices, no need
+ // to release it.
+ CFMutableDictionaryRef match_dictionary = IOServiceMatching("IOPCIDevice");
+ io_iterator_t entry_iterator;
+ std::vector<GPUInfo::GPUDevice> gpu_list;
+ if (IOServiceGetMatchingServices(kIOMasterPortDefault,
+ match_dictionary,
+ &entry_iterator) == kIOReturnSuccess) {
+ io_registry_entry_t entry;
+ while ((entry = IOIteratorNext(entry_iterator))) {
+ GPUInfo::GPUDevice gpu;
+ if (GetEntryProperty(entry, CFSTR("class-code")) != 0x30000) {
+ // 0x30000 : DISPLAY_VGA
+ continue;
+ }
+ gpu.vendor_id = GetEntryProperty(entry, CFSTR("vendor-id"));
+ gpu.device_id = GetEntryProperty(entry, CFSTR("device-id"));
+ if (gpu.vendor_id && gpu.device_id)
+ gpu_list.push_back(gpu);
+ }
+ IOObjectRelease(entry_iterator);
+ }
+
+ switch (gpu_list.size()) {
+ case 0:
+ return false;
+ case 1:
+ gpu_info->gpu = gpu_list[0];
+ break;
+ case 2:
+ {
+ int integrated = -1;
+ int discrete = -1;
+ if (gpu_list[0].vendor_id == kVendorIDIntel)
+ integrated = 0;
+ else if (gpu_list[1].vendor_id == kVendorIDIntel)
+ integrated = 1;
+ if (integrated >= 0) {
+ switch (gpu_list[1 - integrated].vendor_id) {
+ case kVendorIDAMD:
+ gpu_info->amd_switchable = true;
+ discrete = 1 - integrated;
+ break;
+ case kVendorIDNVidia:
+ gpu_info->optimus = true;
+ discrete = 1 - integrated;
+ break;
+ default:
+ break;
+ }
+ }
+ if (integrated >= 0 && discrete >= 0) {
+ // We always put discrete GPU as primary for blacklisting purpose.
+ gpu_info->gpu = gpu_list[discrete];
+ gpu_info->secondary_gpus.push_back(gpu_list[integrated]);
+ break;
+ }
+ // If it's not optimus or amd_switchable, we put the current GPU as
+ // primary. Fall through to default.
+ }
+ default:
+ {
+ GPUInfo::GPUDevice active_gpu = GetActiveGPU();
+ size_t current = gpu_list.size();
+ if (active_gpu.vendor_id && active_gpu.device_id) {
+ for (size_t i = 0; i < gpu_list.size(); ++i) {
+ if (gpu_list[i].vendor_id == active_gpu.vendor_id &&
+ gpu_list[i].device_id == active_gpu.device_id) {
+ current = i;
+ break;
+ }
+ }
+ }
+ if (current == gpu_list.size()) {
+ // If we fail to identify the current GPU, select any one as primary.
+ current = 0;
+ }
+ for (size_t i = 0; i < gpu_list.size(); ++i) {
+ if (i == current)
+ gpu_info->gpu = gpu_list[i];
+ else
+ gpu_info->secondary_gpus.push_back(gpu_list[i]);
+ }
+ }
+ break;
+ }
+ return (gpu_info->gpu.vendor_id && gpu_info->gpu.device_id);
+}
+
+} // namespace anonymous
+
+bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
+ DCHECK(gpu_info);
+
+ TRACE_EVENT0("gpu", "gpu_info_collector::CollectGraphicsInfo");
+
+ gpu_info->can_lose_context =
+ (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2);
+ gpu_info->finalized = true;
+ return CollectGraphicsInfoGL(gpu_info);
+}
+
+GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
+ DCHECK(vendor_id && device_id);
+ *vendor_id = 0;
+ *device_id = 0;
+
+ GPUInfo gpu_info;
+ if (CollectPCIVideoCardInfo(&gpu_info)) {
+ *vendor_id = gpu_info.gpu.vendor_id;
+ *device_id = gpu_info.gpu.device_id;
+ return kGpuIDSuccess;
+ }
+ return kGpuIDFailure;
+}
+
+bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
+ DCHECK(gpu_info);
+
+ std::string model_name;
+ int32 model_major = 0, model_minor = 0;
+ base::mac::ParseModelIdentifier(base::mac::GetModelIdentifier(),
+ &model_name, &model_major, &model_minor);
+ ReplaceChars(model_name, " ", "_", &gpu_info->machine_model);
+ gpu_info->machine_model += " " + base::IntToString(model_major) +
+ "." + base::IntToString(model_minor);
+
+ return CollectPCIVideoCardInfo(gpu_info);
+}
+
+bool CollectDriverInfoGL(GPUInfo* gpu_info) {
+ DCHECK(gpu_info);
+
+ // Extract the OpenGL driver version string from the GL_VERSION string.
+ // Mac OpenGL drivers have the driver version
+ // at the end of the gl version string preceded by a dash.
+ // Use some jiggery-pokery to turn that utf8 string into a std::wstring.
+ std::string gl_version_string = gpu_info->gl_version_string;
+ size_t pos = gl_version_string.find_last_of('-');
+ if (pos == std::string::npos)
+ return false;
+ gpu_info->driver_version = gl_version_string.substr(pos + 1);
+ return true;
+}
+
+void MergeGPUInfo(GPUInfo* basic_gpu_info,
+ const GPUInfo& context_gpu_info) {
+ MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
+}
+
+} // namespace gpu
diff --git a/gpu/config/gpu_info_collector_ozone.cc b/gpu/config/gpu_info_collector_ozone.cc
new file mode 100644
index 0000000..acef6ae
--- /dev/null
+++ b/gpu/config/gpu_info_collector_ozone.cc
@@ -0,0 +1,37 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_info_collector.h"
+
+#include "base/logging.h"
+
+namespace gpu {
+
+bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
+ return CollectBasicGraphicsInfo(gpu_info);
+}
+
+GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
+ DCHECK(vendor_id && device_id);
+ *vendor_id = 0;
+ *device_id = 0;
+ return kGpuIDNotSupported;
+}
+
+bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
+ gpu_info->can_lose_context = false;
+ return true;
+}
+
+bool CollectDriverInfoGL(GPUInfo* gpu_info) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void MergeGPUInfo(GPUInfo* basic_gpu_info,
+ const GPUInfo& context_gpu_info) {
+ MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
+}
+
+} // namespace gpu_info_collector
diff --git a/gpu/config/gpu_info_collector_unittest.cc b/gpu/config/gpu_info_collector_unittest.cc
new file mode 100644
index 0000000..5e61ee2
--- /dev/null
+++ b/gpu/config/gpu_info_collector_unittest.cc
@@ -0,0 +1,186 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_info_collector.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_mock.h"
+
+using ::gfx::MockGLInterface;
+using ::testing::Return;
+
+namespace gpu {
+
+class GPUInfoCollectorTest : public testing::Test {
+ public:
+ GPUInfoCollectorTest() {}
+ virtual ~GPUInfoCollectorTest() { }
+
+ virtual void SetUp() {
+ // TODO(kbr): make this setup robust in the case where
+ // GLSurface::InitializeOneOff() has already been called by
+ // another unit test. http://crbug.com/100285
+ gfx::InitializeGLBindings(gfx::kGLImplementationMockGL);
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
+#if defined(OS_WIN)
+ const uint32 vendor_id = 0x10de;
+ const uint32 device_id = 0x0658;
+ const char* driver_vendor = ""; // not implemented
+ const char* driver_version = "";
+ const char* shader_version = "1.40";
+ const char* gl_version = "3.1";
+ const char* gl_renderer = "Quadro FX 380/PCI/SSE2";
+ const char* gl_vendor = "NVIDIA Corporation";
+ const char* gl_version_string = "3.1.0";
+ const char* gl_shading_language_version = "1.40 NVIDIA via Cg compiler";
+ const char* gl_extensions =
+ "GL_OES_packed_depth_stencil GL_EXT_texture_format_BGRA8888 "
+ "GL_EXT_read_format_bgra";
+#elif defined(OS_MACOSX)
+ const uint32 vendor_id = 0x10de;
+ const uint32 device_id = 0x0640;
+ const char* driver_vendor = ""; // not implemented
+ const char* driver_version = "1.6.18";
+ const char* shader_version = "1.20";
+ const char* gl_version = "2.1";
+ const char* gl_renderer = "NVIDIA GeForce GT 120 OpenGL Engine";
+ const char* gl_vendor = "NVIDIA Corporation";
+ const char* gl_version_string = "2.1 NVIDIA-1.6.18";
+ const char* gl_shading_language_version = "1.20 ";
+ const char* gl_extensions =
+ "GL_OES_packed_depth_stencil GL_EXT_texture_format_BGRA8888 "
+ "GL_EXT_read_format_bgra";
+#else // defined (OS_LINUX)
+ const uint32 vendor_id = 0x10de;
+ const uint32 device_id = 0x0658;
+ const char* driver_vendor = "NVIDIA";
+ const char* driver_version = "195.36.24";
+ const char* shader_version = "1.50";
+ const char* gl_version = "3.2";
+ const char* gl_renderer = "Quadro FX 380/PCI/SSE2";
+ const char* gl_vendor = "NVIDIA Corporation";
+ const char* gl_version_string = "3.2.0 NVIDIA 195.36.24";
+ const char* gl_shading_language_version = "1.50 NVIDIA via Cg compiler";
+ const char* gl_extensions =
+ "GL_OES_packed_depth_stencil GL_EXT_texture_format_BGRA8888 "
+ "GL_EXT_read_format_bgra";
+#endif
+ test_values_.gpu.vendor_id = vendor_id;
+ test_values_.gpu.device_id = device_id;
+ test_values_.driver_vendor = driver_vendor;
+ test_values_.driver_version =driver_version;
+ test_values_.pixel_shader_version = shader_version;
+ test_values_.vertex_shader_version = shader_version;
+ test_values_.gl_version = gl_version;
+ test_values_.gl_renderer = gl_renderer;
+ test_values_.gl_vendor = gl_vendor;
+ test_values_.gl_version_string = gl_version_string;
+ test_values_.gl_extensions = gl_extensions;
+ test_values_.can_lose_context = false;
+
+ EXPECT_CALL(*gl_, GetString(GL_EXTENSIONS))
+ .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>(
+ gl_extensions)));
+ EXPECT_CALL(*gl_, GetString(GL_SHADING_LANGUAGE_VERSION))
+ .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>(
+ gl_shading_language_version)));
+ EXPECT_CALL(*gl_, GetString(GL_VERSION))
+ .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>(
+ gl_version_string)));
+ EXPECT_CALL(*gl_, GetString(GL_VENDOR))
+ .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>(
+ gl_vendor)));
+ EXPECT_CALL(*gl_, GetString(GL_RENDERER))
+ .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>(
+ gl_renderer)));
+ }
+
+ virtual void TearDown() {
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
+ }
+
+ public:
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
+ GPUInfo test_values_;
+};
+
+// TODO(rlp): Test the vendor and device id collection if deemed necessary as
+// it involves several complicated mocks for each platform.
+
+// TODO(kbr): re-enable these tests; see http://crbug.com/100285 .
+
+TEST_F(GPUInfoCollectorTest, DISABLED_DriverVendorGL) {
+ GPUInfo gpu_info;
+ CollectGraphicsInfoGL(&gpu_info);
+ EXPECT_EQ(test_values_.driver_vendor,
+ gpu_info.driver_vendor);
+}
+
+// Skip Windows because the driver version is obtained from bot registry.
+#if !defined(OS_WIN)
+TEST_F(GPUInfoCollectorTest, DISABLED_DriverVersionGL) {
+ GPUInfo gpu_info;
+ CollectGraphicsInfoGL(&gpu_info);
+ EXPECT_EQ(test_values_.driver_version,
+ gpu_info.driver_version);
+}
+#endif
+
+TEST_F(GPUInfoCollectorTest, DISABLED_PixelShaderVersionGL) {
+ GPUInfo gpu_info;
+ CollectGraphicsInfoGL(&gpu_info);
+ EXPECT_EQ(test_values_.pixel_shader_version,
+ gpu_info.pixel_shader_version);
+}
+
+TEST_F(GPUInfoCollectorTest, DISABLED_VertexShaderVersionGL) {
+ GPUInfo gpu_info;
+ CollectGraphicsInfoGL(&gpu_info);
+ EXPECT_EQ(test_values_.vertex_shader_version,
+ gpu_info.vertex_shader_version);
+}
+
+TEST_F(GPUInfoCollectorTest, DISABLED_GLVersionGL) {
+ GPUInfo gpu_info;
+ CollectGraphicsInfoGL(&gpu_info);
+ EXPECT_EQ(test_values_.gl_version,
+ gpu_info.gl_version);
+}
+
+TEST_F(GPUInfoCollectorTest, DISABLED_GLVersionStringGL) {
+ GPUInfo gpu_info;
+ CollectGraphicsInfoGL(&gpu_info);
+ EXPECT_EQ(test_values_.gl_version_string,
+ gpu_info.gl_version_string);
+}
+
+TEST_F(GPUInfoCollectorTest, DISABLED_GLRendererGL) {
+ GPUInfo gpu_info;
+ CollectGraphicsInfoGL(&gpu_info);
+ EXPECT_EQ(test_values_.gl_renderer,
+ gpu_info.gl_renderer);
+}
+
+TEST_F(GPUInfoCollectorTest, DISABLED_GLVendorGL) {
+ GPUInfo gpu_info;
+ CollectGraphicsInfoGL(&gpu_info);
+ EXPECT_EQ(test_values_.gl_vendor,
+ gpu_info.gl_vendor);
+}
+
+TEST_F(GPUInfoCollectorTest, DISABLED_GLExtensionsGL) {
+ GPUInfo gpu_info;
+ CollectGraphicsInfoGL(&gpu_info);
+ EXPECT_EQ(test_values_.gl_extensions,
+ gpu_info.gl_extensions);
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_info_collector_win.cc b/gpu/config/gpu_info_collector_win.cc
new file mode 100644
index 0000000..de96450
--- /dev/null
+++ b/gpu/config/gpu_info_collector_win.cc
@@ -0,0 +1,654 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_info_collector.h"
+
+// This has to be included before windows.h.
+#include "third_party/re2/re2/re2.h"
+
+#include <windows.h>
+#include <d3d9.h>
+#include <d3d11.h>
+#include <dxgi.h>
+#include <setupapi.h>
+
+#include "base/command_line.h"
+#include "base/debug/trace_event.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "base/scoped_native_library.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/string16.h"
+#include "base/stringprintf.h"
+#include "base/threading/thread.h"
+#include "base/threading/worker_pool.h"
+#include "base/win/registry.h"
+#include "base/win/scoped_com_initializer.h"
+#include "base/win/scoped_comptr.h"
+#include "base/win/windows_version.h"
+#include "third_party/libxml/chromium/libxml_utils.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_egl.h"
+
+namespace gpu {
+
+namespace {
+
+// This must be kept in sync with histograms.xml.
+enum DisplayLinkInstallationStatus {
+ DISPLAY_LINK_NOT_INSTALLED,
+ DISPLAY_LINK_7_1_OR_EARLIER,
+ DISPLAY_LINK_7_2_OR_LATER,
+ DISPLAY_LINK_INSTALLATION_STATUS_MAX
+};
+
+float ReadXMLFloatValue(XmlReader* reader) {
+ std::string score_string;
+ if (!reader->ReadElementContent(&score_string))
+ return 0.0;
+
+ double score;
+ if (!base::StringToDouble(score_string, &score))
+ return 0.0;
+
+ return static_cast<float>(score);
+}
+
+GpuPerformanceStats RetrieveGpuPerformanceStats() {
+ TRACE_EVENT0("gpu", "RetrieveGpuPerformanceStats");
+
+ // If the user re-runs the assessment without restarting, the COM API
+ // returns WINSAT_ASSESSMENT_STATE_NOT_AVAILABLE. Because of that and
+ // http://crbug.com/124325, read the assessment result files directly.
+ GpuPerformanceStats stats;
+
+ // Get path to WinSAT results files.
+ wchar_t winsat_results_path[MAX_PATH];
+ DWORD size = ExpandEnvironmentStrings(
+ L"%WinDir%\\Performance\\WinSAT\\DataStore\\",
+ winsat_results_path, MAX_PATH);
+ if (size == 0 || size > MAX_PATH) {
+ LOG(ERROR) << "The path to the WinSAT results is too long: "
+ << size << " chars.";
+ return stats;
+ }
+
+ // Find most recent formal assessment results.
+ file_util::FileEnumerator file_enumerator(
+ base::FilePath(winsat_results_path),
+ false, // not recursive
+ file_util::FileEnumerator::FILES,
+ FILE_PATH_LITERAL("* * Formal.Assessment (*).WinSAT.xml"));
+
+ base::FilePath current_results;
+ for (base::FilePath results = file_enumerator.Next(); !results.empty();
+ results = file_enumerator.Next()) {
+ // The filenames start with the date and time as yyyy-mm-dd hh.mm.ss.xxx,
+ // so the greatest file lexicographically is also the most recent file.
+ if (base::FilePath::CompareLessIgnoreCase(current_results.value(),
+ results.value()))
+ current_results = results;
+ }
+
+ std::string current_results_string = current_results.MaybeAsASCII();
+ if (current_results_string.empty()) {
+ LOG(ERROR) << "Can't retrieve a valid WinSAT assessment.";
+ return stats;
+ }
+
+ // Get relevant scores from results file. XML schema at:
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/aa969210.aspx
+ XmlReader reader;
+ if (!reader.LoadFile(current_results_string)) {
+ LOG(ERROR) << "Could not open WinSAT results file.";
+ return stats;
+ }
+ // Descend into <WinSAT> root element.
+ if (!reader.SkipToElement() || !reader.Read()) {
+ LOG(ERROR) << "Could not read WinSAT results file.";
+ return stats;
+ }
+
+ // Search for <WinSPR> element containing the results.
+ do {
+ if (reader.NodeName() == "WinSPR")
+ break;
+ } while (reader.Next());
+ // Descend into <WinSPR> element.
+ if (!reader.Read()) {
+ LOG(ERROR) << "Could not find WinSPR element in results file.";
+ return stats;
+ }
+
+ // Read scores.
+ for (int depth = reader.Depth(); reader.Depth() == depth; reader.Next()) {
+ std::string node_name = reader.NodeName();
+ if (node_name == "SystemScore")
+ stats.overall = ReadXMLFloatValue(&reader);
+ else if (node_name == "GraphicsScore")
+ stats.graphics = ReadXMLFloatValue(&reader);
+ else if (node_name == "GamingScore")
+ stats.gaming = ReadXMLFloatValue(&reader);
+ }
+
+ if (stats.overall == 0.0)
+ LOG(ERROR) << "Could not read overall score from assessment results.";
+ if (stats.graphics == 0.0)
+ LOG(ERROR) << "Could not read graphics score from assessment results.";
+ if (stats.gaming == 0.0)
+ LOG(ERROR) << "Could not read gaming score from assessment results.";
+
+ return stats;
+}
+
+GpuPerformanceStats RetrieveGpuPerformanceStatsWithHistograms() {
+ base::TimeTicks start_time = base::TimeTicks::Now();
+
+ GpuPerformanceStats stats = RetrieveGpuPerformanceStats();
+
+ UMA_HISTOGRAM_TIMES("GPU.WinSAT.ReadResultsFileTime",
+ base::TimeTicks::Now() - start_time);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.OverallScore2",
+ stats.overall * 10, 10, 200, 50);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GraphicsScore2",
+ stats.graphics * 10, 10, 200, 50);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GamingScore2",
+ stats.gaming * 10, 10, 200, 50);
+ UMA_HISTOGRAM_BOOLEAN(
+ "GPU.WinSAT.HasResults",
+ stats.overall != 0.0 && stats.graphics != 0.0 && stats.gaming != 0.0);
+
+ return stats;
+}
+
+// Returns the display link driver version or an invalid version if it is
+// not installed.
+Version DisplayLinkVersion() {
+ base::win::RegKey key;
+
+ if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY))
+ return Version();
+
+ if (key.OpenKey(L"DisplayLink", KEY_READ | KEY_WOW64_64KEY))
+ return Version();
+
+ if (key.OpenKey(L"Core", KEY_READ | KEY_WOW64_64KEY))
+ return Version();
+
+ string16 version;
+ if (key.ReadValue(L"Version", &version))
+ return Version();
+
+ return Version(WideToASCII(version));
+}
+
+// Returns whether Lenovo dCute is installed.
+bool IsLenovoDCuteInstalled() {
+ base::win::RegKey key;
+
+ if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY))
+ return false;
+
+ if (key.OpenKey(L"Lenovo", KEY_READ | KEY_WOW64_64KEY))
+ return false;
+
+ if (key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY))
+ return false;
+
+ return true;
+}
+
+// Determines whether D3D11 won't work, either because it is not supported on
+// the machine or because it is known it is likely to crash.
+bool D3D11ShouldWork(const GPUInfo& gpu_info) {
+ // Windows XP never supports D3D11.
+ if (base::win::GetVersion() <= base::win::VERSION_XP)
+ return false;
+
+ // Intel?
+ if (gpu_info.gpu.vendor_id == 0x8086) {
+ // 2nd Generation Core Processor Family Integrated Graphics Controller
+ // or Intel Ivy Bridge?
+ if (gpu_info.gpu.device_id == 0x0102 ||
+ gpu_info.gpu.device_id == 0x0106 ||
+ gpu_info.gpu.device_id == 0x0116 ||
+ gpu_info.gpu.device_id == 0x0126 ||
+ gpu_info.gpu.device_id == 0x0152 ||
+ gpu_info.gpu.device_id == 0x0156 ||
+ gpu_info.gpu.device_id == 0x015a ||
+ gpu_info.gpu.device_id == 0x0162 ||
+ gpu_info.gpu.device_id == 0x0166) {
+ // http://crbug.com/196373.
+ if (base::win::GetVersion() == base::win::VERSION_VISTA)
+ return false;
+
+ // http://crbug.com/175525.
+ if (gpu_info.display_link_version.IsValid())
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Collects information about the level of D3D11 support and records it in
+// the UMA stats. Records no stats when D3D11 in not supported at all.
+void CollectD3D11SupportOnWorkerThread() {
+ TRACE_EVENT0("gpu", "CollectD3D11Support");
+
+ typedef HRESULT (WINAPI *D3D11CreateDeviceFunc)(
+ IDXGIAdapter* adapter,
+ D3D_DRIVER_TYPE driver_type,
+ HMODULE software,
+ UINT flags,
+ const D3D_FEATURE_LEVEL* feature_levels,
+ UINT num_feature_levels,
+ UINT sdk_version,
+ ID3D11Device** device,
+ D3D_FEATURE_LEVEL* feature_level,
+ ID3D11DeviceContext** immediate_context);
+
+ // This enumeration must be kept in sync with histograms.xml. Do not reorder
+ // the members; always add to the end.
+ enum FeatureLevel {
+ FEATURE_LEVEL_UNKNOWN,
+ FEATURE_LEVEL_NO_D3D11_DLL,
+ FEATURE_LEVEL_NO_CREATE_DEVICE_ENTRY_POINT,
+ FEATURE_LEVEL_DEVICE_CREATION_FAILED,
+ FEATURE_LEVEL_9_1,
+ FEATURE_LEVEL_9_2,
+ FEATURE_LEVEL_9_3,
+ FEATURE_LEVEL_10_0,
+ FEATURE_LEVEL_10_1,
+ FEATURE_LEVEL_11_0,
+ NUM_FEATURE_LEVELS
+ };
+
+ FeatureLevel feature_level = FEATURE_LEVEL_UNKNOWN;
+ UINT bgra_support = 0;
+
+ // This module is leaked in case it is hooked by third party software.
+ base::NativeLibrary d3d11_module = base::LoadNativeLibrary(
+ base::FilePath(L"d3d11.dll"),
+ NULL);
+
+ if (!d3d11_module) {
+ feature_level = FEATURE_LEVEL_NO_D3D11_DLL;
+ } else {
+ D3D11CreateDeviceFunc create_func =
+ reinterpret_cast<D3D11CreateDeviceFunc>(
+ base::GetFunctionPointerFromNativeLibrary(d3d11_module,
+ "D3D11CreateDevice"));
+ if (!create_func) {
+ feature_level = FEATURE_LEVEL_NO_CREATE_DEVICE_ENTRY_POINT;
+ } else {
+ static const D3D_FEATURE_LEVEL d3d_feature_levels[] = {
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1
+ };
+
+ base::win::ScopedComPtr<ID3D11Device> device;
+ D3D_FEATURE_LEVEL d3d_feature_level;
+ base::win::ScopedComPtr<ID3D11DeviceContext> device_context;
+ HRESULT hr = create_func(NULL,
+ D3D_DRIVER_TYPE_HARDWARE,
+ NULL,
+ 0,
+ d3d_feature_levels,
+ arraysize(d3d_feature_levels),
+ D3D11_SDK_VERSION,
+ device.Receive(),
+ &d3d_feature_level,
+ device_context.Receive());
+ if (FAILED(hr)) {
+ feature_level = FEATURE_LEVEL_DEVICE_CREATION_FAILED;
+ } else {
+ switch (d3d_feature_level) {
+ case D3D_FEATURE_LEVEL_11_0:
+ feature_level = FEATURE_LEVEL_11_0;
+ break;
+ case D3D_FEATURE_LEVEL_10_1:
+ feature_level = FEATURE_LEVEL_10_1;
+ break;
+ case D3D_FEATURE_LEVEL_10_0:
+ feature_level = FEATURE_LEVEL_10_0;
+ break;
+ case D3D_FEATURE_LEVEL_9_3:
+ feature_level = FEATURE_LEVEL_9_3;
+ break;
+ case D3D_FEATURE_LEVEL_9_2:
+ feature_level = FEATURE_LEVEL_9_2;
+ break;
+ case D3D_FEATURE_LEVEL_9_1:
+ feature_level = FEATURE_LEVEL_9_1;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ hr = device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM,
+ &bgra_support);
+ DCHECK(SUCCEEDED(hr));
+ }
+ }
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("GPU.D3D11_FeatureLevel",
+ feature_level,
+ NUM_FEATURE_LEVELS);
+
+ // ANGLE requires at least feature level 10.0. Do not record any further
+ // stats if ANGLE would not work anyway.
+ if (feature_level < FEATURE_LEVEL_10_0)
+ return;
+
+ UMA_HISTOGRAM_BOOLEAN(
+ "GPU.D3D11_B8G8R8A8_Texture2DSupport",
+ (bgra_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0);
+ UMA_HISTOGRAM_BOOLEAN(
+ "GPU.D3D11_B8G8R8A8_RenderTargetSupport",
+ (bgra_support & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0);
+}
+
+// Collects information about the level of D3D11 support and records it in
+// the UMA stats. Records no stats when D3D11 in not supported at all.
+void CollectD3D11Support() {
+ // D3D11 takes about 50ms to initialize so do this on a worker thread.
+ base::WorkerPool::PostTask(
+ FROM_HERE,
+ base::Bind(CollectD3D11SupportOnWorkerThread),
+ false);
+}
+} // namespace anonymous
+
+#if !defined(GOOGLE_CHROME_BUILD)
+AMDVideoCardType GetAMDVideocardType() {
+ return STANDALONE;
+}
+#else
+// This function has a real implementation for official builds that can
+// be found in src/third_party/amd.
+AMDVideoCardType GetAMDVideocardType();
+#endif
+
+bool CollectDriverInfoD3D(const std::wstring& device_id,
+ GPUInfo* gpu_info) {
+ TRACE_EVENT0("gpu", "CollectDriverInfoD3D");
+
+ // create device info for the display device
+ HDEVINFO device_info = SetupDiGetClassDevsW(
+ NULL, device_id.c_str(), NULL,
+ DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
+ if (device_info == INVALID_HANDLE_VALUE) {
+ LOG(ERROR) << "Creating device info failed";
+ return false;
+ }
+
+ DWORD index = 0;
+ bool found = false;
+ SP_DEVINFO_DATA device_info_data;
+ device_info_data.cbSize = sizeof(device_info_data);
+ while (SetupDiEnumDeviceInfo(device_info, index++, &device_info_data)) {
+ WCHAR value[255];
+ if (SetupDiGetDeviceRegistryPropertyW(device_info,
+ &device_info_data,
+ SPDRP_DRIVER,
+ NULL,
+ reinterpret_cast<PBYTE>(value),
+ sizeof(value),
+ NULL)) {
+ HKEY key;
+ std::wstring driver_key = L"System\\CurrentControlSet\\Control\\Class\\";
+ driver_key += value;
+ LONG result = RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE, driver_key.c_str(), 0, KEY_QUERY_VALUE, &key);
+ if (result == ERROR_SUCCESS) {
+ DWORD dwcb_data = sizeof(value);
+ std::string driver_version;
+ result = RegQueryValueExW(
+ key, L"DriverVersion", NULL, NULL,
+ reinterpret_cast<LPBYTE>(value), &dwcb_data);
+ if (result == ERROR_SUCCESS)
+ driver_version = WideToASCII(std::wstring(value));
+
+ std::string driver_date;
+ dwcb_data = sizeof(value);
+ result = RegQueryValueExW(
+ key, L"DriverDate", NULL, NULL,
+ reinterpret_cast<LPBYTE>(value), &dwcb_data);
+ if (result == ERROR_SUCCESS)
+ driver_date = WideToASCII(std::wstring(value));
+
+ std::string driver_vendor;
+ dwcb_data = sizeof(value);
+ result = RegQueryValueExW(
+ key, L"ProviderName", NULL, NULL,
+ reinterpret_cast<LPBYTE>(value), &dwcb_data);
+ if (result == ERROR_SUCCESS) {
+ driver_vendor = WideToASCII(std::wstring(value));
+ if (driver_vendor == "Advanced Micro Devices, Inc." ||
+ driver_vendor == "ATI Technologies Inc.") {
+ // We are conservative and assume that in the absence of a clear
+ // signal the videocard is assumed to be switchable. Additionally,
+ // some switchable systems with Intel GPUs aren't correctly
+ // detected, so always count them.
+ AMDVideoCardType amd_card_type = GetAMDVideocardType();
+ gpu_info->amd_switchable = (gpu_info->gpu.vendor_id == 0x8086) ||
+ (amd_card_type != STANDALONE);
+ }
+ }
+
+ gpu_info->driver_vendor = driver_vendor;
+ gpu_info->driver_version = driver_version;
+ gpu_info->driver_date = driver_date;
+ found = true;
+ RegCloseKey(key);
+ break;
+ }
+ }
+ }
+ SetupDiDestroyDeviceInfoList(device_info);
+ return found;
+}
+
+bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
+ TRACE_EVENT0("gpu", "CollectGraphicsInfo");
+
+ DCHECK(gpu_info);
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) {
+ std::string requested_implementation_name =
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
+ if (requested_implementation_name == "swiftshader") {
+ gpu_info->software_rendering = true;
+ return false;
+ }
+ }
+
+ if (!CollectGraphicsInfoGL(gpu_info))
+ return false;
+
+ // ANGLE's renderer strings are of the form:
+ // ANGLE (<adapter_identifier> Direct3D<version> vs_x_x ps_x_x)
+ std::string direct3d_version;
+ int vertex_shader_major_version = 0;
+ int vertex_shader_minor_version = 0;
+ int pixel_shader_major_version = 0;
+ int pixel_shader_minor_version = 0;
+ gpu_info->adapter_luid = 0;
+ if (RE2::FullMatch(gpu_info->gl_renderer,
+ "ANGLE \\(.*\\)") &&
+ RE2::PartialMatch(gpu_info->gl_renderer,
+ " Direct3D(\\w+)",
+ &direct3d_version) &&
+ RE2::PartialMatch(gpu_info->gl_renderer,
+ " vs_(\\d+)_(\\d+)",
+ &vertex_shader_major_version,
+ &vertex_shader_minor_version) &&
+ RE2::PartialMatch(gpu_info->gl_renderer,
+ " ps_(\\d+)_(\\d+)",
+ &pixel_shader_major_version,
+ &pixel_shader_minor_version)) {
+ gpu_info->can_lose_context = direct3d_version == "9";
+ gpu_info->vertex_shader_version =
+ base::StringPrintf("%d.%d",
+ vertex_shader_major_version,
+ vertex_shader_minor_version);
+ gpu_info->pixel_shader_version =
+ base::StringPrintf("%d.%d",
+ pixel_shader_major_version,
+ pixel_shader_minor_version);
+
+ // ANGLE's EGL vendor strings are of the form:
+ // Google, Inc. (adapter LUID: 0123456789ABCDEF)
+ // The LUID is optional and identifies the GPU adapter ANGLE is using.
+ const char* egl_vendor = eglQueryString(
+ gfx::GLSurfaceEGL::GetHardwareDisplay(),
+ EGL_VENDOR);
+ RE2::PartialMatch(egl_vendor,
+ " \\(adapter LUID: ([0-9A-Fa-f]{16})\\)",
+ RE2::Hex(&gpu_info->adapter_luid));
+
+ // DirectX diagnostics are collected asynchronously because it takes a
+ // couple of seconds. Do not mark gpu_info as complete until that is done.
+ gpu_info->finalized = false;
+ } else {
+ gpu_info->finalized = true;
+ }
+
+ return true;
+}
+
+GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
+ DCHECK(vendor_id && device_id);
+ *vendor_id = 0;
+ *device_id = 0;
+
+ // Taken from http://developer.nvidia.com/object/device_ids.html
+ DISPLAY_DEVICE dd;
+ dd.cb = sizeof(DISPLAY_DEVICE);
+ std::wstring id;
+ for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) {
+ if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
+ id = dd.DeviceID;
+ break;
+ }
+ }
+
+ if (id.length() > 20) {
+ int vendor = 0, device = 0;
+ std::wstring vendor_string = id.substr(8, 4);
+ std::wstring device_string = id.substr(17, 4);
+ base::HexStringToInt(WideToASCII(vendor_string), &vendor);
+ base::HexStringToInt(WideToASCII(device_string), &device);
+ *vendor_id = vendor;
+ *device_id = device;
+ return kGpuIDSuccess;
+ }
+ return kGpuIDFailure;
+}
+
+bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
+ TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo");
+
+ DCHECK(gpu_info);
+
+ gpu_info->performance_stats = RetrieveGpuPerformanceStatsWithHistograms();
+
+ // nvd3d9wrap.dll is loaded into all processes when Optimus is enabled.
+ HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll");
+ gpu_info->optimus = nvd3d9wrap != NULL;
+
+ gpu_info->lenovo_dcute = IsLenovoDCuteInstalled();
+
+ gpu_info->display_link_version = DisplayLinkVersion();
+
+ if (!gpu_info->display_link_version .IsValid()) {
+ UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
+ DISPLAY_LINK_NOT_INSTALLED,
+ DISPLAY_LINK_INSTALLATION_STATUS_MAX);
+ } else if (gpu_info->display_link_version.IsOlderThan("7.2")) {
+ UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
+ DISPLAY_LINK_7_1_OR_EARLIER,
+ DISPLAY_LINK_INSTALLATION_STATUS_MAX);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
+ DISPLAY_LINK_7_2_OR_LATER,
+ DISPLAY_LINK_INSTALLATION_STATUS_MAX);
+ }
+
+ // Taken from http://developer.nvidia.com/object/device_ids.html
+ DISPLAY_DEVICE dd;
+ dd.cb = sizeof(DISPLAY_DEVICE);
+ std::wstring id;
+ for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) {
+ if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
+ id = dd.DeviceID;
+ break;
+ }
+ }
+
+ if (id.length() <= 20)
+ return false;
+
+ int vendor_id = 0, device_id = 0;
+ string16 vendor_id_string = id.substr(8, 4);
+ string16 device_id_string = id.substr(17, 4);
+ base::HexStringToInt(WideToASCII(vendor_id_string), &vendor_id);
+ base::HexStringToInt(WideToASCII(device_id_string), &device_id);
+ gpu_info->gpu.vendor_id = vendor_id;
+ gpu_info->gpu.device_id = device_id;
+ // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE.
+ if (!CollectDriverInfoD3D(id, gpu_info))
+ return false;
+
+ // Collect basic information about supported D3D11 features. Delay for 45
+ // seconds so as not to regress performance tests.
+ if (D3D11ShouldWork(*gpu_info)) {
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&CollectD3D11Support),
+ base::TimeDelta::FromSeconds(45));
+ }
+
+ return true;
+}
+
+bool CollectDriverInfoGL(GPUInfo* gpu_info) {
+ TRACE_EVENT0("gpu", "CollectDriverInfoGL");
+
+ if (!gpu_info->driver_version.empty())
+ return true;
+
+ std::string gl_version_string = gpu_info->gl_version_string;
+
+ return RE2::PartialMatch(gl_version_string,
+ "([\\d\\.]+)$",
+ &gpu_info->driver_version);
+}
+
+void MergeGPUInfo(GPUInfo* basic_gpu_info,
+ const GPUInfo& context_gpu_info) {
+ DCHECK(basic_gpu_info);
+
+ if (context_gpu_info.software_rendering) {
+ basic_gpu_info->software_rendering = true;
+ return;
+ }
+
+ MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
+
+ basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics;
+}
+
+} // namespace gpu
diff --git a/gpu/config/gpu_info_collector_x11.cc b/gpu/config/gpu_info_collector_x11.cc
new file mode 100644
index 0000000..6a5de82
--- /dev/null
+++ b/gpu/config/gpu_info_collector_x11.cc
@@ -0,0 +1,274 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_info_collector.h"
+
+#include <X11/Xlib.h>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/debug/trace_event.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_tokenizer.h"
+#include "library_loaders/libpci.h"
+#include "third_party/libXNVCtrl/NVCtrl.h"
+#include "third_party/libXNVCtrl/NVCtrlLib.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/gl_switches.h"
+
+namespace gpu {
+
+namespace {
+
+// This checks if a system supports PCI bus.
+// We check the existence of /sys/bus/pci or /sys/bug/pci_express.
+bool IsPciSupported() {
+ const base::FilePath pci_path("/sys/bus/pci/");
+ const base::FilePath pcie_path("/sys/bus/pci_express/");
+ return (file_util::PathExists(pci_path) ||
+ file_util::PathExists(pcie_path));
+}
+
+// Scan /etc/ati/amdpcsdb.default for "ReleaseVersion".
+// Return empty string on failing.
+std::string CollectDriverVersionATI() {
+ const base::FilePath::CharType kATIFileName[] =
+ FILE_PATH_LITERAL("/etc/ati/amdpcsdb.default");
+ base::FilePath ati_file_path(kATIFileName);
+ if (!file_util::PathExists(ati_file_path))
+ return std::string();
+ std::string contents;
+ if (!file_util::ReadFileToString(ati_file_path, &contents))
+ return std::string();
+ base::StringTokenizer t(contents, "\r\n");
+ while (t.GetNext()) {
+ std::string line = t.token();
+ if (StartsWithASCII(line, "ReleaseVersion=", true)) {
+ size_t begin = line.find_first_of("0123456789");
+ if (begin != std::string::npos) {
+ size_t end = line.find_first_not_of("0123456789.", begin);
+ if (end == std::string::npos)
+ return line.substr(begin);
+ else
+ return line.substr(begin, end - begin);
+ }
+ }
+ }
+ return std::string();
+}
+
+// Use NVCtrl extention to query NV driver version.
+// Return empty string on failing.
+std::string CollectDriverVersionNVidia() {
+ Display* display = base::MessagePumpForUI::GetDefaultXDisplay();
+ if (!display) {
+ LOG(ERROR) << "XOpenDisplay failed.";
+ return std::string();
+ }
+ int event_base = 0, error_base = 0;
+ if (!XNVCTRLQueryExtension(display, &event_base, &error_base)) {
+ LOG(INFO) << "NVCtrl extension does not exist.";
+ return std::string();
+ }
+ int screen_count = ScreenCount(display);
+ for (int screen = 0; screen < screen_count; ++screen) {
+ char* buffer = NULL;
+ if (XNVCTRLIsNvScreen(display, screen) &&
+ XNVCTRLQueryStringAttribute(display, screen, 0,
+ NV_CTRL_STRING_NVIDIA_DRIVER_VERSION,
+ &buffer)) {
+ std::string driver_version(buffer);
+ XFree(buffer);
+ return driver_version;
+ }
+ }
+ return std::string();
+}
+
+const uint32 kVendorIDIntel = 0x8086;
+const uint32 kVendorIDNVidia = 0x10de;
+const uint32 kVendorIDAMD = 0x1002;
+
+bool CollectPCIVideoCardInfo(GPUInfo* gpu_info) {
+ DCHECK(gpu_info);
+
+ if (IsPciSupported() == false) {
+ VLOG(1) << "PCI bus scanning is not supported";
+ return false;
+ }
+
+ // TODO(zmo): be more flexible about library name.
+ LibPciLoader libpci_loader;
+ if (!libpci_loader.Load("libpci.so.3") &&
+ !libpci_loader.Load("libpci.so")) {
+ VLOG(1) << "Failed to locate libpci";
+ return false;
+ }
+
+ pci_access* access = (libpci_loader.pci_alloc)();
+ DCHECK(access != NULL);
+ (libpci_loader.pci_init)(access);
+ (libpci_loader.pci_scan_bus)(access);
+ bool primary_gpu_identified = false;
+ for (pci_dev* device = access->devices;
+ device != NULL; device = device->next) {
+ // Fill the IDs and class fields.
+ (libpci_loader.pci_fill_info)(device, 33);
+ // TODO(zmo): there might be other classes that qualify as display devices.
+ if (device->device_class != 0x0300) // Device class is DISPLAY_VGA.
+ continue;
+
+ GPUInfo::GPUDevice gpu;
+ gpu.vendor_id = device->vendor_id;
+ gpu.device_id = device->device_id;
+
+ if (!primary_gpu_identified) {
+ primary_gpu_identified = true;
+ gpu_info->gpu = gpu;
+ } else {
+ // TODO(zmo): if there are multiple GPUs, we assume the non Intel
+ // one is primary. Revisit this logic because we actually don't know
+ // which GPU we are using at this point.
+ if (gpu_info->gpu.vendor_id == kVendorIDIntel &&
+ gpu.vendor_id != kVendorIDIntel) {
+ gpu_info->secondary_gpus.push_back(gpu_info->gpu);
+ gpu_info->gpu = gpu;
+ } else {
+ gpu_info->secondary_gpus.push_back(gpu);
+ }
+ }
+ }
+
+ // Detect Optimus or AMD Switchable GPU.
+ if (gpu_info->secondary_gpus.size() == 1 &&
+ gpu_info->secondary_gpus[0].vendor_id == kVendorIDIntel) {
+ if (gpu_info->gpu.vendor_id == kVendorIDNVidia)
+ gpu_info->optimus = true;
+ if (gpu_info->gpu.vendor_id == kVendorIDAMD)
+ gpu_info->amd_switchable = true;
+ }
+
+ (libpci_loader.pci_cleanup)(access);
+ return (primary_gpu_identified);
+}
+
+} // namespace anonymous
+
+bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
+ DCHECK(gpu_info);
+
+ TRACE_EVENT0("gpu", "gpu_info_collector::CollectGraphicsInfo");
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kGpuNoContextLost)) {
+ gpu_info->can_lose_context = false;
+ } else {
+#if defined(OS_CHROMEOS)
+ gpu_info->can_lose_context = false;
+#else
+ // TODO(zmo): need to consider the case where we are running on top
+ // of desktop GL and GL_ARB_robustness extension is available.
+ gpu_info->can_lose_context =
+ (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2);
+#endif
+ }
+
+ gpu_info->finalized = true;
+ bool rt = CollectGraphicsInfoGL(gpu_info);
+
+ return rt;
+}
+
+GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
+ DCHECK(vendor_id && device_id);
+ *vendor_id = 0;
+ *device_id = 0;
+
+ GPUInfo gpu_info;
+ if (CollectPCIVideoCardInfo(&gpu_info)) {
+ *vendor_id = gpu_info.gpu.vendor_id;
+ *device_id = gpu_info.gpu.device_id;
+ return kGpuIDSuccess;
+ }
+ return kGpuIDFailure;
+}
+
+bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
+ DCHECK(gpu_info);
+
+ bool rt = CollectPCIVideoCardInfo(gpu_info);
+
+ std::string driver_version;
+ switch (gpu_info->gpu.vendor_id) {
+ case kVendorIDAMD:
+ driver_version = CollectDriverVersionATI();
+ if (!driver_version.empty()) {
+ gpu_info->driver_vendor = "ATI / AMD";
+ gpu_info->driver_version = driver_version;
+ }
+ break;
+ case kVendorIDNVidia:
+ driver_version = CollectDriverVersionNVidia();
+ if (!driver_version.empty()) {
+ gpu_info->driver_vendor = "NVIDIA";
+ gpu_info->driver_version = driver_version;
+ }
+ break;
+ case kVendorIDIntel:
+ // In dual-GPU cases, sometimes PCI scan only gives us the
+ // integrated GPU (i.e., the Intel one).
+ driver_version = CollectDriverVersionNVidia();
+ if (!driver_version.empty()) {
+ gpu_info->driver_vendor = "NVIDIA";
+ gpu_info->driver_version = driver_version;
+ // Machines with more than two GPUs are not handled.
+ if (gpu_info->secondary_gpus.size() <= 1)
+ gpu_info->optimus = true;
+ }
+ break;
+ }
+
+ return rt;
+}
+
+bool CollectDriverInfoGL(GPUInfo* gpu_info) {
+ DCHECK(gpu_info);
+
+ std::string gl_version_string = gpu_info->gl_version_string;
+ if (StartsWithASCII(gl_version_string, "OpenGL ES", true))
+ gl_version_string = gl_version_string.substr(10);
+ std::vector<std::string> pieces;
+ base::SplitStringAlongWhitespace(gl_version_string, &pieces);
+ // In linux, the gl version string might be in the format of
+ // GLVersion DriverVendor DriverVersion
+ if (pieces.size() < 3)
+ return false;
+
+ std::string driver_version = pieces[2];
+ size_t pos = driver_version.find_first_not_of("0123456789.");
+ if (pos == 0)
+ return false;
+ if (pos != std::string::npos)
+ driver_version = driver_version.substr(0, pos);
+
+ gpu_info->driver_vendor = pieces[1];
+ gpu_info->driver_version = driver_version;
+ return true;
+}
+
+void MergeGPUInfo(GPUInfo* basic_gpu_info,
+ const GPUInfo& context_gpu_info) {
+ MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
+}
+
+} // namespace gpu
diff --git a/gpu/config/gpu_info_unittest.cc b/gpu/config/gpu_info_unittest.cc
new file mode 100644
index 0000000..f6b6eb6
--- /dev/null
+++ b/gpu/config/gpu_info_unittest.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+// Test that an empty GPUInfo has valid members
+TEST(GPUInfoBasicTest, EmptyGPUInfo) {
+ GPUInfo gpu_info;
+ EXPECT_EQ(gpu_info.finalized, false);
+ EXPECT_EQ(gpu_info.initialization_time.ToInternalValue(), 0);
+ EXPECT_EQ(gpu_info.gpu.vendor_id, 0u);
+ EXPECT_EQ(gpu_info.gpu.device_id, 0u);
+ EXPECT_EQ(gpu_info.secondary_gpus.size(), 0u);
+ EXPECT_EQ(gpu_info.driver_vendor, "");
+ EXPECT_EQ(gpu_info.driver_version, "");
+ EXPECT_EQ(gpu_info.driver_date, "");
+ EXPECT_EQ(gpu_info.pixel_shader_version, "");
+ EXPECT_EQ(gpu_info.vertex_shader_version, "");
+ EXPECT_EQ(gpu_info.gl_version, "");
+ EXPECT_EQ(gpu_info.gl_version_string, "");
+ EXPECT_EQ(gpu_info.gl_vendor, "");
+ EXPECT_EQ(gpu_info.gl_renderer, "");
+ EXPECT_EQ(gpu_info.gl_extensions, "");
+ EXPECT_EQ(gpu_info.can_lose_context, false);
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_performance_stats.h b/gpu/config/gpu_performance_stats.h
new file mode 100644
index 0000000..2ade8bf
--- /dev/null
+++ b/gpu/config/gpu_performance_stats.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_PERFORMANCE_STATS_H_
+#define GPU_CONFIG_GPU_PERFORMANCE_STATS_H_
+
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+
+struct GPU_EXPORT GpuPerformanceStats {
+ GpuPerformanceStats() : graphics(0.f), gaming(0.f), overall(0.f) {}
+
+ float graphics;
+ float gaming;
+ float overall;
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_PERFORMANCE_STATS_H_
+
diff --git a/gpu/config/gpu_switching_list.cc b/gpu/config/gpu_switching_list.cc
new file mode 100644
index 0000000..b87dfb2
--- /dev/null
+++ b/gpu/config/gpu_switching_list.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_switching_list.h"
+
+#include "gpu/config/gpu_switching_option.h"
+
+namespace gpu {
+
+GpuSwitchingList::GpuSwitchingList()
+ : GpuControlList() {
+}
+
+GpuSwitchingList::~GpuSwitchingList() {
+}
+
+// static
+GpuSwitchingList* GpuSwitchingList::Create() {
+ GpuSwitchingList* list = new GpuSwitchingList();
+ list->AddSupportedFeature("force_integrated",
+ GPU_SWITCHING_OPTION_FORCE_INTEGRATED);
+ list->AddSupportedFeature("force_discrete",
+ GPU_SWITCHING_OPTION_FORCE_DISCRETE);
+ return list;
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_switching_list.h b/gpu/config/gpu_switching_list.h
new file mode 100644
index 0000000..095597a
--- /dev/null
+++ b/gpu/config/gpu_switching_list.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_SWITCHING_LIST_H_
+#define GPU_CONFIG_GPU_SWITCHING_LIST_H_
+
+#include <string>
+
+#include "gpu/config/gpu_control_list.h"
+
+namespace gpu {
+
+class GPU_EXPORT GpuSwitchingList : public GpuControlList {
+ public:
+ virtual ~GpuSwitchingList();
+
+ static GpuSwitchingList* Create();
+
+ private:
+ GpuSwitchingList();
+
+ DISALLOW_COPY_AND_ASSIGN(GpuSwitchingList);
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_SWITCHING_LIST_H_
+
diff --git a/gpu/config/gpu_switching_list_json.cc b/gpu/config/gpu_switching_list_json.cc
new file mode 100644
index 0000000..9916b02
--- /dev/null
+++ b/gpu/config/gpu_switching_list_json.cc
@@ -0,0 +1,125 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Determines whether a certain gpu is prefered in a dual-gpu situation.
+// A valid gpu_switching_list.json file are in the format of
+// {
+// "version": "x.y",
+// "entries": [
+// { // entry 1
+// },
+// ...
+// { // entry n
+// }
+// ]
+// }
+//
+// Each entry contains the following fields (fields are optional unless
+// specifically described as mandatory below):
+// 1. "id" is an integer. 0 is reserved. This field is mandatory.
+// 2. "os" contains "type" and an optional "version". "type" could be "macosx",
+// "linux", "win", "chromeos", or "any". "any" is the same as not specifying
+// "os".
+// "version" is a VERSION structure (defined below).
+// 3. "vendor_id" is a string. 0 is reserved.
+// 4. "device_id" is an array of strings. 0 is reserved.
+// 5. "multi_gpu_style" is a string, valid values include "optimus", and
+// "amd_switchable".
+// 6. "multi_gpu_category" is a string, valid values include "any", "primary",
+// and "secondary". If unspecified, the default value is "primary".
+// 7. "driver_vendor" is a STRING structure (defined below).
+// 8. "driver_version" is a VERSION structure (defined below).
+// 9. "driver_date" is a VERSION structure (defined below).
+// The version is interpreted as "year.month.day".
+// 10. "gl_vendor" is a STRING structure (defined below).
+// 11. "gl_renderer" is a STRING structure (defined below).
+// 12. "gl_extensions" is a STRING structure (defined below).
+// 13. "perf_graphics" is a FLOAT structure (defined below).
+// 14. "perf_gaming" is a FLOAT structure (defined below).
+// 15. "perf_overall" is a FLOAT structure (defined below).
+// 16. "machine_model" contais "name" and an optional "version". "name" is a
+// STRING structure and "version" is a VERSION structure (defined below).
+// 17. "gpu_count" is a INT structure (defined below).
+// 18 "cpu_info" is a STRING structure (defined below).
+// 19. "exceptions" is a list of entries.
+// 20. "features" is a list of gpu switching options, including
+// "force_discrete" and "force_integrated".
+// This field is mandatory.
+// 21. "description" has the description of the entry.
+// 22. "webkit_bugs" is an array of associated webkit bug numbers.
+// 23. "cr_bugs" is an array of associated webkit bug numbers.
+// 24. "browser_version" is a VERSION structure (defined below). If this
+// condition is not satisfied, the entry will be ignored. If it is not
+// present, then the entry applies to all versions of the browser.
+// 25. "disabled" is a boolean. If it is present, the entry will be skipped.
+// This can not be used in exceptions.
+//
+// VERSION includes "op", "style", "number", and "number2". "op" can be any of
+// the following values: "=", "<", "<=", ">", ">=", "any", "between". "style"
+// is optional and can be "lexical" or "numerical"; if it's not specified, it
+// defaults to "numerical". "number2" is only used if "op" is "between".
+// "between" is "number <= * <= number2".
+// "number" is used for all "op" values except "any". "number" and "number2"
+// are in the format of x, x.x, x.x.x, etc.
+// Only "driver_version" supports lexical style if the format is major.minor;
+// in that case, major is still numerical, but minor is lexical.
+//
+// STRING includes "op" and "value". "op" can be any of the following values:
+// "contains", "beginwith", "endwith", "=". "value" is a string.
+//
+// FLOAT includes "op" "value", and "value2". "op" can be any of the
+// following values: "=", "<", "<=", ">", ">=", "any", "between". "value2" is
+// only used if "op" is "between". "value" is used for all "op" values except
+// "any". "value" and "value2" are valid float numbers.
+// INT is very much like FLOAT, except that the values need to be integers.
+
+#include "gpu/config/gpu_control_list_jsons.h"
+
+#define LONG_STRING_CONST(...) #__VA_ARGS__
+
+namespace gpu {
+
+const char kGpuSwitchingListJson[] = LONG_STRING_CONST(
+
+{
+ "name": "gpu switching list",
+ // Please update the version number whenever you change this file.
+ "version": "2.0",
+ "entries": [
+ {
+ "id": 1,
+ "description": "Force to use discrete GPU on older MacBookPro models.",
+ "cr_bugs": [113703],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": ">=",
+ "number": "10.7"
+ }
+ },
+ "machine_model": {
+ "name": {
+ "op": "=",
+ "value": "MacBookPro"
+ },
+ "version": {
+ "op": "<",
+ "number": "8"
+ }
+ },
+ "gpu_count": {
+ "op": "=",
+ "value": "2"
+ },
+ "features": [
+ "force_discrete"
+ ]
+ }
+ ]
+}
+
+); // LONG_STRING_CONST macro
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_switching_list_unittest.cc b/gpu/config/gpu_switching_list_unittest.cc
new file mode 100644
index 0000000..78dc74d
--- /dev/null
+++ b/gpu/config/gpu_switching_list_unittest.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "gpu/config/gpu_control_list_jsons.h"
+#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_switching_list.h"
+#include "gpu/config/gpu_switching_option.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#define LONG_STRING_CONST(...) #__VA_ARGS__
+
+const char kOsVersion[] = "10.6.4";
+
+namespace gpu {
+
+class GpuSwitchingListTest : public testing::Test {
+ public:
+ GpuSwitchingListTest() { }
+
+ virtual ~GpuSwitchingListTest() { }
+
+ const GPUInfo& gpu_info() const {
+ return gpu_info_;
+ }
+
+ protected:
+ virtual void SetUp() {
+ gpu_info_.gpu.vendor_id = 0x10de;
+ gpu_info_.gpu.device_id = 0x0640;
+ gpu_info_.driver_vendor = "NVIDIA";
+ gpu_info_.driver_version = "1.6.18";
+ gpu_info_.driver_date = "7-14-2009";
+ gpu_info_.machine_model = "MacBookPro 7.1";
+ gpu_info_.gl_vendor = "NVIDIA Corporation";
+ gpu_info_.gl_renderer = "NVIDIA GeForce GT 120 OpenGL Engine";
+ gpu_info_.performance_stats.graphics = 5.0;
+ gpu_info_.performance_stats.gaming = 5.0;
+ gpu_info_.performance_stats.overall = 5.0;
+ }
+
+ virtual void TearDown() {
+ }
+
+ private:
+ GPUInfo gpu_info_;
+};
+
+TEST_F(GpuSwitchingListTest, CurrentSwitchingListValidation) {
+ scoped_ptr<GpuSwitchingList> switching_list(GpuSwitchingList::Create());
+ EXPECT_TRUE(switching_list->LoadList(
+ kGpuSwitchingListJson, GpuControlList::kAllOs));
+ EXPECT_FALSE(switching_list->contains_unknown_fields());
+}
+
+TEST_F(GpuSwitchingListTest, GpuSwitching) {
+ const std::string json = LONG_STRING_CONST(
+ {
+ "name": "gpu switching list",
+ "version": "0.1",
+ "entries": [
+ {
+ "id": 1,
+ "os": {
+ "type": "macosx"
+ },
+ "features": [
+ "force_discrete"
+ ]
+ },
+ {
+ "id": 2,
+ "os": {
+ "type": "win"
+ },
+ "features": [
+ "force_integrated"
+ ]
+ }
+ ]
+ }
+ );
+ scoped_ptr<GpuSwitchingList> switching_list(GpuSwitchingList::Create());
+ EXPECT_TRUE(switching_list->LoadList(json, GpuControlList::kAllOs));
+ std::set<int> switching = switching_list->MakeDecision(
+ GpuControlList::kOsMacosx, kOsVersion, gpu_info());
+ EXPECT_EQ(1u, switching.size());
+ EXPECT_EQ(1u, switching.count(GPU_SWITCHING_OPTION_FORCE_DISCRETE));
+ std::vector<uint32> entries;
+ switching_list->GetDecisionEntries(&entries, false);
+ ASSERT_EQ(1u, entries.size());
+ EXPECT_EQ(1u, entries[0]);
+
+ switching_list.reset(GpuSwitchingList::Create());
+ EXPECT_TRUE(switching_list->LoadList(json, GpuControlList::kAllOs));
+ switching = switching_list->MakeDecision(
+ GpuControlList::kOsWin, kOsVersion, gpu_info());
+ EXPECT_EQ(1u, switching.size());
+ EXPECT_EQ(1u, switching.count(GPU_SWITCHING_OPTION_FORCE_INTEGRATED));
+ switching_list->GetDecisionEntries(&entries, false);
+ ASSERT_EQ(1u, entries.size());
+ EXPECT_EQ(2u, entries[0]);
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_switching_option.h b/gpu/config/gpu_switching_option.h
new file mode 100644
index 0000000..036c15f
--- /dev/null
+++ b/gpu/config/gpu_switching_option.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_SWITCHING_OPTION_H_
+#define GPU_CONFIG_GPU_SWITCHING_OPTION_H_
+
+//#include "build/build_config.h"
+
+namespace gpu {
+
+enum GpuSwitchingOption {
+ GPU_SWITCHING_OPTION_AUTOMATIC,
+ GPU_SWITCHING_OPTION_FORCE_INTEGRATED,
+ GPU_SWITCHING_OPTION_FORCE_DISCRETE,
+ GPU_SWITCHING_OPTION_UNKNOWN
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_SWITCHING_OPTION_H_
+
diff --git a/gpu/config/gpu_test_config.cc b/gpu/config/gpu_test_config.cc
new file mode 100644
index 0000000..ffb6e5f
--- /dev/null
+++ b/gpu/config/gpu_test_config.cc
@@ -0,0 +1,272 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_test_config.h"
+
+#include "base/logging.h"
+#include "base/sys_info.h"
+#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_info_collector.h"
+#include "gpu/config/gpu_test_expectations_parser.h"
+
+namespace gpu {
+
+namespace {
+
+GPUTestConfig::OS GetCurrentOS() {
+#if defined(OS_CHROMEOS)
+ return GPUTestConfig::kOsChromeOS;
+#elif defined(OS_LINUX) || defined(OS_OPENBSD)
+ return GPUTestConfig::kOsLinux;
+#elif defined(OS_WIN)
+ int32 major_version = 0;
+ int32 minor_version = 0;
+ int32 bugfix_version = 0;
+ base::SysInfo::OperatingSystemVersionNumbers(
+ &major_version, &minor_version, &bugfix_version);
+ if (major_version == 5)
+ return GPUTestConfig::kOsWinXP;
+ if (major_version == 6 && minor_version == 0)
+ return GPUTestConfig::kOsWinVista;
+ if (major_version == 6 && minor_version == 1)
+ return GPUTestConfig::kOsWin7;
+ if (major_version == 6 && minor_version == 2)
+ return GPUTestConfig::kOsWin8;
+#elif defined(OS_MACOSX)
+ int32 major_version = 0;
+ int32 minor_version = 0;
+ int32 bugfix_version = 0;
+ base::SysInfo::OperatingSystemVersionNumbers(
+ &major_version, &minor_version, &bugfix_version);
+ if (major_version == 10) {
+ switch (minor_version) {
+ case 5:
+ return GPUTestConfig::kOsMacLeopard;
+ case 6:
+ return GPUTestConfig::kOsMacSnowLeopard;
+ case 7:
+ return GPUTestConfig::kOsMacLion;
+ case 8:
+ return GPUTestConfig::kOsMacMountainLion;
+ }
+ }
+#elif defined(OS_ANDROID)
+ return GPUTestConfig::kOsAndroid;
+#endif
+ return GPUTestConfig::kOsUnknown;
+}
+
+} // namespace anonymous
+
+GPUTestConfig::GPUTestConfig()
+ : validate_gpu_info_(true),
+ os_(kOsUnknown),
+ gpu_device_id_(0),
+ build_type_(kBuildTypeUnknown) {
+}
+
+GPUTestConfig::~GPUTestConfig() {
+}
+
+void GPUTestConfig::set_os(int32 os) {
+ DCHECK_EQ(0, os & ~(kOsAndroid | kOsWin | kOsMac | kOsLinux | kOsChromeOS));
+ os_ = os;
+}
+
+void GPUTestConfig::AddGPUVendor(uint32 gpu_vendor) {
+ DCHECK_NE(0u, gpu_vendor);
+ for (size_t i = 0; i < gpu_vendor_.size(); ++i)
+ DCHECK_NE(gpu_vendor_[i], gpu_vendor);
+ gpu_vendor_.push_back(gpu_vendor);
+}
+
+void GPUTestConfig::set_gpu_device_id(uint32 id) {
+ gpu_device_id_ = id;
+}
+
+void GPUTestConfig::set_build_type(int32 build_type) {
+ DCHECK_EQ(0, build_type & ~(kBuildTypeRelease | kBuildTypeDebug));
+ build_type_ = build_type;
+}
+
+bool GPUTestConfig::IsValid() const {
+ if (!validate_gpu_info_)
+ return true;
+ if (gpu_device_id_ != 0 && (gpu_vendor_.size() != 1 || gpu_vendor_[0] == 0))
+ return false;
+ return true;
+}
+
+bool GPUTestConfig::OverlapsWith(const GPUTestConfig& config) const {
+ DCHECK(IsValid());
+ DCHECK(config.IsValid());
+ if (config.os_ != kOsUnknown && os_ != kOsUnknown &&
+ (os_ & config.os_) == 0)
+ return false;
+ if (config.gpu_vendor_.size() > 0 && gpu_vendor_.size() > 0) {
+ bool shared = false;
+ for (size_t i = 0; i < config.gpu_vendor_.size() && !shared; ++i) {
+ for (size_t j = 0; j < gpu_vendor_.size(); ++j) {
+ if (config.gpu_vendor_[i] == gpu_vendor_[j]) {
+ shared = true;
+ break;
+ }
+ }
+ }
+ if (!shared)
+ return false;
+ }
+ if (config.gpu_device_id_ != 0 && gpu_device_id_ != 0 &&
+ gpu_device_id_ != config.gpu_device_id_)
+ return false;
+ if (config.build_type_ != kBuildTypeUnknown &&
+ build_type_ != kBuildTypeUnknown &&
+ (build_type_ & config.build_type_) == 0)
+ return false;
+ return true;
+}
+
+void GPUTestConfig::DisableGPUInfoValidation() {
+ validate_gpu_info_ = false;
+}
+
+void GPUTestConfig::ClearGPUVendor() {
+ gpu_vendor_.clear();
+}
+
+GPUTestBotConfig::~GPUTestBotConfig() {
+}
+
+void GPUTestBotConfig::AddGPUVendor(uint32 gpu_vendor) {
+ DCHECK_EQ(0u, GPUTestConfig::gpu_vendor().size());
+ GPUTestConfig::AddGPUVendor(gpu_vendor);
+}
+
+bool GPUTestBotConfig::SetGPUInfo(const GPUInfo& gpu_info) {
+ DCHECK(validate_gpu_info_);
+ if (gpu_info.gpu.device_id == 0 || gpu_info.gpu.vendor_id == 0)
+ return false;
+ ClearGPUVendor();
+ AddGPUVendor(gpu_info.gpu.vendor_id);
+ set_gpu_device_id(gpu_info.gpu.device_id);
+ return true;
+}
+
+bool GPUTestBotConfig::IsValid() const {
+ switch (os()) {
+ case kOsWinXP:
+ case kOsWinVista:
+ case kOsWin7:
+ case kOsWin8:
+ case kOsMacLeopard:
+ case kOsMacSnowLeopard:
+ case kOsMacLion:
+ case kOsMacMountainLion:
+ case kOsLinux:
+ case kOsChromeOS:
+ case kOsAndroid:
+ break;
+ default:
+ return false;
+ }
+ if (validate_gpu_info_) {
+ if (gpu_vendor().size() != 1 || gpu_vendor()[0] == 0)
+ return false;
+ if (gpu_device_id() == 0)
+ return false;
+ }
+ switch (build_type()) {
+ case kBuildTypeRelease:
+ case kBuildTypeDebug:
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool GPUTestBotConfig::Matches(const GPUTestConfig& config) const {
+ DCHECK(IsValid());
+ DCHECK(config.IsValid());
+ if (config.os() != kOsUnknown && (os() & config.os()) == 0)
+ return false;
+ if (config.gpu_vendor().size() > 0) {
+ bool contained = false;
+ for (size_t i = 0; i < config.gpu_vendor().size(); ++i) {
+ if (config.gpu_vendor()[i] == gpu_vendor()[0]) {
+ contained = true;
+ break;
+ }
+ }
+ if (!contained)
+ return false;
+ }
+ if (config.gpu_device_id() != 0 &&
+ gpu_device_id() != config.gpu_device_id())
+ return false;
+ if (config.build_type() != kBuildTypeUnknown &&
+ (build_type() & config.build_type()) == 0)
+ return false;
+ return true;
+}
+
+bool GPUTestBotConfig::Matches(const std::string& config_data) const {
+ GPUTestExpectationsParser parser;
+ GPUTestConfig config;
+
+ if (!parser.ParseConfig(config_data, &config))
+ return false;
+ return Matches(config);
+}
+
+bool GPUTestBotConfig::LoadCurrentConfig(const GPUInfo* gpu_info) {
+ bool rt;
+ if (gpu_info == NULL) {
+ GPUInfo my_gpu_info;
+ GpuIDResult result;
+ result = CollectGpuID(&my_gpu_info.gpu.vendor_id,
+ &my_gpu_info.gpu.device_id);
+ if (result == kGpuIDNotSupported) {
+ DisableGPUInfoValidation();
+ rt = true;
+ } else {
+ rt = SetGPUInfo(my_gpu_info);
+ }
+ } else {
+ rt = SetGPUInfo(*gpu_info);
+ }
+ set_os(GetCurrentOS());
+ if (os() == kOsUnknown)
+ rt = false;
+#if defined(NDEBUG)
+ set_build_type(kBuildTypeRelease);
+#else
+ set_build_type(kBuildTypeDebug);
+#endif
+ return rt;
+}
+
+// static
+bool GPUTestBotConfig::CurrentConfigMatches(const std::string& config_data) {
+ GPUTestBotConfig my_config;
+ if (!my_config.LoadCurrentConfig(NULL))
+ return false;
+ return my_config.Matches(config_data);
+}
+
+// static
+bool GPUTestBotConfig::CurrentConfigMatches(
+ const std::vector<std::string>& configs) {
+ GPUTestBotConfig my_config;
+ if (!my_config.LoadCurrentConfig(NULL))
+ return false;
+ for (size_t i = 0 ; i < configs.size(); ++i) {
+ if (my_config.Matches(configs[i]))
+ return true;
+ }
+ return false;
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_test_config.h b/gpu/config/gpu_test_config.h
new file mode 100644
index 0000000..3c7b038
--- /dev/null
+++ b/gpu/config/gpu_test_config.h
@@ -0,0 +1,124 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_TEST_CONFIG_H_
+#define GPU_CONFIG_GPU_TEST_CONFIG_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+
+struct GPUInfo;
+
+class GPU_EXPORT GPUTestConfig {
+ public:
+ enum OS {
+ kOsUnknown = 0,
+ kOsWinXP = 1 << 0,
+ kOsWinVista = 1 << 1,
+ kOsWin7 = 1 << 2,
+ kOsWin8 = 1 << 3,
+ kOsWin = kOsWinXP | kOsWinVista | kOsWin7 | kOsWin8,
+ kOsMacLeopard = 1 << 4,
+ kOsMacSnowLeopard = 1 << 5,
+ kOsMacLion = 1 << 6,
+ kOsMacMountainLion = 1 << 7,
+ kOsMac = kOsMacLeopard | kOsMacSnowLeopard | kOsMacLion |
+ kOsMacMountainLion,
+ kOsLinux = 1 << 8,
+ kOsChromeOS = 1 << 9,
+ kOsAndroid = 1 << 10,
+ };
+
+ enum BuildType {
+ kBuildTypeUnknown = 0,
+ kBuildTypeRelease = 1 << 0,
+ kBuildTypeDebug = 1 << 1,
+ };
+
+ GPUTestConfig();
+ virtual ~GPUTestConfig();
+
+ void set_os(int32 os);
+ void set_gpu_device_id(uint32 id);
+ void set_build_type(int32 build_type);
+
+ virtual void AddGPUVendor(uint32 gpu_vendor);
+
+ int32 os() const { return os_; }
+ const std::vector<uint32>& gpu_vendor() const { return gpu_vendor_; }
+ uint32 gpu_device_id() const { return gpu_device_id_; }
+ int32 build_type() const { return build_type_; }
+
+ // Check if the config is valid. For example, if gpu_device_id_ is set, but
+ // gpu_vendor_ is unknown, then it's invalid.
+ virtual bool IsValid() const;
+
+ // Check if two configs overlap, i.e., if there exists a config that matches
+ // both configs.
+ bool OverlapsWith(const GPUTestConfig& config) const;
+
+ // Disable validation of GPU vendor and device ids.
+ void DisableGPUInfoValidation();
+
+ protected:
+ void ClearGPUVendor();
+
+ // Indicates that the OS has the notion of a numeric GPU vendor and device id
+ // and this data should be validated.
+ bool validate_gpu_info_;
+
+ private:
+ // operating system.
+ int32 os_;
+
+ // GPU vendor.
+ std::vector<uint32> gpu_vendor_;
+
+ // GPU device id (unique to each vendor).
+ uint32 gpu_device_id_;
+
+ // Release or Debug.
+ int32 build_type_;
+};
+
+class GPU_EXPORT GPUTestBotConfig : public GPUTestConfig {
+ public:
+ GPUTestBotConfig() { }
+ virtual ~GPUTestBotConfig();
+
+ // This should only be called when no gpu_vendor is added.
+ virtual void AddGPUVendor(uint32 gpu_vendor) OVERRIDE;
+
+ // Return false if gpu_info does not have valid vendor_id and device_id.
+ bool SetGPUInfo(const GPUInfo& gpu_info);
+
+ // Check if the bot config is valid, i.e., if it is one valid test-bot
+ // environment. For example, if a field is unknown, or if OS is not one
+ // fully defined OS, then it's valid.
+ virtual bool IsValid() const OVERRIDE;
+
+ // Check if a bot config matches a test config, i.e., the test config is a
+ // superset of the bot config.
+ bool Matches(const GPUTestConfig& config) const;
+ bool Matches(const std::string& config_data) const;
+
+ // Setup the config with the current gpu testing environment.
+ // If gpu_info is NULL, collect GPUInfo first.
+ bool LoadCurrentConfig(const GPUInfo* gpu_info);
+
+ // Check if this bot's config matches |config_data| or any of the |configs|.
+ static bool CurrentConfigMatches(const std::string& config_data);
+ static bool CurrentConfigMatches(const std::vector<std::string>& configs);
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_TEST_CONFIG_H_
+
diff --git a/gpu/config/gpu_test_config_unittest.cc b/gpu/config/gpu_test_config_unittest.cc
new file mode 100644
index 0000000..b9411dc
--- /dev/null
+++ b/gpu/config/gpu_test_config_unittest.cc
@@ -0,0 +1,255 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_test_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+class GPUTestConfigTest : public testing::Test {
+ public:
+ GPUTestConfigTest() { }
+
+ virtual ~GPUTestConfigTest() { }
+
+ protected:
+ virtual void SetUp() { }
+
+ virtual void TearDown() { }
+};
+
+TEST_F(GPUTestConfigTest, EmptyValues) {
+ GPUTestConfig config;
+ EXPECT_EQ(GPUTestConfig::kOsUnknown, config.os());
+ EXPECT_EQ(0u, config.gpu_vendor().size());
+ EXPECT_EQ(0u, config.gpu_device_id());
+ EXPECT_EQ(GPUTestConfig::kBuildTypeUnknown, config.build_type());
+}
+
+TEST_F(GPUTestConfigTest, SetGPUInfo) {
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x10de;
+ gpu_info.gpu.device_id = 0x0640;
+ GPUTestBotConfig config;
+ EXPECT_TRUE(config.SetGPUInfo(gpu_info));
+ EXPECT_EQ(1u, config.gpu_vendor().size());
+ EXPECT_EQ(gpu_info.gpu.vendor_id, config.gpu_vendor()[0]);
+ EXPECT_EQ(gpu_info.gpu.device_id, config.gpu_device_id());
+
+ gpu_info.gpu.vendor_id = 0x8086;
+ gpu_info.gpu.device_id = 0x0046;
+ EXPECT_TRUE(config.SetGPUInfo(gpu_info));
+ EXPECT_EQ(1u, config.gpu_vendor().size());
+ EXPECT_EQ(gpu_info.gpu.vendor_id, config.gpu_vendor()[0]);
+ EXPECT_EQ(gpu_info.gpu.device_id, config.gpu_device_id());
+}
+
+TEST_F(GPUTestConfigTest, IsValid) {
+ {
+ GPUTestConfig config;
+ config.set_gpu_device_id(0x0640);
+ EXPECT_FALSE(config.IsValid());
+ config.AddGPUVendor(0x10de);
+ EXPECT_TRUE(config.IsValid());
+ }
+
+ {
+ GPUTestBotConfig config;
+ config.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ config.set_os(GPUTestConfig::kOsWin7);
+ config.set_gpu_device_id(0x0640);
+ EXPECT_FALSE(config.IsValid());
+ config.AddGPUVendor(0x10de);
+ EXPECT_TRUE(config.IsValid());
+
+ config.set_gpu_device_id(0);
+ EXPECT_FALSE(config.IsValid());
+ config.set_gpu_device_id(0x0640);
+ EXPECT_TRUE(config.IsValid());
+
+ config.set_os(GPUTestConfig::kOsWin);
+ EXPECT_FALSE(config.IsValid());
+ config.set_os(GPUTestConfig::kOsWin7 | GPUTestConfig::kOsWinXP);
+ EXPECT_FALSE(config.IsValid());
+ config.set_os(GPUTestConfig::kOsWin7);
+ EXPECT_TRUE(config.IsValid());
+
+ config.set_build_type(GPUTestConfig::kBuildTypeUnknown);
+ EXPECT_FALSE(config.IsValid());
+ config.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ EXPECT_TRUE(config.IsValid());
+ }
+}
+
+TEST_F(GPUTestConfigTest, Matches) {
+ GPUTestBotConfig config;
+ config.set_os(GPUTestConfig::kOsWin7);
+ config.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ config.AddGPUVendor(0x10de);
+ config.set_gpu_device_id(0x0640);
+ EXPECT_TRUE(config.IsValid());
+
+ { // os matching
+ GPUTestConfig config2;
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_os(GPUTestConfig::kOsWin);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_os(GPUTestConfig::kOsWin7);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_os(GPUTestConfig::kOsMac);
+ EXPECT_FALSE(config.Matches(config2));
+ config2.set_os(GPUTestConfig::kOsWin7 | GPUTestConfig::kOsLinux);
+ EXPECT_TRUE(config.Matches(config2));
+ }
+
+ { // gpu vendor matching
+ {
+ GPUTestConfig config2;
+ config2.AddGPUVendor(0x10de);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.AddGPUVendor(0x1004);
+ EXPECT_TRUE(config.Matches(config2));
+ }
+ {
+ GPUTestConfig config2;
+ config2.AddGPUVendor(0x8086);
+ EXPECT_FALSE(config.Matches(config2));
+ }
+ }
+
+ { // build type matching
+ GPUTestConfig config2;
+ config2.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_build_type(GPUTestConfig::kBuildTypeRelease |
+ GPUTestConfig::kBuildTypeDebug);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_build_type(GPUTestConfig::kBuildTypeDebug);
+ EXPECT_FALSE(config.Matches(config2));
+ }
+
+ { // exact matching
+ GPUTestConfig config2;
+ config2.set_os(GPUTestConfig::kOsWin7);
+ config2.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ config2.AddGPUVendor(0x10de);
+ config2.set_gpu_device_id(0x0640);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_gpu_device_id(0x0641);
+ EXPECT_FALSE(config.Matches(config2));
+ }
+}
+
+TEST_F(GPUTestConfigTest, StringMatches) {
+ GPUTestBotConfig config;
+ config.set_os(GPUTestConfig::kOsWin7);
+ config.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ config.AddGPUVendor(0x10de);
+ config.set_gpu_device_id(0x0640);
+ EXPECT_TRUE(config.IsValid());
+
+ EXPECT_TRUE(config.Matches(std::string()));
+
+ // os matching
+ EXPECT_TRUE(config.Matches("WIN"));
+ EXPECT_TRUE(config.Matches("WIN7"));
+ EXPECT_FALSE(config.Matches("MAC"));
+ EXPECT_TRUE(config.Matches("WIN7 LINUX"));
+
+ // gpu vendor matching
+ EXPECT_TRUE(config.Matches("NVIDIA"));
+ EXPECT_TRUE(config.Matches("NVIDIA AMD"));
+ EXPECT_FALSE(config.Matches("INTEL"));
+
+ // build type matching
+ EXPECT_TRUE(config.Matches("RELEASE"));
+ EXPECT_TRUE(config.Matches("RELEASE DEBUG"));
+ EXPECT_FALSE(config.Matches("DEBUG"));
+
+ // exact matching
+ EXPECT_TRUE(config.Matches("WIN7 RELEASE NVIDIA 0X0640"));
+ EXPECT_FALSE(config.Matches("WIN7 RELEASE NVIDIA 0X0641"));
+}
+
+TEST_F(GPUTestConfigTest, OverlapsWith) {
+ { // os
+ // win vs win7
+ GPUTestConfig config;
+ config.set_os(GPUTestConfig::kOsWin);
+ GPUTestConfig config2;
+ config2.set_os(GPUTestConfig::kOsWin7);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ // win vs win7+linux
+ config2.set_os(GPUTestConfig::kOsWin7 | GPUTestConfig::kOsLinux);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ // win vs mac
+ config2.set_os(GPUTestConfig::kOsMac);
+ EXPECT_FALSE(config.OverlapsWith(config2));
+ EXPECT_FALSE(config2.OverlapsWith(config));
+ // win vs unknown
+ config2.set_os(GPUTestConfig::kOsUnknown);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ }
+
+ { // gpu vendor
+ GPUTestConfig config;
+ config.AddGPUVendor(0x10de);
+ // nvidia vs unknown
+ GPUTestConfig config2;
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ // nvidia vs intel
+ config2.AddGPUVendor(0x1086);
+ EXPECT_FALSE(config.OverlapsWith(config2));
+ EXPECT_FALSE(config2.OverlapsWith(config));
+ // nvidia vs nvidia+intel
+ config2.AddGPUVendor(0x10de);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ }
+
+ { // build type
+ // release vs debug
+ GPUTestConfig config;
+ config.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ GPUTestConfig config2;
+ config2.set_build_type(GPUTestConfig::kBuildTypeDebug);
+ EXPECT_FALSE(config.OverlapsWith(config2));
+ EXPECT_FALSE(config2.OverlapsWith(config));
+ // release vs release+debug
+ config2.set_build_type(GPUTestConfig::kBuildTypeRelease |
+ GPUTestConfig::kBuildTypeDebug);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ // release vs unknown
+ config2.set_build_type(GPUTestConfig::kBuildTypeUnknown);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ }
+
+ { // win7 vs nvidia
+ GPUTestConfig config;
+ config.set_os(GPUTestConfig::kOsWin7);
+ GPUTestConfig config2;
+ config2.AddGPUVendor(0x10de);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ }
+}
+
+TEST_F(GPUTestConfigTest, LoadCurrentConfig) {
+ GPUTestBotConfig config;
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x10de;
+ gpu_info.gpu.device_id = 0x0640;
+ EXPECT_TRUE(config.LoadCurrentConfig(&gpu_info));
+ EXPECT_TRUE(config.IsValid());
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_test_expectations_parser.cc b/gpu/config/gpu_test_expectations_parser.cc
new file mode 100644
index 0000000..8cc2b3c
--- /dev/null
+++ b/gpu/config/gpu_test_expectations_parser.cc
@@ -0,0 +1,503 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_test_expectations_parser.h"
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/strings/string_split.h"
+
+namespace gpu {
+
+namespace {
+
+enum LineParserStage {
+ kLineParserBegin = 0,
+ kLineParserBugID,
+ kLineParserConfigs,
+ kLineParserColon,
+ kLineParserTestName,
+ kLineParserEqual,
+ kLineParserExpectations,
+};
+
+enum Token {
+ // os
+ kConfigWinXP = 0,
+ kConfigWinVista,
+ kConfigWin7,
+ kConfigWin8,
+ kConfigWin,
+ kConfigMacLeopard,
+ kConfigMacSnowLeopard,
+ kConfigMacLion,
+ kConfigMacMountainLion,
+ kConfigMac,
+ kConfigLinux,
+ kConfigChromeOS,
+ kConfigAndroid,
+ // gpu vendor
+ kConfigNVidia,
+ kConfigAMD,
+ kConfigIntel,
+ kConfigVMWare,
+ // build type
+ kConfigRelease,
+ kConfigDebug,
+ // expectation
+ kExpectationPass,
+ kExpectationFail,
+ kExpectationFlaky,
+ kExpectationTimeout,
+ kExpectationSkip,
+ // separator
+ kSeparatorColon,
+ kSeparatorEqual,
+
+ kNumberOfExactMatchTokens,
+
+ // others
+ kConfigGPUDeviceID,
+ kTokenComment,
+ kTokenWord,
+};
+
+struct TokenInfo {
+ const char* name;
+ int32 flag;
+};
+
+const TokenInfo kTokenData[] = {
+ { "xp", GPUTestConfig::kOsWinXP },
+ { "vista", GPUTestConfig::kOsWinVista },
+ { "win7", GPUTestConfig::kOsWin7 },
+ { "win8", GPUTestConfig::kOsWin8 },
+ { "win", GPUTestConfig::kOsWin },
+ { "leopard", GPUTestConfig::kOsMacLeopard },
+ { "snowleopard", GPUTestConfig::kOsMacSnowLeopard },
+ { "lion", GPUTestConfig::kOsMacLion },
+ { "mountainlion", GPUTestConfig::kOsMacMountainLion },
+ { "mac", GPUTestConfig::kOsMac },
+ { "linux", GPUTestConfig::kOsLinux },
+ { "chromeos", GPUTestConfig::kOsChromeOS },
+ { "android", GPUTestConfig::kOsAndroid },
+ { "nvidia", 0x10DE },
+ { "amd", 0x1002 },
+ { "intel", 0x8086 },
+ { "vmware", 0x15ad },
+ { "release", GPUTestConfig::kBuildTypeRelease },
+ { "debug", GPUTestConfig::kBuildTypeDebug },
+ { "pass", GPUTestExpectationsParser::kGpuTestPass },
+ { "fail", GPUTestExpectationsParser::kGpuTestFail },
+ { "flaky", GPUTestExpectationsParser::kGpuTestFlaky },
+ { "timeout", GPUTestExpectationsParser::kGpuTestTimeout },
+ { "skip", GPUTestExpectationsParser::kGpuTestSkip },
+ { ":", 0 },
+ { "=", 0 },
+};
+
+enum ErrorType {
+ kErrorFileIO = 0,
+ kErrorIllegalEntry,
+ kErrorInvalidEntry,
+ kErrorEntryWithOsConflicts,
+ kErrorEntryWithGpuVendorConflicts,
+ kErrorEntryWithBuildTypeConflicts,
+ kErrorEntryWithGpuDeviceIdConflicts,
+ kErrorEntryWithExpectationConflicts,
+ kErrorEntriesOverlap,
+
+ kNumberOfErrors,
+};
+
+const char* kErrorMessage[] = {
+ "file IO failed",
+ "entry with wrong format",
+ "entry invalid, likely wrong modifiers combination",
+ "entry with OS modifier conflicts",
+ "entry with GPU vendor modifier conflicts",
+ "entry with GPU build type conflicts",
+ "entry with GPU device id conflicts or malformat",
+ "entry with expectation modifier conflicts",
+ "two entries's configs overlap",
+};
+
+Token ParseToken(const std::string& word) {
+ if (StartsWithASCII(word, "//", false))
+ return kTokenComment;
+ if (StartsWithASCII(word, "0x", false))
+ return kConfigGPUDeviceID;
+
+ for (int32 i = 0; i < kNumberOfExactMatchTokens; ++i) {
+ if (LowerCaseEqualsASCII(word, kTokenData[i].name))
+ return static_cast<Token>(i);
+ }
+ return kTokenWord;
+}
+
+// reference name can have the last character as *.
+bool NamesMatching(const std::string& ref, const std::string& test_name) {
+ size_t len = ref.length();
+ if (len == 0)
+ return false;
+ if (ref[len - 1] == '*') {
+ if (test_name.length() > len -1 &&
+ ref.compare(0, len - 1, test_name, 0, len - 1) == 0)
+ return true;
+ return false;
+ }
+ return (ref == test_name);
+}
+
+} // namespace anonymous
+
+GPUTestExpectationsParser::GPUTestExpectationsParser() {
+ // Some sanity check.
+ DCHECK_EQ(static_cast<unsigned int>(kNumberOfExactMatchTokens),
+ sizeof(kTokenData) / sizeof(kTokenData[0]));
+ DCHECK_EQ(static_cast<unsigned int>(kNumberOfErrors),
+ sizeof(kErrorMessage) / sizeof(kErrorMessage[0]));
+}
+
+GPUTestExpectationsParser::~GPUTestExpectationsParser() {
+}
+
+bool GPUTestExpectationsParser::LoadTestExpectations(const std::string& data) {
+ entries_.clear();
+ error_messages_.clear();
+
+ std::vector<std::string> lines;
+ base::SplitString(data, '\n', &lines);
+ bool rt = true;
+ for (size_t i = 0; i < lines.size(); ++i) {
+ if (!ParseLine(lines[i], i + 1))
+ rt = false;
+ }
+ if (DetectConflictsBetweenEntries()) {
+ entries_.clear();
+ rt = false;
+ }
+
+ return rt;
+}
+
+bool GPUTestExpectationsParser::LoadTestExpectations(
+ const base::FilePath& path) {
+ entries_.clear();
+ error_messages_.clear();
+
+ std::string data;
+ if (!file_util::ReadFileToString(path, &data)) {
+ error_messages_.push_back(kErrorMessage[kErrorFileIO]);
+ return false;
+ }
+ return LoadTestExpectations(data);
+}
+
+int32 GPUTestExpectationsParser::GetTestExpectation(
+ const std::string& test_name,
+ const GPUTestBotConfig& bot_config) const {
+ for (size_t i = 0; i < entries_.size(); ++i) {
+ if (NamesMatching(entries_[i].test_name, test_name) &&
+ bot_config.Matches(entries_[i].test_config))
+ return entries_[i].test_expectation;
+ }
+ return kGpuTestPass;
+}
+
+const std::vector<std::string>&
+GPUTestExpectationsParser::GetErrorMessages() const {
+ return error_messages_;
+}
+
+bool GPUTestExpectationsParser::ParseConfig(
+ const std::string& config_data, GPUTestConfig* config) {
+ DCHECK(config);
+ std::vector<std::string> tokens;
+ base::SplitStringAlongWhitespace(config_data, &tokens);
+
+ for (size_t i = 0; i < tokens.size(); ++i) {
+ Token token = ParseToken(tokens[i]);
+ switch (token) {
+ case kConfigWinXP:
+ case kConfigWinVista:
+ case kConfigWin7:
+ case kConfigWin8:
+ case kConfigWin:
+ case kConfigMacLeopard:
+ case kConfigMacSnowLeopard:
+ case kConfigMacLion:
+ case kConfigMacMountainLion:
+ case kConfigMac:
+ case kConfigLinux:
+ case kConfigChromeOS:
+ case kConfigAndroid:
+ case kConfigNVidia:
+ case kConfigAMD:
+ case kConfigIntel:
+ case kConfigVMWare:
+ case kConfigRelease:
+ case kConfigDebug:
+ case kConfigGPUDeviceID:
+ if (token == kConfigGPUDeviceID) {
+ if (!UpdateTestConfig(config, tokens[i], 0))
+ return false;
+ } else {
+ if (!UpdateTestConfig(config, token, 0))
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GPUTestExpectationsParser::ParseLine(
+ const std::string& line_data, size_t line_number) {
+ std::vector<std::string> tokens;
+ base::SplitStringAlongWhitespace(line_data, &tokens);
+ int32 stage = kLineParserBegin;
+ GPUTestExpectationEntry entry;
+ entry.line_number = line_number;
+ GPUTestConfig& config = entry.test_config;
+ bool comments_encountered = false;
+ for (size_t i = 0; i < tokens.size() && !comments_encountered; ++i) {
+ Token token = ParseToken(tokens[i]);
+ switch (token) {
+ case kTokenComment:
+ comments_encountered = true;
+ break;
+ case kConfigWinXP:
+ case kConfigWinVista:
+ case kConfigWin7:
+ case kConfigWin8:
+ case kConfigWin:
+ case kConfigMacLeopard:
+ case kConfigMacSnowLeopard:
+ case kConfigMacLion:
+ case kConfigMacMountainLion:
+ case kConfigMac:
+ case kConfigLinux:
+ case kConfigChromeOS:
+ case kConfigAndroid:
+ case kConfigNVidia:
+ case kConfigAMD:
+ case kConfigIntel:
+ case kConfigVMWare:
+ case kConfigRelease:
+ case kConfigDebug:
+ case kConfigGPUDeviceID:
+ // MODIFIERS, could be in any order, need at least one.
+ if (stage != kLineParserConfigs && stage != kLineParserBugID) {
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+ line_number);
+ return false;
+ }
+ if (token == kConfigGPUDeviceID) {
+ if (!UpdateTestConfig(&config, tokens[i], line_number))
+ return false;
+ } else {
+ if (!UpdateTestConfig(&config, token, line_number))
+ return false;
+ }
+ if (stage == kLineParserBugID)
+ stage++;
+ break;
+ case kSeparatorColon:
+ // :
+ if (stage != kLineParserConfigs) {
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+ line_number);
+ return false;
+ }
+ stage++;
+ break;
+ case kSeparatorEqual:
+ // =
+ if (stage != kLineParserTestName) {
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+ line_number);
+ return false;
+ }
+ stage++;
+ break;
+ case kTokenWord:
+ // BUG_ID or TEST_NAME
+ if (stage == kLineParserBegin) {
+ // Bug ID is not used for anything; ignore it.
+ } else if (stage == kLineParserColon) {
+ entry.test_name = tokens[i];
+ } else {
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+ line_number);
+ return false;
+ }
+ stage++;
+ break;
+ case kExpectationPass:
+ case kExpectationFail:
+ case kExpectationFlaky:
+ case kExpectationTimeout:
+ case kExpectationSkip:
+ // TEST_EXPECTATIONS
+ if (stage != kLineParserEqual && stage != kLineParserExpectations) {
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+ line_number);
+ return false;
+ }
+ if ((kTokenData[token].flag & entry.test_expectation) != 0) {
+ PushErrorMessage(kErrorMessage[kErrorEntryWithExpectationConflicts],
+ line_number);
+ return false;
+ }
+ entry.test_expectation =
+ (kTokenData[token].flag | entry.test_expectation);
+ if (stage == kLineParserEqual)
+ stage++;
+ break;
+ default:
+ DCHECK(false);
+ break;
+ }
+ }
+ if (stage == kLineParserBegin) {
+ // The whole line is empty or all comments
+ return true;
+ }
+ if (stage == kLineParserExpectations) {
+ if (!config.IsValid()) {
+ PushErrorMessage(kErrorMessage[kErrorInvalidEntry], line_number);
+ return false;
+ }
+ entries_.push_back(entry);
+ return true;
+ }
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
+ return false;
+}
+
+bool GPUTestExpectationsParser::UpdateTestConfig(
+ GPUTestConfig* config, int32 token, size_t line_number) {
+ DCHECK(config);
+ switch (token) {
+ case kConfigWinXP:
+ case kConfigWinVista:
+ case kConfigWin7:
+ case kConfigWin8:
+ case kConfigWin:
+ case kConfigMacLeopard:
+ case kConfigMacSnowLeopard:
+ case kConfigMacLion:
+ case kConfigMacMountainLion:
+ case kConfigMac:
+ case kConfigLinux:
+ case kConfigChromeOS:
+ case kConfigAndroid:
+ if ((config->os() & kTokenData[token].flag) != 0) {
+ PushErrorMessage(kErrorMessage[kErrorEntryWithOsConflicts],
+ line_number);
+ return false;
+ }
+ config->set_os(config->os() | kTokenData[token].flag);
+ break;
+ case kConfigNVidia:
+ case kConfigAMD:
+ case kConfigIntel:
+ case kConfigVMWare:
+ {
+ uint32 gpu_vendor =
+ static_cast<uint32>(kTokenData[token].flag);
+ for (size_t i = 0; i < config->gpu_vendor().size(); ++i) {
+ if (config->gpu_vendor()[i] == gpu_vendor) {
+ PushErrorMessage(
+ kErrorMessage[kErrorEntryWithGpuVendorConflicts],
+ line_number);
+ return false;
+ }
+ }
+ config->AddGPUVendor(gpu_vendor);
+ }
+ break;
+ case kConfigRelease:
+ case kConfigDebug:
+ if ((config->build_type() & kTokenData[token].flag) != 0) {
+ PushErrorMessage(
+ kErrorMessage[kErrorEntryWithBuildTypeConflicts],
+ line_number);
+ return false;
+ }
+ config->set_build_type(
+ config->build_type() | kTokenData[token].flag);
+ break;
+ default:
+ DCHECK(false);
+ break;
+ }
+ return true;
+}
+
+bool GPUTestExpectationsParser::UpdateTestConfig(
+ GPUTestConfig* config,
+ const std::string& gpu_device_id,
+ size_t line_number) {
+ DCHECK(config);
+ uint32 device_id = 0;
+ if (config->gpu_device_id() != 0 ||
+ !base::HexStringToInt(gpu_device_id,
+ reinterpret_cast<int*>(&device_id)) ||
+ device_id == 0) {
+ PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts],
+ line_number);
+ return false;
+ }
+ config->set_gpu_device_id(device_id);
+ return true;
+}
+
+bool GPUTestExpectationsParser::DetectConflictsBetweenEntries() {
+ bool rt = false;
+ for (size_t i = 0; i < entries_.size(); ++i) {
+ for (size_t j = i + 1; j < entries_.size(); ++j) {
+ if (entries_[i].test_name == entries_[j].test_name &&
+ entries_[i].test_config.OverlapsWith(entries_[j].test_config)) {
+ PushErrorMessage(kErrorMessage[kErrorEntriesOverlap],
+ entries_[i].line_number,
+ entries_[j].line_number);
+ rt = true;
+ }
+ }
+ }
+ return rt;
+}
+
+void GPUTestExpectationsParser::PushErrorMessage(
+ const std::string& message, size_t line_number) {
+ error_messages_.push_back(
+ base::StringPrintf("Line %d : %s",
+ static_cast<int>(line_number), message.c_str()));
+}
+
+void GPUTestExpectationsParser::PushErrorMessage(
+ const std::string& message,
+ size_t entry1_line_number,
+ size_t entry2_line_number) {
+ error_messages_.push_back(
+ base::StringPrintf("Line %d and %d : %s",
+ static_cast<int>(entry1_line_number),
+ static_cast<int>(entry2_line_number),
+ message.c_str()));
+}
+
+GPUTestExpectationsParser:: GPUTestExpectationEntry::GPUTestExpectationEntry()
+ : test_expectation(0),
+ line_number(0) {
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_test_expectations_parser.h b/gpu/config/gpu_test_expectations_parser.h
new file mode 100644
index 0000000..a69f7e9
--- /dev/null
+++ b/gpu/config/gpu_test_expectations_parser.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_
+#define GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "gpu/config/gpu_test_config.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+
+class GPU_EXPORT GPUTestExpectationsParser {
+ public:
+ enum GPUTestExpectation {
+ kGpuTestPass = 1 << 0,
+ kGpuTestFail = 1 << 1,
+ kGpuTestFlaky = 1 << 2,
+ kGpuTestTimeout = 1 << 3,
+ kGpuTestSkip = 1 << 4,
+ };
+
+ GPUTestExpectationsParser();
+ ~GPUTestExpectationsParser();
+
+ // Parse the text expectations, and if no error is encountered,
+ // save all the entries. Otherwise, generate error messages.
+ // Return true if parsing succeeds.
+ bool LoadTestExpectations(const std::string& data);
+ bool LoadTestExpectations(const base::FilePath& path);
+
+ // Query error messages from the last LoadTestExpectations() call.
+ const std::vector<std::string>& GetErrorMessages() const;
+
+ // Get the test expectation of a given test on a given bot.
+ int32 GetTestExpectation(const std::string& test_name,
+ const GPUTestBotConfig& bot_config) const;
+
+ // Parse a list of config modifiers. If we have a valid entry with no
+ // conflicts, | config | stores it, and the function returns true.
+ bool ParseConfig(const std::string& config_data, GPUTestConfig* config);
+
+ private:
+ struct GPUTestExpectationEntry {
+ GPUTestExpectationEntry();
+
+ std::string test_name;
+ GPUTestConfig test_config;
+ int32 test_expectation;
+ size_t line_number;
+ };
+
+ // Parse a line of text. If we have a valid entry, save it; otherwise,
+ // generate error messages.
+ bool ParseLine(const std::string& line_data, size_t line_number);
+
+ // Update OS/GPUVendor/BuildType modifiers. May generate an error message.
+ bool UpdateTestConfig(
+ GPUTestConfig* config, int32 token, size_t line_number);
+
+ // Update GPUDeviceID modifier. May generate an error message.
+ bool UpdateTestConfig(GPUTestConfig* config,
+ const std::string & gpu_device_id,
+ size_t line_number);
+
+ // Check if two entries' config overlap with each other. May generate an
+ // error message.
+ bool DetectConflictsBetweenEntries();
+
+ // Save an error message, which can be queried later.
+ void PushErrorMessage(const std::string& message, size_t line_number);
+ void PushErrorMessage(const std::string& message,
+ size_t entry1_line_number,
+ size_t entry2_line_number);
+
+ std::vector<GPUTestExpectationEntry> entries_;
+ std::vector<std::string> error_messages_;
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_
+
diff --git a/gpu/config/gpu_test_expectations_parser_unittest.cc b/gpu/config/gpu_test_expectations_parser_unittest.cc
new file mode 100644
index 0000000..79c169c
--- /dev/null
+++ b/gpu/config/gpu_test_expectations_parser_unittest.cc
@@ -0,0 +1,245 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "gpu/config/gpu_test_expectations_parser.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+class GPUTestExpectationsParserTest : public testing::Test {
+ public:
+ GPUTestExpectationsParserTest() { }
+
+ virtual ~GPUTestExpectationsParserTest() { }
+
+ const GPUTestBotConfig& bot_config() const {
+ return bot_config_;
+ }
+
+ protected:
+ virtual void SetUp() {
+ bot_config_.set_os(GPUTestConfig::kOsWin7);
+ bot_config_.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ bot_config_.AddGPUVendor(0x10de);
+ bot_config_.set_gpu_device_id(0x0640);
+ ASSERT_TRUE(bot_config_.IsValid());
+ }
+
+ virtual void TearDown() { }
+
+ private:
+ GPUTestBotConfig bot_config_;
+};
+
+TEST_F(GPUTestExpectationsParserTest, CommentOnly) {
+ const std::string text =
+ " \n"
+ "// This is just some comment\n"
+ "";
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass,
+ parser.GetTestExpectation("some_test", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, ValidFullEntry) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestFail,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, ValidPartialEntry) {
+ const std::string text =
+ "BUG12345 WIN NVIDIA : MyTest = TIMEOUT";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestTimeout,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, ValidUnrelatedOsEntry) {
+ const std::string text =
+ "BUG12345 LEOPARD : MyTest = TIMEOUT";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, ValidUnrelatedTestEntry) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : AnotherTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, AllModifiers) {
+ const std::string text =
+ "BUG12345 XP VISTA WIN7 WIN8 LEOPARD SNOWLEOPARD LION MOUNTAINLION "
+ "LINUX CHROMEOS ANDROID "
+ "NVIDIA INTEL AMD VMWARE RELEASE DEBUG : MyTest = "
+ "PASS FAIL FLAKY TIMEOUT SKIP";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass |
+ GPUTestExpectationsParser::kGpuTestFail |
+ GPUTestExpectationsParser::kGpuTestFlaky |
+ GPUTestExpectationsParser::kGpuTestTimeout |
+ GPUTestExpectationsParser::kGpuTestSkip,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, DuplicateModifiers) {
+ const std::string text =
+ "BUG12345 WIN7 WIN7 RELEASE NVIDIA 0x0640 : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, AllModifiersLowerCase) {
+ const std::string text =
+ "BUG12345 xp vista win7 leopard snowleopard lion linux chromeos android "
+ "nvidia intel amd vmware release debug : MyTest = "
+ "pass fail flaky timeout skip";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass |
+ GPUTestExpectationsParser::kGpuTestFail |
+ GPUTestExpectationsParser::kGpuTestFlaky |
+ GPUTestExpectationsParser::kGpuTestTimeout |
+ GPUTestExpectationsParser::kGpuTestSkip,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, MissingColon) {
+ const std::string text =
+ "BUG12345 XP MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, MissingEqual) {
+ const std::string text =
+ "BUG12345 XP : MyTest FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, IllegalModifier) {
+ const std::string text =
+ "BUG12345 XP XXX : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, OsConflicts) {
+ const std::string text =
+ "BUG12345 XP WIN : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, InvalidModifierCombination) {
+ const std::string text =
+ "BUG12345 XP NVIDIA INTEL 0x0640 : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, BadGpuDeviceID) {
+ const std::string text =
+ "BUG12345 XP NVIDIA 0xU07X : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, MoreThanOneGpuDeviceID) {
+ const std::string text =
+ "BUG12345 XP NVIDIA 0x0640 0x0641 : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, MultipleEntriesConflicts) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : MyTest = FAIL\n"
+ "BUG12345 WIN : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, MultipleTests) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : MyTest = FAIL\n"
+ "BUG12345 WIN : AnotherTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, ValidMultipleEntries) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : MyTest = FAIL\n"
+ "BUG12345 LINUX : MyTest = TIMEOUT";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestFail,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, StarMatching) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : MyTest* = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestFail,
+ parser.GetTestExpectation("MyTest0", bot_config()));
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass,
+ parser.GetTestExpectation("OtherTest", bot_config()));
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc
new file mode 100644
index 0000000..7fae88a
--- /dev/null
+++ b/gpu/config/gpu_util.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_util.h"
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/config/gpu_control_list_jsons.h"
+#include "gpu/config/gpu_driver_bug_list.h"
+#include "gpu/config/gpu_info_collector.h"
+#include "ui/gl/gl_switches.h"
+
+namespace gpu {
+
+namespace {
+
+// Combine the integers into a string, seperated by ','.
+std::string IntSetToString(const std::set<int>& list) {
+ std::string rt;
+ for (std::set<int>::const_iterator it = list.begin();
+ it != list.end(); ++it) {
+ if (!rt.empty())
+ rt += ",";
+ rt += base::IntToString(*it);
+ }
+ return rt;
+}
+
+} // namespace anonymous
+
+GpuSwitchingOption StringToGpuSwitchingOption(
+ const std::string& switching_string) {
+ if (switching_string == switches::kGpuSwitchingOptionNameAutomatic)
+ return GPU_SWITCHING_OPTION_AUTOMATIC;
+ if (switching_string == switches::kGpuSwitchingOptionNameForceIntegrated)
+ return GPU_SWITCHING_OPTION_FORCE_INTEGRATED;
+ if (switching_string == switches::kGpuSwitchingOptionNameForceDiscrete)
+ return GPU_SWITCHING_OPTION_FORCE_DISCRETE;
+ return GPU_SWITCHING_OPTION_UNKNOWN;
+}
+
+std::string GpuSwitchingOptionToString(GpuSwitchingOption option) {
+ switch (option) {
+ case GPU_SWITCHING_OPTION_AUTOMATIC:
+ return switches::kGpuSwitchingOptionNameAutomatic;
+ case GPU_SWITCHING_OPTION_FORCE_INTEGRATED:
+ return switches::kGpuSwitchingOptionNameForceIntegrated;
+ case GPU_SWITCHING_OPTION_FORCE_DISCRETE:
+ return switches::kGpuSwitchingOptionNameForceDiscrete;
+ default:
+ return "unknown";
+ }
+}
+
+void MergeFeatureSets(std::set<int>* dst, const std::set<int>& src) {
+ DCHECK(dst);
+ if (src.empty())
+ return;
+ dst->insert(src.begin(), src.end());
+}
+
+void ApplyGpuDriverBugWorkarounds(CommandLine* command_line) {
+ GPUInfo gpu_info;
+ CollectBasicGraphicsInfo(&gpu_info);
+
+ GpuDriverBugList* list = GpuDriverBugList::Create();
+ list->LoadList("0", kGpuDriverBugListJson,
+ GpuControlList::kCurrentOsOnly);
+ std::set<int> workarounds = list->MakeDecision(
+ GpuControlList::kOsAny, std::string(), gpu_info);
+ if (!workarounds.empty()) {
+ command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds,
+ IntSetToString(workarounds));
+ }
+}
+
+} // namespace gpu
diff --git a/gpu/config/gpu_util.h b/gpu/config/gpu_util.h
new file mode 100644
index 0000000..6d6800e
--- /dev/null
+++ b/gpu/config/gpu_util.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_UTIL_H_
+#define GPU_CONFIG_GPU_UTIL_H_
+
+#include <set>
+#include <string>
+
+#include "build/build_config.h"
+#include "gpu/config/gpu_switching_option.h"
+#include "gpu/gpu_export.h"
+
+class CommandLine;
+
+namespace gpu {
+
+// Maps string to GpuSwitchingOption; returns GPU_SWITCHING_UNKNOWN if an
+// unknown name is input (case-sensitive).
+GPU_EXPORT GpuSwitchingOption StringToGpuSwitchingOption(
+ const std::string& switching_string);
+
+// Gets a string version of a GpuSwitchingOption.
+GPU_EXPORT std::string GpuSwitchingOptionToString(GpuSwitchingOption option);
+
+// Merge features in src into dst.
+GPU_EXPORT void MergeFeatureSets(
+ std::set<int>* dst, const std::set<int>& src);
+
+// Collect basic GPUInfo, compute the driver bug workarounds for the current
+// system, and append the |command_line|.
+GPU_EXPORT void ApplyGpuDriverBugWorkarounds(CommandLine* command_line);
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_UTIL_H_
+
diff --git a/gpu/config/gpu_util_unittest.cc b/gpu/config/gpu_util_unittest.cc
new file mode 100644
index 0000000..f3e3f8f
--- /dev/null
+++ b/gpu/config/gpu_util_unittest.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gl/gl_switches.h"
+
+namespace gpu {
+
+TEST(GpuUtilTest, GpuSwitchingOptionFromString) {
+ // Test StringToGpuSwitchingOption.
+ EXPECT_EQ(StringToGpuSwitchingOption(
+ switches::kGpuSwitchingOptionNameAutomatic),
+ GPU_SWITCHING_OPTION_AUTOMATIC);
+ EXPECT_EQ(StringToGpuSwitchingOption(
+ switches::kGpuSwitchingOptionNameForceDiscrete),
+ GPU_SWITCHING_OPTION_FORCE_DISCRETE);
+ EXPECT_EQ(StringToGpuSwitchingOption(
+ switches::kGpuSwitchingOptionNameForceIntegrated),
+ GPU_SWITCHING_OPTION_FORCE_INTEGRATED);
+ EXPECT_EQ(StringToGpuSwitchingOption("xxx"), GPU_SWITCHING_OPTION_UNKNOWN);
+}
+
+TEST(GpuUtilTest, GpuSwitchingOptionToString) {
+ // Test GpuSwitchingOptionToString.
+ EXPECT_STREQ(
+ GpuSwitchingOptionToString(GPU_SWITCHING_OPTION_AUTOMATIC).c_str(),
+ switches::kGpuSwitchingOptionNameAutomatic);
+ EXPECT_STREQ(
+ GpuSwitchingOptionToString(GPU_SWITCHING_OPTION_FORCE_DISCRETE).c_str(),
+ switches::kGpuSwitchingOptionNameForceDiscrete);
+ EXPECT_STREQ(
+ GpuSwitchingOptionToString(GPU_SWITCHING_OPTION_FORCE_INTEGRATED).c_str(),
+ switches::kGpuSwitchingOptionNameForceIntegrated);
+}
+
+TEST(GpuUtilTest, MergeFeatureSets) {
+ {
+ // Merge two empty sets.
+ std::set<int> src;
+ std::set<int> dst;
+ EXPECT_TRUE(dst.empty());
+ MergeFeatureSets(&dst, src);
+ EXPECT_TRUE(dst.empty());
+ }
+ {
+ // Merge an empty set into a set with elements.
+ std::set<int> src;
+ std::set<int> dst;
+ dst.insert(1);
+ EXPECT_EQ(1u, dst.size());
+ MergeFeatureSets(&dst, src);
+ EXPECT_EQ(1u, dst.size());
+ }
+ {
+ // Merge two sets where the source elements are already in the target set.
+ std::set<int> src;
+ std::set<int> dst;
+ src.insert(1);
+ dst.insert(1);
+ EXPECT_EQ(1u, dst.size());
+ MergeFeatureSets(&dst, src);
+ EXPECT_EQ(1u, dst.size());
+ }
+ {
+ // Merge two sets with different elements.
+ std::set<int> src;
+ std::set<int> dst;
+ src.insert(1);
+ dst.insert(2);
+ EXPECT_EQ(1u, dst.size());
+ MergeFeatureSets(&dst, src);
+ EXPECT_EQ(2u, dst.size());
+ }
+}
+
+} // namespace gpu
diff --git a/gpu/config/software_rendering_list_json.cc b/gpu/config/software_rendering_list_json.cc
new file mode 100644
index 0000000..9621100
--- /dev/null
+++ b/gpu/config/software_rendering_list_json.cc
@@ -0,0 +1,1116 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Determines whether certain gpu-related features are blacklisted or not.
+// A valid software_rendering_list.json file are in the format of
+// {
+// "version": "x.y",
+// "entries": [
+// { // entry 1
+// },
+// ...
+// { // entry n
+// }
+// ]
+// }
+//
+// Each entry contains the following fields (fields are optional unless
+// specifically described as mandatory below):
+// 1. "id" is an integer. 0 is reserved. This field is mandatory.
+// 2. "os" contains "type" and an optional "version". "type" could be "macosx",
+// "linux", "win", "chromeos", or "any". "any" is the same as not specifying
+// "os".
+// "version" is a VERSION structure (defined below).
+// 3. "vendor_id" is a string. 0 is reserved.
+// 4. "device_id" is an array of strings. 0 is reserved.
+// 5. "multi_gpu_style" is a string, valid values include "optimus", and
+// "amd_switchable".
+// 6. "multi_gpu_category" is a string, valid values include "any", "primary",
+// and "secondary". If unspecified, the default value is "primary".
+// 7. "driver_vendor" is a STRING structure (defined below).
+// 8. "driver_version" is a VERSION structure (defined below).
+// 9. "driver_date" is a VERSION structure (defined below).
+// The version is interpreted as "year.month.day".
+// 10. "gl_vendor" is a STRING structure (defined below).
+// 11. "gl_renderer" is a STRING structure (defined below).
+// 12. "gl_extensions" is a STRING structure (defined below).
+// 13. "perf_graphics" is a FLOAT structure (defined below).
+// 14. "perf_gaming" is a FLOAT structure (defined below).
+// 15. "perf_overall" is a FLOAT structure (defined below).
+// 16. "machine_model" contais "name" and an optional "version". "name" is a
+// STRING structure and "version" is a VERSION structure (defined below).
+// 17. "gpu_count" is a INT structure (defined below).
+// 18 "cpu_info" is a STRING structure (defined below).
+// 19. "exceptions" is a list of entries.
+// 20. "features" is a list of gpu feature strings, valid values include
+// "accelerated_2d_canvas", "accelerated_compositing", "webgl",
+// "multisampling", "flash_3d", "flash_stage3d", "texture_sharing",
+// "accelerated_video", "accelerated_video_decode", "panel_fitting",
+// "force_compositing_mode", and "all".
+// This field is mandatory.
+// 21. "description" has the description of the entry.
+// 22. "webkit_bugs" is an array of associated webkit bug numbers.
+// 23. "cr_bugs" is an array of associated webkit bug numbers.
+// 24. "browser_version" is a VERSION structure (defined below). If this
+// condition is not satisfied, the entry will be ignored. If it is not
+// present, then the entry applies to all versions of the browser.
+// 25. "disabled" is a boolean. If it is present, the entry will be skipped.
+// This can not be used in exceptions.
+//
+// VERSION includes "op", "style", "number", and "number2". "op" can be any of
+// the following values: "=", "<", "<=", ">", ">=", "any", "between". "style"
+// is optional and can be "lexical" or "numerical"; if it's not specified, it
+// defaults to "numerical". "number2" is only used if "op" is "between".
+// "between" is "number <= * <= number2".
+// "number" is used for all "op" values except "any". "number" and "number2"
+// are in the format of x, x.x, x.x.x, etc.
+// Only "driver_version" supports lexical style if the format is major.minor;
+// in that case, major is still numerical, but minor is lexical.
+//
+// STRING includes "op" and "value". "op" can be any of the following values:
+// "contains", "beginwith", "endwith", "=". "value" is a string.
+//
+// FLOAT includes "op" "value", and "value2". "op" can be any of the
+// following values: "=", "<", "<=", ">", ">=", "any", "between". "value2" is
+// only used if "op" is "between". "value" is used for all "op" values except
+// "any". "value" and "value2" are valid float numbers.
+// INT is very much like FLOAT, except that the values need to be integers.
+
+#include "gpu/config/gpu_control_list_jsons.h"
+
+#define LONG_STRING_CONST(...) #__VA_ARGS__
+
+namespace gpu {
+
+const char kSoftwareRenderingListJson[] = LONG_STRING_CONST(
+
+{
+ "name": "software rendering list",
+ // Please update the version number whenever you change this file.
+ "version": "6.0",
+ "entries": [
+ {
+ "id": 1,
+ "description": "ATI Radeon X1900 is not compatible with WebGL on the Mac.",
+ "webkit_bugs": [47028],
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x1002",
+ "device_id": ["0x7249"],
+ "features": [
+ "webgl",
+ "flash_3d",
+ "flash_stage3d"
+ ]
+ },
+ {
+ "id": 3,
+ "description": "GL driver is software rendered. Accelerated compositing is disabled.",
+ "cr_bugs": [59302],
+ "os": {
+ "type": "linux"
+ },
+ "gl_renderer": {
+ "op": "contains",
+ "value": "software"
+ },
+ "features": [
+ "accelerated_compositing"
+ ]
+ },
+ {
+ "id": 4,
+ "description": "The Intel Mobile 945 Express family of chipsets is not compatible with WebGL.",
+ "os": {
+ "type": "any"
+ },
+ "vendor_id": "0x8086",
+ "device_id": ["0x27AE"],
+ "features": [
+ "webgl",
+ "flash_3d",
+ "flash_stage3d"
+ ]
+ },
+ {
+ "id": 5,
+ "description": "ATI/AMD cards with older or third-party drivers in Linux are crash-prone.",
+ "cr_bugs": [71381, 76428, 73910, 101225, 136240],
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x1002",
+ "exceptions": [
+ {
+ "driver_vendor": {
+ "op": "contains",
+ "value": "AMD"
+ },
+ "driver_version": {
+ "op": ">=",
+ "style": "lexical",
+ "number": "8.98"
+ }
+ }
+ ],
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 8,
+ "description": "NVIDIA GeForce FX Go5200 is assumed to be buggy.",
+ "cr_bugs": [72938],
+ "os": {
+ "type": "any"
+ },
+ "vendor_id": "0x10de",
+ "device_id": ["0x0324"],
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 10,
+ "description": "NVIDIA GeForce 7300 GT on Mac does not support WebGL.",
+ "cr_bugs": [73794],
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x10de",
+ "device_id": ["0x0393"],
+ "features": [
+ "webgl",
+ "flash_3d",
+ "flash_stage3d"
+ ]
+ },
+ {
+ "id": 12,
+ "description": "Drivers older than 2009-01 on Windows are possibly unreliable.",
+ "cr_bugs": [72979, 89802],
+ "os": {
+ "type": "win"
+ },
+ "driver_date": {
+ "op": "<",
+ "number": "2009.1"
+ },
+ "exceptions": [
+ {
+ "vendor_id": "0x8086",
+ "device_id": ["0x29a2"],
+ "driver_version": {
+ "op": ">=",
+ "number": "7.15.10.1624"
+ }
+ }
+ ],
+ "features": [
+ "accelerated_2d_canvas",
+ "accelerated_video",
+ "accelerated_video_decode",
+ "3d_css",
+ "multisampling",
+ "flash_3d",
+ "force_compositing_mode"
+ ]
+ },
+ {
+ "id": 13,
+ "description": "ATI drivers older than 10.6 on Windows XP are possibly unreliable.",
+ "cr_bugs": [74212],
+ "os": {
+ "type": "win",
+ "version": {
+ "op": "=",
+ "number": "5"
+ }
+ },
+ "vendor_id": "0x1002",
+ "driver_version": {
+ "op": "<",
+ "number": "8.741"
+ },
+ "features": [
+ "accelerated_video",
+ "accelerated_video_decode",
+ "3d_css",
+ "multisampling",
+ "flash_3d",
+ "force_compositing_mode"
+ ]
+ },
+ {
+ "id": 14,
+ "description": "NVIDIA drivers older than 257.21 on Windows XP are possibly unreliable.",
+ "cr_bugs": [74212],
+ "os": {
+ "type": "win",
+ "version": {
+ "op": "=",
+ "number": "5"
+ }
+ },
+ "vendor_id": "0x10de",
+ "driver_version": {
+ "op": "<",
+ "number": "6.14.12.5721"
+ },
+ "features": [
+ "accelerated_video",
+ "accelerated_video_decode",
+ "3d_css",
+ "multisampling",
+ "flash_3d",
+ "force_compositing_mode"
+ ]
+ },
+ {
+ "id": 15,
+ "description": "Intel drivers older than 14.42.7.5294 on Windows XP are possibly unreliable.",
+ "cr_bugs": [74212],
+ "os": {
+ "type": "win",
+ "version": {
+ "op": "=",
+ "number": "5"
+ }
+ },
+ "vendor_id": "0x8086",
+ "driver_version": {
+ "op": "<",
+ "number": "6.14.10.5294"
+ },
+ "features": [
+ "accelerated_video",
+ "accelerated_video_decode",
+ "3d_css",
+ "multisampling",
+ "flash_3d",
+ "force_compositing_mode"
+ ]
+ },
+ {
+ "id": 16,
+ "description": "Multisampling is buggy in ATI cards on older MacOSX.",
+ "cr_bugs": [67752, 83153],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "<",
+ "number": "10.7.2"
+ }
+ },
+ "vendor_id": "0x1002",
+ "features": [
+ "multisampling"
+ ]
+ },
+ {
+ "id": 17,
+ "description": "Intel mesa drivers are crash-prone.",
+ "cr_bugs": [76703, 164555],
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x8086",
+ "exceptions": [
+ {
+ "device_id": ["0x0102", "0x0106", "0x0112", "0x0116", "0x0122", "0x0126", "0x010a", "0x0152", "0x0156", "0x015a", "0x0162", "0x0166"],
+ "driver_version": {
+ "op": ">=",
+ "number": "8.0"
+ }
+ },
+ {
+ "device_id": ["0xa001", "0xa002", "0xa011", "0xa012", "0x29a2", "0x2992", "0x2982", "0x2972", "0x2a12", "0x2a42", "0x2e02", "0x2e12", "0x2e22", "0x2e32", "0x2e42", "0x2e92"],
+ "driver_version": {
+ "op": ">",
+ "number": "8.0.2"
+ }
+ },
+ {
+ "device_id": ["0x0042", "0x0046"],
+ "driver_version": {
+ "op": ">=",
+ "number": "8.0.2"
+ }
+ },
+ {
+ "device_id": ["0x2a02"],
+ "driver_version": {
+ "op": ">=",
+ "number": "9.1"
+ }
+ }
+ ],
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 18,
+ "description": "NVIDIA Quadro FX 1500 is buggy.",
+ "cr_bugs": [84701],
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x10de",
+ "device_id": ["0x029e"],
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 19,
+ "description": "GPU acceleration is no longer supported in Leopard.",
+ "cr_bugs": [87157, 130495],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "=",
+ "number": "10.5"
+ }
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 23,
+ "description": "Mesa drivers in linux older than 7.11 are assumed to be buggy.",
+ "os": {
+ "type": "linux"
+ },
+ "driver_vendor": {
+ "op": "=",
+ "value": "Mesa"
+ },
+ "driver_version": {
+ "op": "<",
+ "number": "7.11"
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 24,
+ "description": "Accelerated 2d canvas is unstable in Linux at the moment.",
+ "os": {
+ "type": "linux"
+ },
+ "features": [
+ "accelerated_2d_canvas"
+ ]
+ },
+ {
+ "id": 27,
+ "description": "ATI/AMD cards with older drivers in Linux are crash-prone.",
+ "cr_bugs": [95934, 94973, 136240],
+ "os": {
+ "type": "linux"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "ATI"
+ },
+ "exceptions": [
+ {
+ "driver_vendor": {
+ "op": "contains",
+ "value": "AMD"
+ },
+ "driver_version": {
+ "op": ">=",
+ "style": "lexical",
+ "number": "8.98"
+ }
+ }
+ ],
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 28,
+ "description": "ATI/AMD cards with third-party drivers in Linux are crash-prone.",
+ "cr_bugs": [95934, 94973],
+ "os": {
+ "type": "linux"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "X.Org"
+ },
+ "gl_renderer": {
+ "op": "contains",
+ "value": "AMD"
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 29,
+ "description": "ATI/AMD cards with third-party drivers in Linux are crash-prone.",
+ "cr_bugs": [95934, 94973],
+ "os": {
+ "type": "linux"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "X.Org"
+ },
+ "gl_renderer": {
+ "op": "contains",
+ "value": "ATI"
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 30,
+ "description": "NVIDIA cards with nouveau drivers in Linux are crash-prone.",
+ "cr_bugs": [94103],
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x10de",
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "nouveau"
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 32,
+ "description": "Accelerated 2d canvas is disabled on Windows systems with low perf stats.",
+ "cr_bugs": [116350, 151500],
+ "os": {
+ "type": "win"
+ },
+ "perf_overall": {
+ "op": "<",
+ "value": "3.5"
+ },
+ "exceptions": [
+ {
+ "perf_gaming": {
+ "op": ">",
+ "value": "3.5"
+ }
+ },
+ {
+ "cpu_info": {
+ "op": "contains",
+ "value": "Atom"
+ }
+ }
+ ],
+ "features": [
+ "accelerated_2d_canvas"
+ ]
+ },
+ {
+ "id": 33,
+ "description": "Multisampling is buggy in Intel IvyBridge.",
+ "cr_bugs": [116370],
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x8086",
+ "device_id": ["0x0152", "0x0156", "0x015a", "0x0162", "0x0166"],
+ "features": [
+ "multisampling"
+ ]
+ },
+ {
+ "id": 34,
+ "description": "S3 Trio (used in Virtual PC) is not compatible.",
+ "cr_bugs": [119948],
+ "os": {
+ "type": "win"
+ },
+ "vendor_id": "0x5333",
+ "device_id": ["0x8811"],
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 35,
+ "description": "Stage3D is not supported on Linux.",
+ "cr_bugs": [129848],
+ "os": {
+ "type": "linux"
+ },
+ "features": [
+ "flash_stage3d"
+ ]
+ },
+ {
+ "id": 37,
+ "description": "Drivers are unreliable for Optimus on Linux.",
+ "cr_bugs": [131308],
+ "os": {
+ "type": "linux"
+ },
+ "multi_gpu_style": "optimus",
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 38,
+ "description": "Accelerated 2D canvas is unstable for NVidia GeForce 9400M on Lion.",
+ "cr_bugs": [130495],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "=",
+ "number": "10.7"
+ }
+ },
+ "vendor_id": "0x10de",
+ "device_id": ["0x0863"],
+ "features": [
+ "accelerated_2d_canvas"
+ ]
+ },
+ {
+ "id": 41,
+ "description": "Disable 3D (but not Stage3D) in Flash on XP",
+ "cr_bugs": [134885],
+ "os": {
+ "type": "win",
+ "version": {
+ "op": "=",
+ "number": "5"
+ }
+ },
+ "features": [
+ "flash_3d"
+ ]
+ },
+ {
+ "id": 42,
+ "description": "AMD Radeon HD 6490M on Snow Leopard is buggy.",
+ "cr_bugs": [137307],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "=",
+ "number": "10.6"
+ }
+ },
+ "vendor_id": "0x1002",
+ "device_id": ["0x6760"],
+ "features": [
+ "webgl"
+ ]
+ },
+ {
+ "id": 43,
+ "description": "Intel driver version 8.15.10.1749 has problems sharing textures.",
+ "cr_bugs": [133924],
+ "os": {
+ "type": "win"
+ },
+ "vendor_id": "0x8086",
+ "driver_version": {
+ "op": "=",
+ "number": "8.15.10.1749"
+ },
+ "features": [
+ "texture_sharing"
+ ]
+ },
+ {
+ "id": 44,
+ "description": "Intel HD 4000 causes kernel panic on Lion.",
+ "cr_bugs": [134015],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "between",
+ "number": "10.7.0",
+ "number2": "10.7.4"
+ }
+ },
+ "vendor_id": "0x8086",
+ "device_id": ["0x0166"],
+ "multi_gpu_category": "any",
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 45,
+ "description": "Parallels drivers older than 7 are buggy.",
+ "cr_bugs": [138105],
+ "os": {
+ "type": "win"
+ },
+ "vendor_id": "0x1ab8",
+ "driver_version": {
+ "op": "<",
+ "number": "7"
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 46,
+ "description": "ATI FireMV 2400 cards on Windows are buggy.",
+ "cr_bugs": [124152],
+ "os": {
+ "type": "win"
+ },
+ "vendor_id": "0x1002",
+ "device_id": ["0x3151"],
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 47,
+ "description": "NVIDIA linux drivers older than 295.* are assumed to be buggy.",
+ "cr_bugs": [78497],
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x10de",
+ "driver_vendor": {
+ "op": "=",
+ "value": "NVIDIA"
+ },
+ "driver_version": {
+ "op": "<",
+ "number": "295"
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 48,
+ // Please keep in sync with content/test/content_browser_test.cc.
+ "description": "Accelerated video decode is unavailable on Mac and Linux.",
+ "cr_bugs": [137247, 133828],
+ "exceptions": [
+ {
+ "os": {
+ "type": "chromeos"
+ }
+ },
+ {
+ "os": {
+ "type": "win"
+ }
+ }
+ ],
+ "features": [
+ "accelerated_video_decode"
+ ]
+ },
+ {
+ "id": 49,
+ "description": "NVidia GeForce GT 650M can cause the system to hang with flash 3D.",
+ "cr_bugs": [140175],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "between",
+ "number": "10.8.0",
+ "number2": "10.8.1"
+ }
+ },
+ "multi_gpu_style": "optimus",
+ "vendor_id": "0x10de",
+ "device_id": ["0x0fd5"],
+ "features": [
+ "flash_3d",
+ "flash_stage3d"
+ ]
+ },
+ {
+ "id": 50,
+ "description": "Disable VMware software renderer.",
+ "cr_bugs": [145531],
+ "os": {
+ "type": "linux"
+ },
+ "gl_vendor": {
+ "op": "beginwith",
+ "value": "VMware"
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 51,
+ "description": "NVIDIA drivers 6.14.11.9621 is buggy on Windows XP.",
+ "cr_bugs": [152096],
+ "os": {
+ "type": "win",
+ "version": {
+ "op": "=",
+ "number": "5"
+ }
+ },
+ "vendor_id": "0x10de",
+ "driver_version": {
+ "op": "=",
+ "number": "6.14.11.9621"
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 52,
+ "description": "NVIDIA drivers 6.14.11.8267 is buggy on Windows XP.",
+ "cr_bugs": [152096],
+ "os": {
+ "type": "win",
+ "version": {
+ "op": "=",
+ "number": "5"
+ }
+ },
+ "vendor_id": "0x10de",
+ "driver_version": {
+ "op": "=",
+ "number": "6.14.11.8267"
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 53,
+ "description": "The Intel GMA500 is too slow for Stage3D.",
+ "cr_bugs": [152096],
+ "vendor_id": "0x8086",
+ "device_id": ["0x8108", "0x8109"],
+ "features": [
+ "flash_stage3d"
+ ]
+ },
+ {
+ "id": 55,
+ "description": "Drivers older than 2007-01 on Windows are assumed to be buggy.",
+ "cr_bugs": [72979, 89802],
+ "os": {
+ "type": "win"
+ },
+ "driver_date": {
+ "op": "<",
+ "number": "2007.1"
+ },
+ "exceptions": [
+ {
+ "vendor_id": "0x8086",
+ "device_id": ["0x29a2"],
+ "driver_version": {
+ "op": ">=",
+ "number": "7.15.10.1624"
+ }
+ }
+ ],
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 56,
+ "description": "NVIDIA linux drivers are unstable when using multiple Open GL contexts and with low memory.",
+ "cr_bugs": [145600],
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x10de",
+ "driver_vendor": {
+ "op": "=",
+ "value": "NVIDIA"
+ },
+ "features": [
+ "accelerated_video",
+ "accelerated_video_decode",
+ "flash_3d",
+ "flash_stage3d"
+ ]
+ },
+ {
+ "id": 57,
+ "description": "Enable panel fitting capability on ChromeOS only on IVB and SNB Graphics Controllers.",
+ "exceptions": [
+ {
+ "os": {
+ "type": "chromeos"
+ },
+ "vendor_id": "0x8086",
+ "device_id": ["0x0106", "0x0116", "0x0166"]
+ }
+ ],
+ "features": [
+ "panel_fitting"
+ ]
+ },
+ {
+ "id": 59,
+ "description": "NVidia driver 8.15.11.8593 is crashy on Windows.",
+ "cr_bugs": [155749],
+ "os": {
+ "type": "win"
+ },
+ "vendor_id": "0x10de",
+ "driver_version": {
+ "op": "=",
+ "number": "8.15.11.8593"
+ },
+ "features": [
+ "accelerated_video_decode"
+ ]
+ },
+ {
+ "id": 60,
+ "description": "Multisampling is buggy on Mac with NVIDIA gpu prior to 10.8.3.",
+ "cr_bugs": [137303],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "<",
+ "number": "10.8.3"
+ }
+ },
+ "vendor_id": "0x10de",
+ "features": [
+ "multisampling"
+ ]
+ },
+ {
+ "id": 61,
+ "description": "Multisampling is buggy on Mac with Intel gpu prior to 10.8.3.",
+ "cr_bugs": [137303],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "<",
+ "number": "10.8.3"
+ }
+ },
+ "vendor_id": "0x8086",
+ "features": [
+ "multisampling"
+ ]
+ },
+ {
+ "id": 62,
+ "description": "Accelerated 2D canvas buggy on old Qualcomm Adreno.",
+ "cr_bugs": [161575],
+ "os": {
+ "type": "android"
+ },
+ "gl_renderer": {
+ "op": "contains",
+ "value": "Adreno"
+ },
+ "driver_version": {
+ "op": "<",
+ "number": "4.1"
+ },
+ "features": [
+ "accelerated_2d_canvas"
+ ]
+ },
+ {
+ "id": 63,
+ "description": "Multisampling is buggy on Mac with AMD gpu prior to 10.8.3.",
+ "cr_bugs": [162466],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "<",
+ "number": "10.8.3"
+ }
+ },
+ "vendor_id": "0x1002",
+ "features": [
+ "multisampling"
+ ]
+ },
+ {
+ "id": 64,
+ "description": "Hardware video decode is only supported in win7+.",
+ "cr_bugs": [159458],
+ "os": {
+ "type": "win",
+ "version": {
+ "op": "<",
+ "number": "6.1"
+ }
+ },
+ "features": [
+ "accelerated_video_decode"
+ ]
+ },
+ {
+ "id": 65,
+ "description": "Force compositing mode is unstable in Win Vista.",
+ "cr_bugs": [170421],
+ "os": {
+ "type": "win",
+ "version": {
+ "op": "=",
+ "number": "6.0"
+ }
+ },
+ "features": [
+ "force_compositing_mode"
+ ]
+ },
+ {
+ "id": 66,
+ "description": "Force compositing mode is unstable in MacOSX earlier than 10.8.",
+ "cr_bugs": [174101],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "<",
+ "number": "10.8"
+ }
+ },
+ "features": [
+ "force_compositing_mode"
+ ]
+ },
+ {
+ "id": 67,
+ "description": "Accelerated 2D Canvas is not supported on WinXP.",
+ "cr_bugs": [175149],
+ "os": {
+ "type": "win",
+ "version": {
+ "op": "=",
+ "number": "5"
+ }
+ },
+ "features": [
+ "accelerated_2d_canvas"
+ ]
+ },
+ {
+ "id": 68,
+ "description": "VMware Fusion 4 has corrupt rendering with Win Vista+.",
+ "cr_bugs": [169470],
+ "os": {
+ "type": "win",
+ "version": {
+ "op": ">=",
+ "number": "6.0"
+ }
+ },
+ "vendor_id": "0x15ad",
+ "driver_version": {
+ "op": "<=",
+ "number": "7.14.1.1134"
+ },
+ "features": [
+ "all"
+ ]
+ },
+ {
+ "id": 69,
+ "description": "NVIDIA driver 8.17.11.9621 is buggy with Stage3D baseline mode.",
+ "cr_bugs": [172771],
+ "os": {
+ "type": "win"
+ },
+ "vendor_id": "0x10de",
+ "driver_version": {
+ "op": "=",
+ "number": "8.17.11.9621"
+ },
+ "features": [
+ "flash_stage3d_baseline"
+ ]
+ },
+ {
+ "id": 70,
+ "description": "NVIDIA driver 8.17.11.8267 is buggy with Stage3D baseline mode.",
+ "cr_bugs": [172771],
+ "os": {
+ "type": "win"
+ },
+ "vendor_id": "0x10de",
+ "driver_version": {
+ "op": "=",
+ "number": "8.17.11.8267"
+ },
+ "features": [
+ "flash_stage3d_baseline"
+ ]
+ },
+ {
+ "id": 71,
+ "description": "All Intel drivers before 8.15.10.2021 are buggy with Stage3D baseline mode.",
+ "cr_bugs": [172771],
+ "os": {
+ "type": "win"
+ },
+ "vendor_id": "0x8086",
+ "driver_version": {
+ "op": "<",
+ "number": "8.15.10.2021"
+ },
+ "features": [
+ "flash_stage3d_baseline"
+ ]
+ },
+ {
+ "id": 72,
+ "description": "NVIDIA GeForce 6200 LE is buggy with WebGL.",
+ "cr_bugs": [232529],
+ "os": {
+ "type": "win"
+ },
+ "vendor_id": "0x10de",
+ "device_id": ["0x0163"],
+ "features": [
+ "webgl"
+ ]
+ },
+ {
+ "id": 73,
+ "description": "WebGL is buggy with the NVIDIA GeForce GT 330M, 9400, and 9400M on MacOSX earlier than 10.8",
+ "cr_bugs": [233523],
+ "os": {
+ "type": "macosx",
+ "version": {
+ "op": "<",
+ "number": "10.8"
+ }
+ },
+ "vendor_id": "0x10de",
+ "device_id": ["0x0a29", "0x0861", "0x0863"],
+ "features": [
+ "webgl"
+ ]
+ }
+ ]
+}
+
+); // LONG_STRING_CONST macro
+
+} // namespace gpu
+
diff --git a/gpu/disk_cache_proto.target.darwin-arm.mk b/gpu/disk_cache_proto.target.darwin-arm.mk
index 5ade799..2f140c9 100644
--- a/gpu/disk_cache_proto.target.darwin-arm.mk
+++ b/gpu/disk_cache_proto.target.darwin-arm.mk
@@ -17,14 +17,14 @@
### Generated for rule "gpu_gpu_gyp_disk_cache_proto_target_genproto":
# "{'inputs': ['../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'msvs_cygwin_shell': '0', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['command_buffer/service/disk_cache_proto.proto'], 'action': ['python', '../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', 'command_buffer/service', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)', 'process_outputs_as_sources': '1'}":
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: $(LOCAL_PATH)/gpu/command_buffer/service/disk_cache_proto.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
mkdir -p $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service $(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service; cd $(gyp_local_path)/gpu; python ../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h" --proto-in-dir command_buffer/service --proto-in-file "disk_cache_proto$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service" --python_out "$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service"
-$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
-$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
.PHONY: gpu_disk_cache_proto_gyp_rule_trigger
gpu_disk_cache_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
@@ -94,6 +94,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -122,9 +123,9 @@
$(LOCAL_PATH) \
$(LOCAL_PATH)/third_party/protobuf \
$(LOCAL_PATH)/third_party/protobuf/src \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/disk_cache_proto.target.darwin-x86.mk b/gpu/disk_cache_proto.target.darwin-x86.mk
index d3c2c65..5117015 100644
--- a/gpu/disk_cache_proto.target.darwin-x86.mk
+++ b/gpu/disk_cache_proto.target.darwin-x86.mk
@@ -17,14 +17,14 @@
### Generated for rule "gpu_gpu_gyp_disk_cache_proto_target_genproto":
# "{'inputs': ['../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'msvs_cygwin_shell': '0', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['command_buffer/service/disk_cache_proto.proto'], 'action': ['python', '../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', 'command_buffer/service', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)', 'process_outputs_as_sources': '1'}":
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: $(LOCAL_PATH)/gpu/command_buffer/service/disk_cache_proto.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
mkdir -p $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service $(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service; cd $(gyp_local_path)/gpu; python ../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h" --proto-in-dir command_buffer/service --proto-in-file "disk_cache_proto$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service" --python_out "$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service"
-$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
-$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
.PHONY: gpu_disk_cache_proto_gyp_rule_trigger
gpu_disk_cache_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
@@ -96,6 +96,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -124,9 +125,9 @@
$(LOCAL_PATH) \
$(LOCAL_PATH)/third_party/protobuf \
$(LOCAL_PATH)/third_party/protobuf/src \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/disk_cache_proto.target.linux-arm.mk b/gpu/disk_cache_proto.target.linux-arm.mk
index 5ade799..2f140c9 100644
--- a/gpu/disk_cache_proto.target.linux-arm.mk
+++ b/gpu/disk_cache_proto.target.linux-arm.mk
@@ -17,14 +17,14 @@
### Generated for rule "gpu_gpu_gyp_disk_cache_proto_target_genproto":
# "{'inputs': ['../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'msvs_cygwin_shell': '0', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['command_buffer/service/disk_cache_proto.proto'], 'action': ['python', '../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', 'command_buffer/service', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)', 'process_outputs_as_sources': '1'}":
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: $(LOCAL_PATH)/gpu/command_buffer/service/disk_cache_proto.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
mkdir -p $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service $(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service; cd $(gyp_local_path)/gpu; python ../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h" --proto-in-dir command_buffer/service --proto-in-file "disk_cache_proto$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service" --python_out "$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service"
-$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
-$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
.PHONY: gpu_disk_cache_proto_gyp_rule_trigger
gpu_disk_cache_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
@@ -94,6 +94,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -122,9 +123,9 @@
$(LOCAL_PATH) \
$(LOCAL_PATH)/third_party/protobuf \
$(LOCAL_PATH)/third_party/protobuf/src \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/disk_cache_proto.target.linux-x86.mk b/gpu/disk_cache_proto.target.linux-x86.mk
index d3c2c65..5117015 100644
--- a/gpu/disk_cache_proto.target.linux-x86.mk
+++ b/gpu/disk_cache_proto.target.linux-x86.mk
@@ -17,14 +17,14 @@
### Generated for rule "gpu_gpu_gyp_disk_cache_proto_target_genproto":
# "{'inputs': ['../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'msvs_cygwin_shell': '0', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['command_buffer/service/disk_cache_proto.proto'], 'action': ['python', '../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', 'command_buffer/service', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)', 'process_outputs_as_sources': '1'}":
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: $(LOCAL_PATH)/gpu/command_buffer/service/disk_cache_proto.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
mkdir -p $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service $(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service; cd $(gyp_local_path)/gpu; python ../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h" --proto-in-dir command_buffer/service --proto-in-file "disk_cache_proto$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service" --python_out "$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service"
-$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
-$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
.PHONY: gpu_disk_cache_proto_gyp_rule_trigger
gpu_disk_cache_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
@@ -96,6 +96,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -124,9 +125,9 @@
$(LOCAL_PATH) \
$(LOCAL_PATH)/third_party/protobuf \
$(LOCAL_PATH)/third_party/protobuf/src \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_c_lib.target.darwin-arm.mk b/gpu/gles2_c_lib.target.darwin-arm.mk
index 321caba..627066b 100644
--- a/gpu/gles2_c_lib.target.darwin-arm.mk
+++ b/gpu/gles2_c_lib.target.darwin-arm.mk
@@ -68,6 +68,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -96,9 +97,9 @@
$(LOCAL_PATH) \
$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_c_lib.target.darwin-x86.mk b/gpu/gles2_c_lib.target.darwin-x86.mk
index 991a04f..a3dfb83 100644
--- a/gpu/gles2_c_lib.target.darwin-x86.mk
+++ b/gpu/gles2_c_lib.target.darwin-x86.mk
@@ -70,6 +70,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -98,9 +99,9 @@
$(LOCAL_PATH) \
$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_c_lib.target.linux-arm.mk b/gpu/gles2_c_lib.target.linux-arm.mk
index 321caba..627066b 100644
--- a/gpu/gles2_c_lib.target.linux-arm.mk
+++ b/gpu/gles2_c_lib.target.linux-arm.mk
@@ -68,6 +68,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -96,9 +97,9 @@
$(LOCAL_PATH) \
$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_c_lib.target.linux-x86.mk b/gpu/gles2_c_lib.target.linux-x86.mk
index 991a04f..a3dfb83 100644
--- a/gpu/gles2_c_lib.target.linux-x86.mk
+++ b/gpu/gles2_c_lib.target.linux-x86.mk
@@ -70,6 +70,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -98,9 +99,9 @@
$(LOCAL_PATH) \
$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_cmd_helper.target.darwin-arm.mk b/gpu/gles2_cmd_helper.target.darwin-arm.mk
index 166f09a..601bccf 100644
--- a/gpu/gles2_cmd_helper.target.darwin-arm.mk
+++ b/gpu/gles2_cmd_helper.target.darwin-arm.mk
@@ -67,6 +67,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -92,9 +93,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_cmd_helper.target.darwin-x86.mk b/gpu/gles2_cmd_helper.target.darwin-x86.mk
index ebddb4e..b8d6197 100644
--- a/gpu/gles2_cmd_helper.target.darwin-x86.mk
+++ b/gpu/gles2_cmd_helper.target.darwin-x86.mk
@@ -69,6 +69,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -94,9 +95,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_cmd_helper.target.linux-arm.mk b/gpu/gles2_cmd_helper.target.linux-arm.mk
index 166f09a..601bccf 100644
--- a/gpu/gles2_cmd_helper.target.linux-arm.mk
+++ b/gpu/gles2_cmd_helper.target.linux-arm.mk
@@ -67,6 +67,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -92,9 +93,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_cmd_helper.target.linux-x86.mk b/gpu/gles2_cmd_helper.target.linux-x86.mk
index ebddb4e..b8d6197 100644
--- a/gpu/gles2_cmd_helper.target.linux-x86.mk
+++ b/gpu/gles2_cmd_helper.target.linux-x86.mk
@@ -69,6 +69,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -94,9 +95,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc
index 1d3fea6..6eb6eab 100644
--- a/gpu/gles2_conform_support/egl/display.cc
+++ b/gpu/gles2_conform_support/egl/display.cc
@@ -230,7 +230,8 @@
NULL,
transfer_buffer_.get(),
share_resources,
- true));
+ true,
+ NULL));
if (!context_->Initialize(
kTransferBufferSize,
diff --git a/gpu/gles2_conform_support/gles2_conform_support.gyp b/gpu/gles2_conform_support/gles2_conform_support.gyp
index 94ebebf..7e62d32 100644
--- a/gpu/gles2_conform_support/gles2_conform_support.gyp
+++ b/gpu/gles2_conform_support/gles2_conform_support.gyp
@@ -114,6 +114,12 @@
['toolkit_uses_gtk == 1', {
'dependencies': ['../../build/linux/system.gyp:gtk'],
}],
+ # See http://crbug.com/162998#c4 for why this is needed.
+ ['OS=="linux" and linux_use_tcmalloc==1', {
+ 'dependencies': [
+ '../../base/allocator/allocator.gyp:allocator',
+ ],
+ }],
],
'defines': [
'GLES2_CONFORM_SUPPORT_ONLY',
diff --git a/gpu/gles2_implementation.target.darwin-arm.mk b/gpu/gles2_implementation.target.darwin-arm.mk
index 021ebe8..ba0618d 100644
--- a/gpu/gles2_implementation.target.darwin-arm.mk
+++ b/gpu/gles2_implementation.target.darwin-arm.mk
@@ -30,7 +30,7 @@
gpu/command_buffer/client/gles2_implementation.cc \
gpu/command_buffer/client/gles2_interface.cc \
gpu/command_buffer/client/gles2_trace_implementation.cc \
- gpu/command_buffer/client/gpu_memory_buffer_factory.cc \
+ gpu/command_buffer/client/gpu_memory_buffer_tracker.cc \
gpu/command_buffer/client/program_info_manager.cc \
gpu/command_buffer/client/query_tracker.cc \
gpu/command_buffer/client/share_group.cc \
@@ -78,6 +78,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -108,9 +109,9 @@
$(LOCAL_PATH) \
$(gyp_shared_intermediate_dir)/ui/gl \
$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_implementation.target.darwin-x86.mk b/gpu/gles2_implementation.target.darwin-x86.mk
index 60a47ef..1d60e5b 100644
--- a/gpu/gles2_implementation.target.darwin-x86.mk
+++ b/gpu/gles2_implementation.target.darwin-x86.mk
@@ -30,7 +30,7 @@
gpu/command_buffer/client/gles2_implementation.cc \
gpu/command_buffer/client/gles2_interface.cc \
gpu/command_buffer/client/gles2_trace_implementation.cc \
- gpu/command_buffer/client/gpu_memory_buffer_factory.cc \
+ gpu/command_buffer/client/gpu_memory_buffer_tracker.cc \
gpu/command_buffer/client/program_info_manager.cc \
gpu/command_buffer/client/query_tracker.cc \
gpu/command_buffer/client/share_group.cc \
@@ -80,6 +80,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -110,9 +111,9 @@
$(LOCAL_PATH) \
$(gyp_shared_intermediate_dir)/ui/gl \
$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_implementation.target.linux-arm.mk b/gpu/gles2_implementation.target.linux-arm.mk
index 021ebe8..ba0618d 100644
--- a/gpu/gles2_implementation.target.linux-arm.mk
+++ b/gpu/gles2_implementation.target.linux-arm.mk
@@ -30,7 +30,7 @@
gpu/command_buffer/client/gles2_implementation.cc \
gpu/command_buffer/client/gles2_interface.cc \
gpu/command_buffer/client/gles2_trace_implementation.cc \
- gpu/command_buffer/client/gpu_memory_buffer_factory.cc \
+ gpu/command_buffer/client/gpu_memory_buffer_tracker.cc \
gpu/command_buffer/client/program_info_manager.cc \
gpu/command_buffer/client/query_tracker.cc \
gpu/command_buffer/client/share_group.cc \
@@ -78,6 +78,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -108,9 +109,9 @@
$(LOCAL_PATH) \
$(gyp_shared_intermediate_dir)/ui/gl \
$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gles2_implementation.target.linux-x86.mk b/gpu/gles2_implementation.target.linux-x86.mk
index 60a47ef..1d60e5b 100644
--- a/gpu/gles2_implementation.target.linux-x86.mk
+++ b/gpu/gles2_implementation.target.linux-x86.mk
@@ -30,7 +30,7 @@
gpu/command_buffer/client/gles2_implementation.cc \
gpu/command_buffer/client/gles2_interface.cc \
gpu/command_buffer/client/gles2_trace_implementation.cc \
- gpu/command_buffer/client/gpu_memory_buffer_factory.cc \
+ gpu/command_buffer/client/gpu_memory_buffer_tracker.cc \
gpu/command_buffer/client/program_info_manager.cc \
gpu/command_buffer/client/query_tracker.cc \
gpu/command_buffer/client/share_group.cc \
@@ -80,6 +80,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -110,9 +111,9 @@
$(LOCAL_PATH) \
$(gyp_shared_intermediate_dir)/ui/gl \
$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 0492532..9c72995 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -206,6 +206,21 @@
'command_buffer/service/transfer_buffer_manager_unittest.cc',
'command_buffer/service/vertex_attrib_manager_unittest.cc',
'command_buffer/service/vertex_array_manager_unittest.cc',
+ 'config/gpu_blacklist_unittest.cc',
+ 'config/gpu_control_list_entry_unittest.cc',
+ 'config/gpu_control_list_machine_model_info_unittest.cc',
+ 'config/gpu_control_list_number_info_unittest.cc',
+ 'config/gpu_control_list_os_info_unittest.cc',
+ 'config/gpu_control_list_string_info_unittest.cc',
+ 'config/gpu_control_list_unittest.cc',
+ 'config/gpu_control_list_version_info_unittest.cc',
+ 'config/gpu_driver_bug_list_unittest.cc',
+ 'config/gpu_info_collector_unittest.cc',
+ 'config/gpu_info_unittest.cc',
+ 'config/gpu_switching_list_unittest.cc',
+ 'config/gpu_test_config_unittest.cc',
+ 'config/gpu_test_expectations_parser_unittest.cc',
+ 'config/gpu_util_unittest.cc',
],
'conditions': [
['OS == "android" and gtest_target_type == "shared_library"', {
@@ -243,10 +258,15 @@
],
'sources': [
'<@(gles2_c_lib_source_files)',
+ 'command_buffer/client/gpu_memory_buffer_mock.cc',
+ 'command_buffer/client/gpu_memory_buffer_mock.h',
+ 'command_buffer/client/image_factory_mock.cc',
+ 'command_buffer/client/image_factory_mock.h',
'command_buffer/tests/gl_bind_uniform_location_unittest.cc',
'command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc',
'command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc',
'command_buffer/tests/gl_depth_texture_unittest.cc',
+ 'command_buffer/tests/gl_gpu_memory_buffer_unittests.cc',
'command_buffer/tests/gl_lose_context_chromium_unittests.cc',
'command_buffer/tests/gl_manager.cc',
'command_buffer/tests/gl_manager.h',
@@ -315,6 +335,7 @@
'command_buffer_common',
'command_buffer_service',
'gles2_cmd_helper',
+ 'gpu_config',
'gpu_ipc',
],
'sources': [
@@ -385,6 +406,13 @@
'command_buffer_common',
],
},
+ {
+ 'target_name': 'gpu_config',
+ 'type': 'static_library',
+ 'includes': [
+ 'gpu_config.gypi',
+ ],
+ },
],
},
{ # component != static_library
@@ -407,6 +435,7 @@
'command_buffer_common.gypi',
'command_buffer_service.gypi',
'gles2_cmd_helper.gypi',
+ 'gpu_config.gypi',
'gpu_ipc.gypi',
],
'defines': [
diff --git a/gpu/gpu.target.darwin-arm.mk b/gpu/gpu.target.darwin-arm.mk
index ab5146c..34be7e1 100644
--- a/gpu/gpu.target.darwin-arm.mk
+++ b/gpu/gpu.target.darwin-arm.mk
@@ -16,6 +16,7 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_common_gyp)/gpu_command_buffer_common_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_service_gyp)/gpu_command_buffer_service_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_cmd_helper_gyp)/gpu_gles2_cmd_helper_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_config_gyp)/gpu_gpu_config_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_ipc_gyp)/gpu_gpu_ipc_gyp.a
GYP_GENERATED_OUTPUTS :=
@@ -71,6 +72,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -98,9 +100,9 @@
$(LOCAL_PATH)/gpu \
$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gpu.target.darwin-x86.mk b/gpu/gpu.target.darwin-x86.mk
index 548d95c..e6fa243 100644
--- a/gpu/gpu.target.darwin-x86.mk
+++ b/gpu/gpu.target.darwin-x86.mk
@@ -16,6 +16,7 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_common_gyp)/gpu_command_buffer_common_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_service_gyp)/gpu_command_buffer_service_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_cmd_helper_gyp)/gpu_gles2_cmd_helper_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_config_gyp)/gpu_gpu_config_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_ipc_gyp)/gpu_gpu_ipc_gyp.a
GYP_GENERATED_OUTPUTS :=
@@ -73,6 +74,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -100,9 +102,9 @@
$(LOCAL_PATH)/gpu \
$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gpu.target.linux-arm.mk b/gpu/gpu.target.linux-arm.mk
index ab5146c..34be7e1 100644
--- a/gpu/gpu.target.linux-arm.mk
+++ b/gpu/gpu.target.linux-arm.mk
@@ -16,6 +16,7 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_common_gyp)/gpu_command_buffer_common_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_service_gyp)/gpu_command_buffer_service_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_cmd_helper_gyp)/gpu_gles2_cmd_helper_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_config_gyp)/gpu_gpu_config_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_ipc_gyp)/gpu_gpu_ipc_gyp.a
GYP_GENERATED_OUTPUTS :=
@@ -71,6 +72,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -98,9 +100,9 @@
$(LOCAL_PATH)/gpu \
$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gpu.target.linux-x86.mk b/gpu/gpu.target.linux-x86.mk
index 548d95c..e6fa243 100644
--- a/gpu/gpu.target.linux-x86.mk
+++ b/gpu/gpu.target.linux-x86.mk
@@ -16,6 +16,7 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_common_gyp)/gpu_command_buffer_common_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_service_gyp)/gpu_command_buffer_service_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_cmd_helper_gyp)/gpu_gles2_cmd_helper_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_config_gyp)/gpu_gpu_config_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_ipc_gyp)/gpu_gpu_ipc_gyp.a
GYP_GENERATED_OUTPUTS :=
@@ -73,6 +74,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -100,9 +102,9 @@
$(LOCAL_PATH)/gpu \
$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gpu_common.gypi b/gpu/gpu_common.gypi
index 432457b..14b4921 100644
--- a/gpu/gpu_common.gypi
+++ b/gpu/gpu_common.gypi
@@ -37,8 +37,9 @@
'command_buffer/client/gles2_trace_implementation.h',
'command_buffer/client/gles2_trace_implementation_impl_autogen.h',
'command_buffer/client/gpu_memory_buffer.h',
- 'command_buffer/client/gpu_memory_buffer_factory.cc',
- 'command_buffer/client/gpu_memory_buffer_factory.h',
+ 'command_buffer/client/gpu_memory_buffer_tracker.h',
+ 'command_buffer/client/gpu_memory_buffer_tracker.cc',
+ 'command_buffer/client/image_factory.h',
'command_buffer/client/program_info_manager.cc',
'command_buffer/client/program_info_manager.h',
'command_buffer/client/query_tracker.cc',
diff --git a/gpu/gpu_config.gypi b/gpu/gpu_config.gypi
new file mode 100644
index 0000000..c95605b
--- /dev/null
+++ b/gpu/gpu_config.gypi
@@ -0,0 +1,77 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../third_party/re2/re2.gyp:re2',
+ '../ui/gl/gl.gyp:gl',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'config/dx_diag_node.cc',
+ 'config/dx_diag_node.h',
+ 'config/gpu_blacklist.cc',
+ 'config/gpu_blacklist.h',
+ 'config/gpu_control_list_jsons.h',
+ 'config/gpu_control_list.cc',
+ 'config/gpu_control_list.h',
+ 'config/gpu_driver_bug_list_json.cc',
+ 'config/gpu_driver_bug_list.cc',
+ 'config/gpu_driver_bug_list.h',
+ 'config/gpu_driver_bug_workaround_type.h',
+ 'config/gpu_dx_diagnostics_win.cc',
+ 'config/gpu_feature_type.h',
+ 'config/gpu_info.cc',
+ 'config/gpu_info.h',
+ 'config/gpu_info_collector_android.cc',
+ 'config/gpu_info_collector_mac.mm',
+ 'config/gpu_info_collector_ozone.cc',
+ 'config/gpu_info_collector_win.cc',
+ 'config/gpu_info_collector_x11.cc',
+ 'config/gpu_info_collector.cc',
+ 'config/gpu_info_collector.h',
+ 'config/gpu_performance_stats.h',
+ 'config/gpu_switching_list_json.cc',
+ 'config/gpu_switching_list.cc',
+ 'config/gpu_switching_list.h',
+ 'config/gpu_switching_option.h',
+ 'config/gpu_test_config.cc',
+ 'config/gpu_test_config.h',
+ 'config/gpu_test_expectations_parser.cc',
+ 'config/gpu_test_expectations_parser.h',
+ 'config/gpu_util.cc',
+ 'config/gpu_util.h',
+ 'config/software_rendering_list_json.cc',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'dependencies': [
+ '../third_party/libxml/libxml.gyp:libxml',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '-ldxguid.lib',
+ '-lsetupapi.lib',
+ ],
+ },
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ }],
+ ['OS=="win" and branding=="Chrome"', {
+ 'sources': [
+ '../third_party/amd/AmdCfxPxExt.h',
+ '../third_party/amd/amd_videocard_info_win.cc',
+ ],
+ }],
+ ['OS=="linux" and use_x11==1', {
+ 'dependencies': [
+ '../build/linux/system.gyp:libpci',
+ '../third_party/libXNVCtrl/libXNVCtrl.gyp:libXNVCtrl',
+ ],
+ }],
+ ],
+}
diff --git a/gpu/gpu_config.target.darwin-arm.mk b/gpu/gpu_config.target.darwin-arm.mk
new file mode 100644
index 0000000..9208820
--- /dev/null
+++ b/gpu/gpu_config.target.darwin-arm.mk
@@ -0,0 +1,169 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gpu_config_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+ gpu/config/dx_diag_node.cc \
+ gpu/config/gpu_blacklist.cc \
+ gpu/config/gpu_control_list.cc \
+ gpu/config/gpu_driver_bug_list_json.cc \
+ gpu/config/gpu_driver_bug_list.cc \
+ gpu/config/gpu_info.cc \
+ gpu/config/gpu_info_collector_android.cc \
+ gpu/config/gpu_info_collector.cc \
+ gpu/config/gpu_switching_list_json.cc \
+ gpu/config/gpu_switching_list.cc \
+ gpu/config/gpu_test_config.cc \
+ gpu/config/gpu_test_expectations_parser.cc \
+ gpu/config/gpu_util.cc \
+ gpu/config/software_rendering_list_json.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+ -fstack-protector \
+ --param=ssp-buffer-size=4 \
+ -Werror \
+ -fno-exceptions \
+ -fno-strict-aliasing \
+ -Wall \
+ -Wno-unused-parameter \
+ -Wno-missing-field-initializers \
+ -fvisibility=hidden \
+ -pipe \
+ -fPIC \
+ -fno-tree-sra \
+ -fuse-ld=gold \
+ -Wno-psabi \
+ -ffunction-sections \
+ -funwind-tables \
+ -g \
+ -fstack-protector \
+ -fno-short-enums \
+ -finline-limit=64 \
+ -Wa,--noexecstack \
+ -U_FORTIFY_SOURCE \
+ -Wno-extra \
+ -Wno-ignored-qualifiers \
+ -Wno-type-limits \
+ -Os \
+ -g \
+ -fomit-frame-pointer \
+ -fdata-sections \
+ -ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-DUSE_LINUX_BREAKPAD' \
+ '-DNO_TCMALLOC' \
+ '-DDISABLE_NACL' \
+ '-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
+ '-DUSE_LIBJPEG_TURBO=1' \
+ '-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_GPU=1' \
+ '-DUSE_OPENSSL=1' \
+ '-DENABLE_EGLIMAGE=1' \
+ '-DENABLE_LANGUAGE_DETECTION=1' \
+ '-D__STDC_CONSTANT_MACROS' \
+ '-D__STDC_FORMAT_MACROS' \
+ '-DANDROID' \
+ '-D__GNU_SOURCE=1' \
+ '-DUSE_STLPORT=1' \
+ '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+ '-DCHROME_BUILD_ID=""' \
+ '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+ '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+ '-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH) \
+ $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(LOCAL_PATH)/third_party/khronos \
+ $(LOCAL_PATH)/gpu \
+ $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+ $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+ $(LOCAL_PATH)/third_party/re2 \
+ $(gyp_shared_intermediate_dir)/ui/gl \
+ $(LOCAL_PATH)/third_party/mesa/MesaLib/include \
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+ -fno-rtti \
+ -fno-threadsafe-statics \
+ -fvisibility-inlines-hidden \
+ -Wsign-compare \
+ -Wno-abi \
+ -Wno-error=c++0x-compat \
+ -Wno-non-virtual-dtor \
+ -Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+ -Wl,-z,now \
+ -Wl,-z,relro \
+ -Wl,-z,noexecstack \
+ -fPIC \
+ -Wl,-z,relro \
+ -Wl,-z,now \
+ -fuse-ld=gold \
+ -nostdlib \
+ -Wl,--no-undefined \
+ -Wl,--exclude-libs=ALL \
+ -Wl,--icf=safe \
+ -Wl,--gc-sections \
+ -Wl,-O1 \
+ -Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+ ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+ libstlport \
+ libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gpu_config_gyp
+
+# Alias gyp target name.
+.PHONY: gpu_config
+gpu_config: gpu_gpu_config_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gpu_config.target.darwin-x86.mk b/gpu/gpu_config.target.darwin-x86.mk
new file mode 100644
index 0000000..1e7efb8
--- /dev/null
+++ b/gpu/gpu_config.target.darwin-x86.mk
@@ -0,0 +1,168 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gpu_config_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+ gpu/config/dx_diag_node.cc \
+ gpu/config/gpu_blacklist.cc \
+ gpu/config/gpu_control_list.cc \
+ gpu/config/gpu_driver_bug_list_json.cc \
+ gpu/config/gpu_driver_bug_list.cc \
+ gpu/config/gpu_info.cc \
+ gpu/config/gpu_info_collector_android.cc \
+ gpu/config/gpu_info_collector.cc \
+ gpu/config/gpu_switching_list_json.cc \
+ gpu/config/gpu_switching_list.cc \
+ gpu/config/gpu_test_config.cc \
+ gpu/config/gpu_test_expectations_parser.cc \
+ gpu/config/gpu_util.cc \
+ gpu/config/software_rendering_list_json.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+ --param=ssp-buffer-size=4 \
+ -Werror \
+ -fno-exceptions \
+ -fno-strict-aliasing \
+ -Wall \
+ -Wno-unused-parameter \
+ -Wno-missing-field-initializers \
+ -fvisibility=hidden \
+ -pipe \
+ -fPIC \
+ -m32 \
+ -mmmx \
+ -march=pentium4 \
+ -msse2 \
+ -mfpmath=sse \
+ -fuse-ld=gold \
+ -ffunction-sections \
+ -funwind-tables \
+ -g \
+ -fno-short-enums \
+ -finline-limit=64 \
+ -Wa,--noexecstack \
+ -U_FORTIFY_SOURCE \
+ -Wno-extra \
+ -Wno-ignored-qualifiers \
+ -Wno-type-limits \
+ -fno-stack-protector \
+ -Os \
+ -g \
+ -fomit-frame-pointer \
+ -fdata-sections \
+ -ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-DUSE_LINUX_BREAKPAD' \
+ '-DNO_TCMALLOC' \
+ '-DDISABLE_NACL' \
+ '-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
+ '-DUSE_LIBJPEG_TURBO=1' \
+ '-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_GPU=1' \
+ '-DUSE_OPENSSL=1' \
+ '-DENABLE_EGLIMAGE=1' \
+ '-DENABLE_LANGUAGE_DETECTION=1' \
+ '-D__STDC_CONSTANT_MACROS' \
+ '-D__STDC_FORMAT_MACROS' \
+ '-DANDROID' \
+ '-D__GNU_SOURCE=1' \
+ '-DUSE_STLPORT=1' \
+ '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+ '-DCHROME_BUILD_ID=""' \
+ '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+ '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+ '-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH) \
+ $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(LOCAL_PATH)/third_party/khronos \
+ $(LOCAL_PATH)/gpu \
+ $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+ $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+ $(LOCAL_PATH)/third_party/re2 \
+ $(gyp_shared_intermediate_dir)/ui/gl \
+ $(LOCAL_PATH)/third_party/mesa/MesaLib/include \
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+ -fno-rtti \
+ -fno-threadsafe-statics \
+ -fvisibility-inlines-hidden \
+ -Wsign-compare \
+ -Wno-error=c++0x-compat \
+ -Wno-non-virtual-dtor \
+ -Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+ -Wl,-z,now \
+ -Wl,-z,relro \
+ -Wl,-z,noexecstack \
+ -fPIC \
+ -m32 \
+ -fuse-ld=gold \
+ -nostdlib \
+ -Wl,--no-undefined \
+ -Wl,--exclude-libs=ALL \
+ -Wl,--gc-sections \
+ -Wl,-O1 \
+ -Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+ ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+ libstlport \
+ libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gpu_config_gyp
+
+# Alias gyp target name.
+.PHONY: gpu_config
+gpu_config: gpu_gpu_config_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gpu_config.target.linux-arm.mk b/gpu/gpu_config.target.linux-arm.mk
new file mode 100644
index 0000000..9208820
--- /dev/null
+++ b/gpu/gpu_config.target.linux-arm.mk
@@ -0,0 +1,169 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gpu_config_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+ gpu/config/dx_diag_node.cc \
+ gpu/config/gpu_blacklist.cc \
+ gpu/config/gpu_control_list.cc \
+ gpu/config/gpu_driver_bug_list_json.cc \
+ gpu/config/gpu_driver_bug_list.cc \
+ gpu/config/gpu_info.cc \
+ gpu/config/gpu_info_collector_android.cc \
+ gpu/config/gpu_info_collector.cc \
+ gpu/config/gpu_switching_list_json.cc \
+ gpu/config/gpu_switching_list.cc \
+ gpu/config/gpu_test_config.cc \
+ gpu/config/gpu_test_expectations_parser.cc \
+ gpu/config/gpu_util.cc \
+ gpu/config/software_rendering_list_json.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+ -fstack-protector \
+ --param=ssp-buffer-size=4 \
+ -Werror \
+ -fno-exceptions \
+ -fno-strict-aliasing \
+ -Wall \
+ -Wno-unused-parameter \
+ -Wno-missing-field-initializers \
+ -fvisibility=hidden \
+ -pipe \
+ -fPIC \
+ -fno-tree-sra \
+ -fuse-ld=gold \
+ -Wno-psabi \
+ -ffunction-sections \
+ -funwind-tables \
+ -g \
+ -fstack-protector \
+ -fno-short-enums \
+ -finline-limit=64 \
+ -Wa,--noexecstack \
+ -U_FORTIFY_SOURCE \
+ -Wno-extra \
+ -Wno-ignored-qualifiers \
+ -Wno-type-limits \
+ -Os \
+ -g \
+ -fomit-frame-pointer \
+ -fdata-sections \
+ -ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-DUSE_LINUX_BREAKPAD' \
+ '-DNO_TCMALLOC' \
+ '-DDISABLE_NACL' \
+ '-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
+ '-DUSE_LIBJPEG_TURBO=1' \
+ '-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_GPU=1' \
+ '-DUSE_OPENSSL=1' \
+ '-DENABLE_EGLIMAGE=1' \
+ '-DENABLE_LANGUAGE_DETECTION=1' \
+ '-D__STDC_CONSTANT_MACROS' \
+ '-D__STDC_FORMAT_MACROS' \
+ '-DANDROID' \
+ '-D__GNU_SOURCE=1' \
+ '-DUSE_STLPORT=1' \
+ '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+ '-DCHROME_BUILD_ID=""' \
+ '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+ '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+ '-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH) \
+ $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(LOCAL_PATH)/third_party/khronos \
+ $(LOCAL_PATH)/gpu \
+ $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+ $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+ $(LOCAL_PATH)/third_party/re2 \
+ $(gyp_shared_intermediate_dir)/ui/gl \
+ $(LOCAL_PATH)/third_party/mesa/MesaLib/include \
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+ -fno-rtti \
+ -fno-threadsafe-statics \
+ -fvisibility-inlines-hidden \
+ -Wsign-compare \
+ -Wno-abi \
+ -Wno-error=c++0x-compat \
+ -Wno-non-virtual-dtor \
+ -Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+ -Wl,-z,now \
+ -Wl,-z,relro \
+ -Wl,-z,noexecstack \
+ -fPIC \
+ -Wl,-z,relro \
+ -Wl,-z,now \
+ -fuse-ld=gold \
+ -nostdlib \
+ -Wl,--no-undefined \
+ -Wl,--exclude-libs=ALL \
+ -Wl,--icf=safe \
+ -Wl,--gc-sections \
+ -Wl,-O1 \
+ -Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+ ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+ libstlport \
+ libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gpu_config_gyp
+
+# Alias gyp target name.
+.PHONY: gpu_config
+gpu_config: gpu_gpu_config_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gpu_config.target.linux-x86.mk b/gpu/gpu_config.target.linux-x86.mk
new file mode 100644
index 0000000..1e7efb8
--- /dev/null
+++ b/gpu/gpu_config.target.linux-x86.mk
@@ -0,0 +1,168 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gpu_config_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+ gpu/config/dx_diag_node.cc \
+ gpu/config/gpu_blacklist.cc \
+ gpu/config/gpu_control_list.cc \
+ gpu/config/gpu_driver_bug_list_json.cc \
+ gpu/config/gpu_driver_bug_list.cc \
+ gpu/config/gpu_info.cc \
+ gpu/config/gpu_info_collector_android.cc \
+ gpu/config/gpu_info_collector.cc \
+ gpu/config/gpu_switching_list_json.cc \
+ gpu/config/gpu_switching_list.cc \
+ gpu/config/gpu_test_config.cc \
+ gpu/config/gpu_test_expectations_parser.cc \
+ gpu/config/gpu_util.cc \
+ gpu/config/software_rendering_list_json.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+ --param=ssp-buffer-size=4 \
+ -Werror \
+ -fno-exceptions \
+ -fno-strict-aliasing \
+ -Wall \
+ -Wno-unused-parameter \
+ -Wno-missing-field-initializers \
+ -fvisibility=hidden \
+ -pipe \
+ -fPIC \
+ -m32 \
+ -mmmx \
+ -march=pentium4 \
+ -msse2 \
+ -mfpmath=sse \
+ -fuse-ld=gold \
+ -ffunction-sections \
+ -funwind-tables \
+ -g \
+ -fno-short-enums \
+ -finline-limit=64 \
+ -Wa,--noexecstack \
+ -U_FORTIFY_SOURCE \
+ -Wno-extra \
+ -Wno-ignored-qualifiers \
+ -Wno-type-limits \
+ -fno-stack-protector \
+ -Os \
+ -g \
+ -fomit-frame-pointer \
+ -fdata-sections \
+ -ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-DUSE_LINUX_BREAKPAD' \
+ '-DNO_TCMALLOC' \
+ '-DDISABLE_NACL' \
+ '-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
+ '-DUSE_LIBJPEG_TURBO=1' \
+ '-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_GPU=1' \
+ '-DUSE_OPENSSL=1' \
+ '-DENABLE_EGLIMAGE=1' \
+ '-DENABLE_LANGUAGE_DETECTION=1' \
+ '-D__STDC_CONSTANT_MACROS' \
+ '-D__STDC_FORMAT_MACROS' \
+ '-DANDROID' \
+ '-D__GNU_SOURCE=1' \
+ '-DUSE_STLPORT=1' \
+ '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+ '-DCHROME_BUILD_ID=""' \
+ '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+ '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+ '-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH) \
+ $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(LOCAL_PATH)/third_party/khronos \
+ $(LOCAL_PATH)/gpu \
+ $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+ $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+ $(LOCAL_PATH)/third_party/re2 \
+ $(gyp_shared_intermediate_dir)/ui/gl \
+ $(LOCAL_PATH)/third_party/mesa/MesaLib/include \
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+ -fno-rtti \
+ -fno-threadsafe-statics \
+ -fvisibility-inlines-hidden \
+ -Wsign-compare \
+ -Wno-error=c++0x-compat \
+ -Wno-non-virtual-dtor \
+ -Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+ -Wl,-z,now \
+ -Wl,-z,relro \
+ -Wl,-z,noexecstack \
+ -fPIC \
+ -m32 \
+ -fuse-ld=gold \
+ -nostdlib \
+ -Wl,--no-undefined \
+ -Wl,--exclude-libs=ALL \
+ -Wl,--gc-sections \
+ -Wl,-O1 \
+ -Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+ ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+ libstlport \
+ libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gpu_config_gyp
+
+# Alias gyp target name.
+.PHONY: gpu_config
+gpu_config: gpu_gpu_config_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gpu_ipc.target.darwin-arm.mk b/gpu/gpu_ipc.target.darwin-arm.mk
index 61e5ca7..13214e8 100644
--- a/gpu/gpu_ipc.target.darwin-arm.mk
+++ b/gpu/gpu_ipc.target.darwin-arm.mk
@@ -69,6 +69,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -94,9 +95,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gpu_ipc.target.darwin-x86.mk b/gpu/gpu_ipc.target.darwin-x86.mk
index 58909c8..836b642 100644
--- a/gpu/gpu_ipc.target.darwin-x86.mk
+++ b/gpu/gpu_ipc.target.darwin-x86.mk
@@ -71,6 +71,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -96,9 +97,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gpu_ipc.target.linux-arm.mk b/gpu/gpu_ipc.target.linux-arm.mk
index 61e5ca7..13214e8 100644
--- a/gpu/gpu_ipc.target.linux-arm.mk
+++ b/gpu/gpu_ipc.target.linux-arm.mk
@@ -69,6 +69,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -94,9 +95,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
diff --git a/gpu/gpu_ipc.target.linux-x86.mk b/gpu/gpu_ipc.target.linux-x86.mk
index 58909c8..836b642 100644
--- a/gpu/gpu_ipc.target.linux-x86.mk
+++ b/gpu/gpu_ipc.target.linux-x86.mk
@@ -71,6 +71,7 @@
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
'-DCHROMIUM_BUILD' \
+ '-DENABLE_DOUBLE_RESOURCE_LOAD_TIMING' \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_GPU=1' \
@@ -96,9 +97,9 @@
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
$(LOCAL_PATH)/third_party/khronos \
$(LOCAL_PATH)/gpu \
- $(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
- $(GYP_ABS_ANDROID_TOP_DIR)/bionic \
- $(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+ $(PWD)/frameworks/wilhelm/include \
+ $(PWD)/bionic \
+ $(PWD)/external/stlport/stlport
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)