Chromium Code Reviews| Index: core/cross/cairo/texture_cairo.cc |
| =================================================================== |
| --- core/cross/cairo/texture_cairo.cc (revision 71819) |
| +++ core/cross/cairo/texture_cairo.cc (working copy) |
| @@ -34,6 +34,9 @@ |
| // Texture Class for handling Cairo Rendering Mode. |
| #include "core/cross/cairo/texture_cairo.h" |
| + |
| +#include <string.h> |
|
fbarchard
2011/01/24 19:23:09
is this needed?
Tristan Schmelcher 2
2011/01/24 19:43:37
Yes, it's for memcpy.
|
| + |
| #include "core/cross/cairo/renderer_cairo.h" |
| namespace o3d { |
| @@ -62,7 +65,6 @@ |
| TextureCairo::TextureCairo(ServiceLocator* service_locator, |
| cairo_surface_t* image_surface, |
| - cairo_t* image_surface_context, |
| Texture::Format format, |
| int levels, |
| int width, |
| @@ -76,8 +78,7 @@ |
| enable_render_surfaces), |
| renderer_(static_cast<RendererCairo*>( |
| service_locator->GetService<Renderer>())), |
| - image_surface_(image_surface), |
| - image_surface_context_(image_surface_context) { |
| + image_surface_(image_surface) { |
| DLOG(INFO) << "Texture2D Construct"; |
| DCHECK_NE(format, Texture::UNKNOWN_FORMAT); |
| } |
| @@ -91,7 +92,6 @@ |
| bool enable_render_surfaces) { |
| int cairo_format = CairoFormatFromO3DFormat(format); |
| cairo_surface_t* image_surface; |
| - cairo_t* image_surface_context; |
| cairo_status_t status; |
| if (-1 == cairo_format) { |
| DLOG(ERROR) << "Texture format " << format << " not supported by Cairo"; |
| @@ -106,27 +106,15 @@ |
| DLOG(ERROR) << "Error creating Cairo image surface: " << status; |
| goto fail1; |
| } |
| - image_surface_context = cairo_create(image_surface); |
| - status = cairo_status(image_surface_context); |
| - if (CAIRO_STATUS_SUCCESS != status) { |
| - DLOG(ERROR) << "Error creating Cairo image surface draw context: " |
| - << status; |
| - goto fail2; |
| - } |
| - cairo_set_operator(image_surface_context, CAIRO_OPERATOR_SOURCE); |
| - |
| return new TextureCairo(service_locator, |
| image_surface, |
| - image_surface_context, |
| format, |
| levels, |
| width, |
| height, |
| enable_render_surfaces); |
| - fail2: |
| - cairo_destroy(image_surface_context); |
| fail1: |
| cairo_surface_destroy(image_surface); |
| fail0: |
| @@ -140,7 +128,6 @@ |
| } |
| TextureCairo::~TextureCairo() { |
| - cairo_destroy(image_surface_context_); |
| cairo_surface_destroy(image_surface_); |
| renderer_ = NULL; |
| DLOG(INFO) << "Texture2DCairo Destruct"; |
| @@ -152,7 +139,7 @@ |
| unsigned dst_top, |
| unsigned src_width, |
| unsigned src_height, |
| - const void* src_data, |
| + const void* src_data_void, |
| int src_pitch) { |
| DLOG(INFO) << "Texture2DCairo SetRect"; |
| @@ -161,27 +148,53 @@ |
| return; |
| } |
| - // Create image surface to represent the source. |
| - cairo_surface_t* source_image_surface = cairo_image_surface_create_for_data( |
| - const_cast<unsigned char*>( |
| - static_cast<const unsigned char*>(src_data)), |
| - cairo_image_surface_get_format(image_surface_), |
| - src_width, |
| - src_height, |
| - src_pitch); |
| + cairo_surface_flush(image_surface_); |
| - // Set that surface as the source for paint operations to our texture. |
| - cairo_set_source_surface(image_surface_context_, |
| - source_image_surface, |
| - dst_left, |
| - dst_top); |
| + const unsigned char* src_data = reinterpret_cast<const unsigned char*>( |
| + src_data_void); |
| - // Paint to the texture. This copies the data. |
| - cairo_paint(image_surface_context_); |
| + unsigned char* dst_data = cairo_image_surface_get_data(image_surface_); |
| - // Discard our reference to the source surface. |
| - cairo_surface_destroy(source_image_surface); |
| + int dst_pitch = cairo_image_surface_get_stride(image_surface_); |
| + dst_data += dst_top * dst_pitch + dst_left * 4; |
| + |
| + if (ARGB8 == format()) { |
| + // Cairo supports only premultiplied alpha, but we get the images as |
| + // non-premultiplied alpha, so we have to convert. |
| + for (unsigned i = 0; i < src_height; ++i) { |
|
Tim H
2011/01/24 19:57:55
Are i and j typed correctly?
Tristan Schmelcher 2
2011/01/24 20:25:28
Yeah, they are unsigned to prevent compile warning
|
| + for (unsigned j = 0; j < src_width; ++j) { |
| + // Get source pixel. |
| + uint32 src_pixel = *reinterpret_cast<const uint32*>(src_data); |
| + // Initialize dst_pixel to black with src_pixel's transparency. |
| + uint32 dst_pixel = src_pixel & 0xFF000000; |
| + // Get alpha. |
| + uint32 alpha = src_pixel >> 24; |
| + // Convert the blue. |
| + dst_pixel |= (src_pixel & 0xFF) * alpha / 255; |
|
fbarchard
2011/01/24 19:23:09
Should add rounding
dst_pixel |= ((src_pixel & 0xF
Tristan Schmelcher 2
2011/01/24 19:43:37
Done.
|
| + // Convert the green. |
| + dst_pixel |= (((src_pixel >> 8) & 0xFF) * alpha / 255) << 8; |
| + // Convert the red. |
| + dst_pixel |= (((src_pixel >> 16) & 0xFF) * alpha / 255) << 16; |
|
fbarchard
2011/01/24 19:23:09
note that this will be slow overall.
would be more
Tristan Schmelcher 2
2011/01/24 19:43:37
Hmm, I will try both and look at the compiled asse
fbarchard
2011/01/24 19:56:19
Using int you have 2 shifts, an AND and OR per cha
|
| + // Store result. |
| + *reinterpret_cast<uint32*>(dst_data) = dst_pixel; |
| + src_data += 4; |
| + dst_data += 4; |
| + } |
| + src_data += src_pitch - src_width * 4; |
| + dst_data += dst_pitch - src_width * 4; |
| + } |
| + } else { |
| + // Just copy the data. |
| + for (unsigned i = 0; i < src_height; ++i) { |
| + memcpy(dst_data, src_data, src_width * 4); |
| + src_data += src_pitch; |
| + dst_data += dst_pitch; |
| + } |
| + } |
| + |
| + cairo_surface_mark_dirty(image_surface_); |
| + |
| TextureUpdated(); |
| } |