diff options
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/core/cross/cairo/texture_cairo.cc | 87 | ||||
-rw-r--r-- | o3d/core/cross/cairo/texture_cairo.h | 5 |
2 files changed, 49 insertions, 43 deletions
diff --git a/o3d/core/cross/cairo/texture_cairo.cc b/o3d/core/cross/cairo/texture_cairo.cc index 476988e..7cb8864 100644 --- a/o3d/core/cross/cairo/texture_cairo.cc +++ b/o3d/core/cross/cairo/texture_cairo.cc @@ -1,5 +1,5 @@ /* - * Copyright 2010, Google Inc. + * Copyright 2011, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,6 +34,9 @@ // Texture Class for handling Cairo Rendering Mode. #include "core/cross/cairo/texture_cairo.h" + +#include <string.h> + #include "core/cross/cairo/renderer_cairo.h" namespace o3d { @@ -62,7 +65,6 @@ static int CairoFormatFromO3DFormat( 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 @@ TextureCairo::TextureCairo(ServiceLocator* service_locator, 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 @@ TextureCairo* TextureCairo::Create(ServiceLocator* service_locator, 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 @@ TextureCairo* TextureCairo::Create(ServiceLocator* service_locator, 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 @@ const Texture::RGBASwizzleIndices& TextureCairo::GetABGR32FSwizzleIndices() { } TextureCairo::~TextureCairo() { - cairo_destroy(image_surface_context_); cairo_surface_destroy(image_surface_); renderer_ = NULL; DLOG(INFO) << "Texture2DCairo Destruct"; @@ -152,7 +139,7 @@ void TextureCairo::SetRect(int level, 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,26 +148,48 @@ void TextureCairo::SetRect(int level, 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); - - // 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); - - // Paint to the texture. This copies the data. - cairo_paint(image_surface_context_); - - // Discard our reference to the source surface. - cairo_surface_destroy(source_image_surface); + cairo_surface_flush(image_surface_); + + const unsigned char* src_data = reinterpret_cast<const unsigned char*>( + src_data_void); + + unsigned char* dst_data = cairo_image_surface_get_data(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) { + for (unsigned j = 0; j < src_width; ++j) { + // NOTE: This assumes a little-endian architecture (e.g., x86). It works + // for RGBA or BGRA where alpha is in byte 3. + // Get alpha. + uint8 alpha = src_data[3]; + // Convert each colour. + for (int i = 0; i < 3; i++) { + dst_data[i] = (src_data[i] * alpha + 128U) / 255U; + } + // Copy alpha. + dst_data[3] = alpha; + 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(); } diff --git a/o3d/core/cross/cairo/texture_cairo.h b/o3d/core/cross/cairo/texture_cairo.h index 19aa09c..786d090 100644 --- a/o3d/core/cross/cairo/texture_cairo.h +++ b/o3d/core/cross/cairo/texture_cairo.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, Google Inc. + * Copyright 2011, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -99,7 +99,6 @@ class TextureCairo : public Texture2D { // Initializes the Texture2D. TextureCairo(ServiceLocator* service_locator, cairo_surface_t* image_surface, - cairo_t* image_surface_context, Texture::Format format, int levels, int width, @@ -110,8 +109,6 @@ class TextureCairo : public Texture2D { RendererCairo* renderer_; // The Cairo image for this texture. cairo_surface_t* image_surface_; - // A Cairo drawing context for updating this image. - cairo_t* image_surface_context_; }; } // namespace o2d |