diff options
author | tschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-19 20:32:35 +0000 |
---|---|---|
committer | tschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-19 20:32:35 +0000 |
commit | 1da05ebbe6301142de46ef7cb100b6cc5aaa38c2 (patch) | |
tree | bb071de66b7bc8a519a12833b7adf2a98bce39f0 /o3d | |
parent | 2fc7d941268313c8c4db1d075600de1e0f410f1a (diff) | |
download | chromium_src-1da05ebbe6301142de46ef7cb100b6cc5aaa38c2.zip chromium_src-1da05ebbe6301142de46ef7cb100b6cc5aaa38c2.tar.gz chromium_src-1da05ebbe6301142de46ef7cb100b6cc5aaa38c2.tar.bz2 |
O2D:
- Save textures in memory rather than reading them directly from the SetRect() source, which is an unsafe hack. This fixes a crash when a texture was painted after the shared memory was unregistered, or if a texture was painted that was created from a static image downloaded from the net. This is a perf regression due to the extra copy, but we can add a special shared memory texture class later. This also regresses the functionality because SetRect() updates only a portion of the texture but RendererCairo paints the entire texture. An upcoming CL will add an API to define the region to paint.
- Remove unused weak pointer tracker from Layer class.
- Create textures of the requested image format rather than hard-coding ARGB8, and fail for formats not supported by Cairo.
- Fix a couple crashes caused by missing refcounts.
- Fix crash when trying to render a Layer that has no assigned texture.
TEST=loaded O2D many times
BUG=none
Review URL: http://codereview.chromium.org/5134005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66807 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/core/cross/cairo/layer.cc | 10 | ||||
-rw-r--r-- | o3d/core/cross/cairo/layer.h | 14 | ||||
-rw-r--r-- | o3d/core/cross/cairo/renderer_cairo.cc | 22 | ||||
-rw-r--r-- | o3d/core/cross/cairo/renderer_cairo.h | 6 | ||||
-rw-r--r-- | o3d/core/cross/cairo/texture_cairo.cc | 94 | ||||
-rw-r--r-- | o3d/core/cross/cairo/texture_cairo.h | 52 |
6 files changed, 113 insertions, 85 deletions
diff --git a/o3d/core/cross/cairo/layer.cc b/o3d/core/cross/cairo/layer.cc index e64bd03..23d4dfc 100644 --- a/o3d/core/cross/cairo/layer.cc +++ b/o3d/core/cross/cairo/layer.cc @@ -43,9 +43,13 @@ namespace o2d { O3D_DEFN_CLASS(Layer, ParamObject); Layer::Layer(ServiceLocator* service_locator) - : ParamObject(service_locator), texture_(NULL), - weak_pointer_manager_(this), alpha_(0), scale_x_(0), scale_y_(0), - translate_x_(0), translate_y_(0) { + : ParamObject(service_locator), + texture_(NULL), + alpha_(0), + scale_x_(0), + scale_y_(0), + translate_x_(0), + translate_y_(0) { DLOG(INFO) << "Create Layer"; } diff --git a/o3d/core/cross/cairo/layer.h b/o3d/core/cross/cairo/layer.h index dbe7738..8c341d5 100644 --- a/o3d/core/cross/cairo/layer.h +++ b/o3d/core/cross/cairo/layer.h @@ -49,11 +49,11 @@ namespace o2d { class Layer : public ParamObject { friend class Client; public: - typedef WeakPointer<Layer> WeakPointerType; + typedef SmartPointer<Layer> Ref; // Set the corresponding texture for this Layer instance. void SetTexture(Texture* texture) { - texture_ = down_cast<TextureCairo*>(texture); + texture_ = TextureCairo::Ref(down_cast<TextureCairo*>(texture)); } TextureCairo* GetTexture() { @@ -95,11 +95,6 @@ class Layer : public ParamObject { scale_y_ = y; } - // Gets a weak pointer to us. - WeakPointerType GetWeakPointer() const { - return weak_pointer_manager_.GetWeakPointer(); - } - private: explicit Layer(ServiceLocator* service_locator); @@ -107,10 +102,7 @@ class Layer : public ParamObject { static ObjectBase::Ref Create(ServiceLocator* service_locator); // Texture Container. - TextureCairo* texture_; - - // Manager for weak pointers to us. - WeakPointerType::WeakPointerManager weak_pointer_manager_; + TextureCairo::Ref texture_; // Transparancy of the scene. float alpha_; diff --git a/o3d/core/cross/cairo/renderer_cairo.cc b/o3d/core/cross/cairo/renderer_cairo.cc index ef70d79..018b79e2 100644 --- a/o3d/core/cross/cairo/renderer_cairo.cc +++ b/o3d/core/cross/cairo/renderer_cairo.cc @@ -72,9 +72,6 @@ void RendererCairo::Destroy() { display_ = NULL; } -// TODO(fransiskusx): Need to check if the shared memory data has been -// unregistered. It will prevent errors when accessing unregistered -// shared memory data to render the frame. void RendererCairo::Paint() { DLOG(INFO) << "To paint"; cairo_t* current_drawing = cairo_create(main_surface_); @@ -92,8 +89,8 @@ void RendererCairo::Paint() { Layer* cur = *i; TextureCairo* cur_texture = cur->GetTexture(); - // Check if the pointer to data is null. - if (cur_texture->GetData() == NULL) { + if (!cur_texture) { + // Skip layers with no texture assigned. continue; } @@ -103,17 +100,13 @@ void RendererCairo::Paint() { MaskArea(current_drawing, start_mask_it); // Preparing the image to render. - cairo_surface_t* image = cairo_image_surface_create_for_data( - const_cast<unsigned char*>( - static_cast<const unsigned char*>(cur_texture->GetData())), - CAIRO_FORMAT_ARGB32, cur_texture->GetWidth(), - cur_texture->GetHeight(), cur_texture->GetPitch()); + cairo_surface_t* image = cur_texture->image_surface(); // Scale the image. double width_scaling = - (static_cast<double>(cur->GetScaleX())) / cur_texture->GetWidth(); + (static_cast<double>(cur->GetScaleX())) / cur_texture->width(); double height_scaling = - (static_cast<double>(cur->GetScaleY())) / cur_texture->GetHeight(); + (static_cast<double>(cur->GetScaleY())) / cur_texture->height(); cairo_scale(current_drawing, width_scaling, height_scaling); @@ -124,9 +117,6 @@ void RendererCairo::Paint() { cairo_paint_with_alpha(current_drawing, cur->GetAlpha()); - // Cleaning up the memory. - cairo_surface_destroy(image); - // Restore to the state with no mask. cairo_restore(current_drawing); } @@ -161,7 +151,7 @@ void RendererCairo::MaskArea(cairo_t* cr, LayerRefList::iterator it) { } void RendererCairo::AddLayer(Layer* image) { - layer_list_.push_front(image); + layer_list_.push_front(Layer::Ref(image)); } void RendererCairo::InitCommon() { diff --git a/o3d/core/cross/cairo/renderer_cairo.h b/o3d/core/cross/cairo/renderer_cairo.h index 4452bc4f..f62698a 100644 --- a/o3d/core/cross/cairo/renderer_cairo.h +++ b/o3d/core/cross/cairo/renderer_cairo.h @@ -38,15 +38,15 @@ #include <build/build_config.h> #include <list> #include <vector> + #include "core/cross/renderer_platform.h" #include "core/cross/renderer.h" +#include "core/cross/cairo/layer.h" namespace o3d { namespace o2d { -class Layer; - class RendererCairo : public Renderer { public: static RendererCairo* CreateDefault(ServiceLocator* service_locator); @@ -152,7 +152,7 @@ class RendererCairo : public Renderer { void PopRenderStates(); protected: - typedef std::list<Layer*> LayerRefList; + typedef std::list<Layer::Ref> LayerRefList; // Keep the constructor protected so only factory methods can create // renderers. diff --git a/o3d/core/cross/cairo/texture_cairo.cc b/o3d/core/cross/cairo/texture_cairo.cc index d179a10..31ab81f 100644 --- a/o3d/core/cross/cairo/texture_cairo.cc +++ b/o3d/core/cross/cairo/texture_cairo.cc @@ -46,7 +46,23 @@ Texture::RGBASwizzleIndices g_gl_abgr32f_swizzle_indices = {0, 1, 2, 3}; namespace o2d { +static int CairoFormatFromO3DFormat( + Texture::Format format) { + switch (format) { + case Texture::ARGB8: + return CAIRO_FORMAT_ARGB32; + case Texture::XRGB8: + return CAIRO_FORMAT_RGB24; + default: + return -1; + } + // Cairo also supports two other pure-alpha formats, but we don't expose those + // capabilities. +} + TextureCairo::TextureCairo(ServiceLocator* service_locator, + cairo_surface_t* image_surface, + cairo_t* image_surface_context, Texture::Format format, int levels, int width, @@ -60,7 +76,8 @@ TextureCairo::TextureCairo(ServiceLocator* service_locator, enable_render_surfaces), renderer_(static_cast<RendererCairo*>( service_locator->GetService<Renderer>())), - data_(NULL), left_(0), top_(0), width_(0), height_(0), pitch_(0) { + image_surface_(image_surface), + image_surface_context_(image_surface_context) { DLOG(INFO) << "Texture2D Construct"; DCHECK_NE(format, Texture::UNKNOWN_FORMAT); } @@ -72,13 +89,46 @@ TextureCairo* TextureCairo::Create(ServiceLocator* service_locator, int width, int height, bool enable_render_surfaces) { - TextureCairo* texture = new TextureCairo(service_locator, - format, - levels, - width, - height, - enable_render_surfaces); - return texture; + 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"; + goto fail0; + } + image_surface = cairo_image_surface_create( + static_cast<cairo_format_t>(cairo_format), + width, + height); + status = cairo_surface_status(image_surface); + if (CAIRO_STATUS_SUCCESS != status) { + 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; + } + + 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: + return NULL; } // In 2D: is not really used @@ -88,6 +138,8 @@ const Texture::RGBASwizzleIndices& TextureCairo::GetABGR32FSwizzleIndices() { } TextureCairo::~TextureCairo() { + cairo_destroy(image_surface_context_); + cairo_surface_destroy(image_surface_); renderer_ = NULL; DLOG(INFO) << "Texture2DCairo Destruct"; } @@ -102,12 +154,26 @@ void TextureCairo::SetRect(int level, int src_pitch) { DLOG(INFO) << "Texture2DCairo SetRect"; - data_ = src_data; - left_ = dst_left; - top_ = dst_top; - width_ = src_width; - height_ = src_height; - pitch_ = src_pitch; + // 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); } // Locks the given mipmap level of this texture for loading from main memory, diff --git a/o3d/core/cross/cairo/texture_cairo.h b/o3d/core/cross/cairo/texture_cairo.h index 217c9db..19aa09c 100644 --- a/o3d/core/cross/cairo/texture_cairo.h +++ b/o3d/core/cross/cairo/texture_cairo.h @@ -38,6 +38,9 @@ #include "core/cross/texture.h" +typedef struct _cairo cairo_t; +typedef struct _cairo_surface cairo_surface_t; + namespace o3d { namespace o2d { @@ -74,28 +77,8 @@ class TextureCairo : public Texture2D { // RGBA to the internal format used by the rendering API. virtual const RGBASwizzleIndices& GetABGR32FSwizzleIndices(); - const void* GetData() { - return data_; - } - - unsigned GetOriginX() { - return left_; - } - - unsigned GetOriginY() { - return top_; - } - - unsigned GetWidth() { - return width_; - } - - unsigned GetHeight() { - return height_; - } - - int GetPitch() { - return pitch_; + cairo_surface_t* image_surface() const { + return image_surface_; } protected: @@ -112,30 +95,23 @@ class TextureCairo : public Texture2D { // Returns the implementation-specific texture handle for this texture. virtual void* GetTextureHandle() const; - // The 2d renderer object to be used by client. - RendererCairo* renderer_; - - // Current Frame Data Source - const void* data_; - // X coordinate - unsigned left_; - // Y coordinate - unsigned top_; - // Current Frame Source Width - unsigned width_; - // Current Frame Source Height - unsigned height_; - // Current Frame Source Pitch - int pitch_; - private: // Initializes the Texture2D. TextureCairo(ServiceLocator* service_locator, + cairo_surface_t* image_surface, + cairo_t* image_surface_context, Texture::Format format, int levels, int width, int height, bool enable_render_surfaces); + + // The 2d renderer object to be used by client. + 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 |