summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraelias <aelias@chromium.org>2014-08-25 17:46:20 -0700
committerCommit bot <commit-bot@chromium.org>2014-08-26 00:47:56 +0000
commitd880a3deca8ab1c6c75ef915faa22ab7d40f55ff (patch)
treef388e316830f6fa69fdc138ba6cf66c62e369646
parent9ecb800c3c129578ce352596250f9ca3ab8ad667 (diff)
downloadchromium_src-d880a3deca8ab1c6c75ef915faa22ab7d40f55ff.zip
chromium_src-d880a3deca8ab1c6c75ef915faa22ab7d40f55ff.tar.gz
chromium_src-d880a3deca8ab1c6c75ef915faa22ab7d40f55ff.tar.bz2
Restrict ETC1 power-of-two rounding to old IMG drivers.
The ETC1 spec says that any multiple of 4 is allowed for ETC1 size, but certain old IMG devices (notably the Galaxy Nexus) crash unless the textures are specifically power-of-two. To avoid wasting RAM on all devices due to this device-specific problem, this patch plumbs a driver workaround flag to the thumbnail store (the only user of ETC1 at present). We considered adding a workaround to the service side like all of the others, but because texture size impacts memory budgeting and coordinates, this one seems like it needs to be in the client code. NOTRY=true BUG=150500 Review URL: https://codereview.chromium.org/470233003 Cr-Commit-Position: refs/heads/master@{#291814}
-rw-r--r--chrome/browser/android/thumbnail/thumbnail_store.cc33
-rw-r--r--chrome/browser/android/thumbnail/thumbnail_store.h1
-rw-r--r--content/browser/android/system_ui_resource_manager_impl_unittest.cc2
-rw-r--r--content/browser/android/ui_resource_provider_impl.cc8
-rw-r--r--content/browser/android/ui_resource_provider_impl.h6
-rw-r--r--content/browser/renderer_host/compositor_impl_android.cc32
-rw-r--r--content/browser/renderer_host/compositor_impl_android.h4
-rw-r--r--content/common/gpu/gpu_messages.h1
-rw-r--r--content/public/browser/android/ui_resource_provider.h2
-rw-r--r--gpu/command_buffer/common/capabilities.cc1
-rw-r--r--gpu/command_buffer/common/capabilities.h1
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc2
-rw-r--r--gpu/config/gpu_driver_bug_list_json.cc15
-rw-r--r--gpu/config/gpu_driver_bug_workaround_type.h2
14 files changed, 94 insertions, 16 deletions
diff --git a/chrome/browser/android/thumbnail/thumbnail_store.cc b/chrome/browser/android/thumbnail/thumbnail_store.cc
index 52d9205..3f22a3e 100644
--- a/chrome/browser/android/thumbnail/thumbnail_store.cc
+++ b/chrome/browser/android/thumbnail/thumbnail_store.cc
@@ -38,8 +38,6 @@ const int kCurrentExtraVersion = 1;
// Indicates whether we prefer to have more free CPU memory over GPU memory.
const bool kPreferCPUMemory = true;
-// TODO(): ETC1 texture sizes should be multiples of four, but some drivers only
-// allow power-of-two ETC1 textures. Find better work around.
size_t NextPowerOfTwo(size_t x) {
--x;
x |= x >> 1;
@@ -50,10 +48,18 @@ size_t NextPowerOfTwo(size_t x) {
return x + 1;
}
-gfx::Size GetEncodedSize(const gfx::Size& bitmap_size) {
+size_t RoundUpMod4(size_t x) {
+ return (x + 3) & ~3;
+}
+
+gfx::Size GetEncodedSize(const gfx::Size& bitmap_size, bool supports_npot) {
DCHECK(!bitmap_size.IsEmpty());
- return gfx::Size(NextPowerOfTwo(bitmap_size.width()),
- NextPowerOfTwo(bitmap_size.height()));
+ if (!supports_npot)
+ return gfx::Size(NextPowerOfTwo(bitmap_size.width()),
+ NextPowerOfTwo(bitmap_size.height()));
+ else
+ return gfx::Size(RoundUpMod4(bitmap_size.width()),
+ RoundUpMod4(bitmap_size.height()));
}
template<typename T>
@@ -365,11 +371,16 @@ void ThumbnailStore::CompressThumbnailIfNecessary(
time_stamp,
scale);
- base::WorkerPool::PostTask(
- FROM_HERE,
- base::Bind(
- &ThumbnailStore::CompressionTask, bitmap, post_compression_task),
- true);
+ gfx::Size raw_data_size(bitmap.width(), bitmap.height());
+ gfx::Size encoded_size = GetEncodedSize(
+ raw_data_size, ui_resource_provider_->SupportsETC1NonPowerOfTwo());
+
+ base::WorkerPool::PostTask(FROM_HERE,
+ base::Bind(&ThumbnailStore::CompressionTask,
+ bitmap,
+ encoded_size,
+ post_compression_task),
+ true);
}
void ThumbnailStore::ReadNextThumbnail() {
@@ -539,6 +550,7 @@ void ThumbnailStore::PostWriteTask() {
void ThumbnailStore::CompressionTask(
SkBitmap raw_data,
+ gfx::Size encoded_size,
const base::Callback<void(skia::RefPtr<SkPixelRef>, const gfx::Size&)>&
post_compression_task) {
skia::RefPtr<SkPixelRef> compressed_data;
@@ -550,7 +562,6 @@ void ThumbnailStore::CompressionTask(
size_t pixel_size = 4; // Pixel size is 4 bytes for kARGB_8888_Config.
size_t stride = pixel_size * raw_data_size.width();
- gfx::Size encoded_size = GetEncodedSize(raw_data_size);
size_t encoded_bytes =
etc1_get_encoded_data_size(encoded_size.width(), encoded_size.height());
SkImageInfo info = {encoded_size.width(),
diff --git a/chrome/browser/android/thumbnail/thumbnail_store.h b/chrome/browser/android/thumbnail/thumbnail_store.h
index dbe7bae..b2e5dce 100644
--- a/chrome/browser/android/thumbnail/thumbnail_store.h
+++ b/chrome/browser/android/thumbnail/thumbnail_store.h
@@ -110,6 +110,7 @@ class ThumbnailStore : ThumbnailDelegate {
void PostWriteTask();
static void CompressionTask(
SkBitmap raw_data,
+ gfx::Size encoded_size,
const base::Callback<void(skia::RefPtr<SkPixelRef>, const gfx::Size&)>&
post_compression_task);
void PostCompressionTask(TabId tab_id,
diff --git a/content/browser/android/system_ui_resource_manager_impl_unittest.cc b/content/browser/android/system_ui_resource_manager_impl_unittest.cc
index 95a7e9b..65942b7 100644
--- a/content/browser/android/system_ui_resource_manager_impl_unittest.cc
+++ b/content/browser/android/system_ui_resource_manager_impl_unittest.cc
@@ -63,6 +63,8 @@ class MockUIResourceProvider : public content::UIResourceProvider {
ui_resource_client_map_.erase(id);
}
+ virtual bool SupportsETC1NonPowerOfTwo() const OVERRIDE { return true; }
+
void LayerTreeHostCleared() {
has_layer_tree_host_ = false;
UIResourceClientMap client_map = ui_resource_client_map_;
diff --git a/content/browser/android/ui_resource_provider_impl.cc b/content/browser/android/ui_resource_provider_impl.cc
index d26d42f..cd45d7c 100644
--- a/content/browser/android/ui_resource_provider_impl.cc
+++ b/content/browser/android/ui_resource_provider_impl.cc
@@ -11,7 +11,9 @@
namespace content {
UIResourceProviderImpl::UIResourceProviderImpl()
- : system_ui_resource_manager_(this), host_(NULL) {
+ : system_ui_resource_manager_(this), host_(NULL),
+ supports_etc1_npot_(false) {
+
}
UIResourceProviderImpl::~UIResourceProviderImpl() {
@@ -63,4 +65,8 @@ UIResourceProviderImpl::GetSystemUIResourceManager() {
return system_ui_resource_manager_;
}
+bool UIResourceProviderImpl::SupportsETC1NonPowerOfTwo() const {
+ return supports_etc1_npot_;
+}
+
} // namespace content
diff --git a/content/browser/android/ui_resource_provider_impl.h b/content/browser/android/ui_resource_provider_impl.h
index 57c9ab8..06affe8 100644
--- a/content/browser/android/ui_resource_provider_impl.h
+++ b/content/browser/android/ui_resource_provider_impl.h
@@ -34,12 +34,18 @@ class UIResourceProviderImpl : public UIResourceProvider {
ui::SystemUIResourceManager& GetSystemUIResourceManager();
+ void SetSupportsETC1NonPowerOfTwo(bool supports_etc1_npot) {
+ supports_etc1_npot_ = supports_etc1_npot;
+ }
+ virtual bool SupportsETC1NonPowerOfTwo() const OVERRIDE;
+
private:
typedef base::hash_map<cc::UIResourceId, UIResourceClientAndroid*>
UIResourceClientMap;
UIResourceClientMap ui_resource_client_map_;
SystemUIResourceManagerImpl system_ui_resource_manager_;
cc::LayerTreeHost* host_;
+ bool supports_etc1_npot_;
DISALLOW_COPY_AND_ASSIGN(UIResourceProviderImpl);
};
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 13b0735..b0c3aea 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -14,6 +14,7 @@
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
@@ -56,9 +57,12 @@ const unsigned int kMaxSwapBuffers = 2U;
class OutputSurfaceWithoutParent : public cc::OutputSurface {
public:
OutputSurfaceWithoutParent(const scoped_refptr<
- content::ContextProviderCommandBuffer>& context_provider)
+ content::ContextProviderCommandBuffer>& context_provider,
+ base::WeakPtr<content::CompositorImpl> compositor_impl)
: cc::OutputSurface(context_provider) {
capabilities_.adjust_deadline_for_parent = false;
+ compositor_impl_ = compositor_impl;
+ main_thread_ = base::MessageLoopProxy::current();
}
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE {
@@ -72,6 +76,22 @@ class OutputSurfaceWithoutParent : public cc::OutputSurface {
OutputSurface::SwapBuffers(frame);
}
+
+ virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE {
+ if (!OutputSurface::BindToClient(client))
+ return false;
+
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&content::CompositorImpl::PopulateGpuCapabilities,
+ compositor_impl_,
+ context_provider_->ContextCapabilities().gpu));
+
+ return true;
+ }
+
+ scoped_refptr<base::MessageLoopProxy> main_thread_;
+ base::WeakPtr<content::CompositorImpl> compositor_impl_;
};
class SurfaceTextureTrackerImpl : public gfx::SurfaceTextureTracker {
@@ -552,8 +572,14 @@ scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface(
return scoped_ptr<cc::OutputSurface>();
}
- return scoped_ptr<cc::OutputSurface>(
- new OutputSurfaceWithoutParent(context_provider));
+ return scoped_ptr<cc::OutputSurface>(new OutputSurfaceWithoutParent(
+ context_provider, weak_factory_.GetWeakPtr()));
+}
+
+void CompositorImpl::PopulateGpuCapabilities(
+ gpu::Capabilities gpu_capabilities) {
+ ui_resource_provider_.SetSupportsETC1NonPowerOfTwo(
+ gpu_capabilities.texture_format_etc1_npot);
}
void CompositorImpl::OnLostResources() {
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index e24d581..88f101b 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -15,7 +15,9 @@
#include "content/browser/android/ui_resource_provider_impl.h"
#include "content/browser/renderer_host/image_transport_factory_android.h"
#include "content/common/content_export.h"
+#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/public/browser/android/compositor.h"
+#include "gpu/command_buffer/common/capabilities.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/base/android/system_ui_resource_manager.h"
#include "ui/base/android/window_android_compositor.h"
@@ -54,6 +56,8 @@ class CONTENT_EXPORT CompositorImpl
// Destroy all surface textures associated with |child_process_id|.
static void DestroyAllSurfaceTextures(int child_process_id);
+ void PopulateGpuCapabilities(gpu::Capabilities gpu_capabilities);
+
private:
// Compositor implementation.
virtual void SetRootLayer(scoped_refptr<cc::Layer> root) OVERRIDE;
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h
index a91bd1f..36b50d4 100644
--- a/content/common/gpu/gpu_messages.h
+++ b/content/common/gpu/gpu_messages.h
@@ -194,6 +194,7 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities)
IPC_STRUCT_TRAITS_MEMBER(egl_image_external)
IPC_STRUCT_TRAITS_MEMBER(texture_format_bgra8888)
IPC_STRUCT_TRAITS_MEMBER(texture_format_etc1)
+ IPC_STRUCT_TRAITS_MEMBER(texture_format_etc1_npot)
IPC_STRUCT_TRAITS_MEMBER(texture_rectangle)
IPC_STRUCT_TRAITS_MEMBER(iosurface)
IPC_STRUCT_TRAITS_MEMBER(texture_usage)
diff --git a/content/public/browser/android/ui_resource_provider.h b/content/public/browser/android/ui_resource_provider.h
index 38511e1..c764d1e 100644
--- a/content/public/browser/android/ui_resource_provider.h
+++ b/content/public/browser/android/ui_resource_provider.h
@@ -20,6 +20,8 @@ class CONTENT_EXPORT UIResourceProvider {
UIResourceClientAndroid* client) = 0;
virtual void DeleteUIResource(cc::UIResourceId resource_id) = 0;
+
+ virtual bool SupportsETC1NonPowerOfTwo() const = 0;
};
} // namespace content
diff --git a/gpu/command_buffer/common/capabilities.cc b/gpu/command_buffer/common/capabilities.cc
index f286eaf..257086a 100644
--- a/gpu/command_buffer/common/capabilities.cc
+++ b/gpu/command_buffer/common/capabilities.cc
@@ -11,6 +11,7 @@ Capabilities::Capabilities()
egl_image_external(false),
texture_format_bgra8888(false),
texture_format_etc1(false),
+ texture_format_etc1_npot(false),
texture_rectangle(false),
iosurface(false),
texture_usage(false),
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h
index 9e38f5c..60f7b0d 100644
--- a/gpu/command_buffer/common/capabilities.h
+++ b/gpu/command_buffer/common/capabilities.h
@@ -14,6 +14,7 @@ struct GPU_EXPORT Capabilities {
bool egl_image_external;
bool texture_format_bgra8888;
bool texture_format_etc1;
+ bool texture_format_etc1_npot;
bool texture_rectangle;
bool iosurface;
bool texture_usage;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index a71a5a6..b46c252 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -2711,6 +2711,8 @@ Capabilities GLES2DecoderImpl::GetCapabilities() {
feature_info_->feature_flags().ext_texture_format_bgra8888;
caps.texture_format_etc1 =
feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
+ caps.texture_format_etc1_npot =
+ caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index 1317f9f..2e55cc0 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST(
{
"name": "gpu driver bug list",
// Please update the version number whenever you change this file.
- "version": "7.2",
+ "version": "7.3",
"entries": [
{
"id": 1,
@@ -1026,6 +1026,19 @@ LONG_STRING_CONST(
"features": [
"regenerate_struct_names"
]
+ },
+ {
+ "id": 91,
+ "cr_bugs": [150500],
+ "description": "ETC1 non-power-of-two sized textures crash older IMG drivers",
+ "os": {
+ "type": "android"
+ },
+ "gl_vendor": "Imagination.*",
+ "gl_renderer": "PowerVR SGX 540.*",
+ "features": [
+ "etc1_power_of_two_only"
+ ]
}
]
}
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
index 2b220e0..0d9f200 100644
--- a/gpu/config/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -42,6 +42,8 @@
disable_oes_standard_derivatives) \
GPU_OP(DISABLE_POST_SUB_BUFFERS_FOR_ONSCREEN_SURFACES, \
disable_post_sub_buffers_for_onscreen_surfaces) \
+ GPU_OP(ETC1_POWER_OF_TWO_ONLY, \
+ etc1_power_of_two_only) \
GPU_OP(EXIT_ON_CONTEXT_LOST, \
exit_on_context_lost) \
GPU_OP(FORCE_DISCRETE_GPU, \