Skip to content

Commit

Permalink
cc: Adding ETC1 support to UIResourceBitmap and ResourceProvider
Browse files Browse the repository at this point in the history
ETC1 compressed texture format is used by a number of UI elements.

BUG=

Review URL: https://codereview.chromium.org/27973002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@230631 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
powei@chromium.org committed Oct 24, 2013
1 parent 59940fa commit e0a601e
Show file tree
Hide file tree
Showing 17 changed files with 176 additions and 40 deletions.
3 changes: 3 additions & 0 deletions cc/debug/test_web_graphics_context_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ class CC_EXPORT TestWebGraphicsContext3D : public FakeWebGraphicsContext3D {
void set_have_discard_framebuffer(bool have) {
test_capabilities_.discard_framebuffer = have;
}
void set_support_compressed_texture_etc1(bool support) {
test_capabilities_.texture_format_etc1 = support;
}

// When this context is lost, all contexts in its share group are also lost.
void add_share_group_context(WebKit::WebGraphicsContext3D* context3d) {
Expand Down
1 change: 1 addition & 0 deletions cc/output/context_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ ContextProvider::Capabilities::Capabilities()
shallow_flush(false),
swapbuffers_complete_callback(false),
texture_format_bgra8888(false),
texture_format_etc1(false),
texture_rectangle(false),
texture_storage(false),
texture_usage(false),
Expand Down
1 change: 1 addition & 0 deletions cc/output/context_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> {
bool shallow_flush;
bool swapbuffers_complete_callback;
bool texture_format_bgra8888;
bool texture_format_etc1;
bool texture_rectangle;
bool texture_storage;
bool texture_usage;
Expand Down
1 change: 1 addition & 0 deletions cc/resources/raster_worker_pool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
break;
case LUMINANCE_8:
case RGB_565:
case ETC1:
NOTREACHED();
break;
}
Expand Down
3 changes: 2 additions & 1 deletion cc/resources/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class CC_EXPORT Resource {
size_t bytes() const;

inline static size_t MemorySizeBytes(gfx::Size size, ResourceFormat format) {
return BytesPerPixel(format) * size.width() * size.height();
DCHECK_EQ(0u, (BitsPerPixel(format) * size.width() * size.height()) % 8);
return (BitsPerPixel(format) * size.width() * size.height()) / 8;
}

protected:
Expand Down
1 change: 1 addition & 0 deletions cc/resources/resource_format.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ SkBitmap::Config SkBitmapConfig(ResourceFormat format) {
case RGBA_8888:
case BGRA_8888:
return SkBitmap::kARGB_8888_Config;
case ETC1:
case LUMINANCE_8:
case RGB_565:
NOTREACHED();
Expand Down
3 changes: 2 additions & 1 deletion cc/resources/resource_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ enum ResourceFormat {
BGRA_8888,
LUMINANCE_8,
RGB_565,
RESOURCE_FORMAT_MAX = RGB_565,
ETC1,
RESOURCE_FORMAT_MAX = ETC1,
};

SkBitmap::Config SkBitmapConfig(ResourceFormat format);
Expand Down
28 changes: 18 additions & 10 deletions cc/resources/resource_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ GLenum TextureToStorageFormat(ResourceFormat format) {
case RGBA_4444:
case LUMINANCE_8:
case RGB_565:
case ETC1:
NOTREACHED();
break;
}
Expand All @@ -62,6 +63,7 @@ bool IsFormatSupportedForStorage(ResourceFormat format) {
case RGBA_4444:
case LUMINANCE_8:
case RGB_565:
case ETC1:
return false;
}
return false;
Expand Down Expand Up @@ -838,6 +840,7 @@ bool ResourceProvider::InitializeGL() {
use_texture_storage_ext_ = caps.texture_storage;
use_shallow_flush_ = caps.shallow_flush;
use_texture_usage_hint_ = caps.texture_usage;
use_compressed_texture_etc1_ = caps.texture_format_etc1;

texture_uploader_ =
TextureUploader::Create(context3d, use_map_sub, use_shallow_flush_);
Expand Down Expand Up @@ -1264,6 +1267,7 @@ void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
DCHECK(!resource->external);
DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->image_id);
DCHECK_NE(ETC1, resource->format);

if (resource->type == GLTexture) {
WebGraphicsContext3D* context3d = Context3d();
Expand All @@ -1273,7 +1277,7 @@ void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
context3d->bindBuffer(
GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
resource->gl_pixel_buffer_id);
unsigned bytes_per_pixel = BytesPerPixel(resource->format);
unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8;
context3d->bufferData(
GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
resource->size.height() * RoundUp(bytes_per_pixel
Expand Down Expand Up @@ -1596,15 +1600,19 @@ void ResourceProvider::LazyAllocate(Resource* resource) {
size.width(),
size.height()));
} else {
GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D,
0,
GLInternalFormat(format),
size.width(),
size.height(),
0,
GLDataFormat(format),
GLDataType(format),
NULL));
// ETC1 does not support preallocation.
if (format != ETC1) {
GLC(context3d,
context3d->texImage2D(GL_TEXTURE_2D,
0,
GLInternalFormat(format),
size.width(),
size.height(),
0,
GLDataFormat(format),
GLDataType(format),
NULL));
}
}
}

Expand Down
32 changes: 18 additions & 14 deletions cc/resources/resource_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ class CC_EXPORT ResourceProvider {
bool use_texture_storage_ext_;
bool use_texture_usage_hint_;
bool use_shallow_flush_;
bool use_compressed_texture_etc1_;
scoped_ptr<TextureUploader> texture_uploader_;
int max_texture_size_;
ResourceFormat best_texture_format_;
Expand All @@ -497,16 +498,17 @@ class CC_EXPORT ResourceProvider {

// TODO(epenner): Move these format conversions to resource_format.h
// once that builds on mac (npapi.h currently #includes OpenGL.h).
inline unsigned BytesPerPixel(ResourceFormat format) {
inline unsigned BitsPerPixel(ResourceFormat format) {
DCHECK_LE(format, RESOURCE_FORMAT_MAX);
static const unsigned format_bytes_per_pixel[RESOURCE_FORMAT_MAX + 1] = {
4, // RGBA_8888
2, // RGBA_4444
4, // BGRA_8888
1, // LUMINANCE_8
2 // RGB_565
static const unsigned format_bits_per_pixel[RESOURCE_FORMAT_MAX + 1] = {
32, // RGBA_8888
16, // RGBA_4444
32, // BGRA_8888
8, // LUMINANCE_8
16, // RGB_565,
4 // ETC1
};
return format_bytes_per_pixel[format];
return format_bits_per_pixel[format];
}

inline GLenum GLDataType(ResourceFormat format) {
Expand All @@ -516,19 +518,21 @@ inline GLenum GLDataType(ResourceFormat format) {
GL_UNSIGNED_SHORT_4_4_4_4, // RGBA_4444
GL_UNSIGNED_BYTE, // BGRA_8888
GL_UNSIGNED_BYTE, // LUMINANCE_8
GL_UNSIGNED_SHORT_5_6_5 // RGB_565
GL_UNSIGNED_SHORT_5_6_5, // RGB_565,
GL_UNSIGNED_BYTE // ETC1
};
return format_gl_data_type[format];
}

inline GLenum GLDataFormat(ResourceFormat format) {
DCHECK_LE(format, RESOURCE_FORMAT_MAX);
static const unsigned format_gl_data_format[RESOURCE_FORMAT_MAX + 1] = {
GL_RGBA, // RGBA_8888
GL_RGBA, // RGBA_4444
GL_BGRA_EXT, // BGRA_8888
GL_LUMINANCE, // LUMINANCE_8
GL_RGB // RGB_565
GL_RGBA, // RGBA_8888
GL_RGBA, // RGBA_4444
GL_BGRA_EXT, // BGRA_8888
GL_LUMINANCE, // LUMINANCE_8
GL_RGB, // RGB_565
GL_ETC1_RGB8_OES // ETC1
};
return format_gl_data_format[format];
}
Expand Down
74 changes: 74 additions & 0 deletions cc/resources/resource_provider_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2408,6 +2408,15 @@ class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
WGC3Denum format,
WGC3Denum type,
const void* pixels));
MOCK_METHOD8(compressedTexImage2D,
void(WGC3Denum target,
WGC3Dint level,
WGC3Denum internalformat,
WGC3Dsizei width,
WGC3Dsizei height,
WGC3Dint border,
WGC3Dsizei image_size,
const void* data));
MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(WGC3Denum));
MOCK_METHOD3(createImageCHROMIUM, WGC3Duint(WGC3Dsizei, WGC3Dsizei,
WGC3Denum));
Expand Down Expand Up @@ -2832,6 +2841,71 @@ TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
output_surface.get());
}

TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
if (GetParam() != ResourceProvider::GLTexture)
return;

scoped_ptr<AllocationTrackingContext3D> context_owned(
new AllocationTrackingContext3D);
AllocationTrackingContext3D* context = context_owned.get();
context_owned->set_support_compressed_texture_etc1(true);

FakeOutputSurfaceClient output_surface_client;
scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
context_owned.PassAs<TestWebGraphicsContext3D>()));
CHECK(output_surface->BindToClient(&output_surface_client));

gfx::Size size(4, 4);
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(), 0, false));
int texture_id = 123;

ResourceProvider::ResourceId id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
EXPECT_NE(0u, id);
EXPECT_CALL(*context, createTexture()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
resource_provider->AllocateForTesting(id);

EXPECT_CALL(*context, deleteTexture(texture_id)).Times(1);
resource_provider->DeleteResource(id);
}

TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
if (GetParam() != ResourceProvider::GLTexture)
return;

scoped_ptr<AllocationTrackingContext3D> context_owned(
new AllocationTrackingContext3D);
AllocationTrackingContext3D* context = context_owned.get();
context_owned->set_support_compressed_texture_etc1(true);

FakeOutputSurfaceClient output_surface_client;
scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
context_owned.PassAs<TestWebGraphicsContext3D>()));
CHECK(output_surface->BindToClient(&output_surface_client));

gfx::Size size(4, 4);
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(), 0, false));
int texture_id = 123;
uint8_t pixels[8];

ResourceProvider::ResourceId id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
EXPECT_NE(0u, id);
EXPECT_CALL(*context, createTexture()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
EXPECT_CALL(*context,
compressedTexImage2D(
_, 0, _, size.width(), size.height(), _, _, _)).Times(1);
resource_provider->SetPixels(
id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));

EXPECT_CALL(*context, deleteTexture(texture_id)).Times(1);
resource_provider->DeleteResource(id);
}

INSTANTIATE_TEST_CASE_P(
ResourceProviderTests,
ResourceProviderTest,
Expand Down
15 changes: 10 additions & 5 deletions cc/resources/ui_resource_bitmap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,36 @@ namespace cc {

void UIResourceBitmap::Create(const skia::RefPtr<SkPixelRef>& pixel_ref,
UIResourceFormat format,
UIResourceWrapMode wrap_mode,
gfx::Size size) {
DCHECK(size.width());
DCHECK(size.height());
DCHECK(pixel_ref);
DCHECK(pixel_ref->isImmutable());
format_ = format;
wrap_mode_ = wrap_mode;
size_ = size;
pixel_ref_ = pixel_ref;

// Wrap mode defaults to CLAMP_TO_EDGE.
wrap_mode_ = CLAMP_TO_EDGE;
}

UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap,
UIResourceWrapMode wrap_mode) {
UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap) {
DCHECK_EQ(skbitmap.config(), SkBitmap::kARGB_8888_Config);
DCHECK_EQ(skbitmap.width(), skbitmap.rowBytesAsPixels());
DCHECK(skbitmap.isImmutable());

skia::RefPtr<SkPixelRef> pixel_ref = skia::SharePtr(skbitmap.pixelRef());
Create(pixel_ref,
UIResourceBitmap::RGBA8,
wrap_mode,
gfx::Size(skbitmap.width(), skbitmap.height()));
}

UIResourceBitmap::UIResourceBitmap(const skia::RefPtr<SkPixelRef>& pixel_ref,
UIResourceFormat format,
gfx::Size size) {
Create(pixel_ref, format, size);
}

UIResourceBitmap::~UIResourceBitmap() {}

AutoLockUIResourceBitmap::AutoLockUIResourceBitmap(
Expand Down
12 changes: 8 additions & 4 deletions cc/resources/ui_resource_bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ namespace cc {
class CC_EXPORT UIResourceBitmap {
public:
enum UIResourceFormat {
RGBA8
RGBA8,
ETC1
};
enum UIResourceWrapMode {
CLAMP_TO_EDGE,
Expand All @@ -34,20 +35,23 @@ class CC_EXPORT UIResourceBitmap {
gfx::Size GetSize() const { return size_; }
UIResourceFormat GetFormat() const { return format_; }
UIResourceWrapMode GetWrapMode() const { return wrap_mode_; }
void SetWrapMode(UIResourceWrapMode wrap_mode) { wrap_mode_ = wrap_mode; }

// The constructor for the UIResourceBitmap. User must ensure that |skbitmap|
// is immutable. The SkBitmap format should be in 32-bit RGBA. Wrap mode is
// unnecessary for most UI resources and is defaulted to CLAMP_TO_EDGE.
UIResourceBitmap(const SkBitmap& skbitmap,
UIResourceWrapMode wrap_mode = CLAMP_TO_EDGE);
explicit UIResourceBitmap(const SkBitmap& skbitmap);

UIResourceBitmap(const skia::RefPtr<SkPixelRef>& pixel_ref,
UIResourceFormat format,
gfx::Size size);

~UIResourceBitmap();

private:
friend class AutoLockUIResourceBitmap;
void Create(const skia::RefPtr<SkPixelRef>& pixel_ref,
UIResourceFormat format,
UIResourceWrapMode wrap_mode,
gfx::Size size);

skia::RefPtr<SkPixelRef> pixel_ref_;
Expand Down
Loading

0 comments on commit e0a601e

Please sign in to comment.