summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authortschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-19 20:32:35 +0000
committertschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-19 20:32:35 +0000
commit1da05ebbe6301142de46ef7cb100b6cc5aaa38c2 (patch)
treebb071de66b7bc8a519a12833b7adf2a98bce39f0 /o3d
parent2fc7d941268313c8c4db1d075600de1e0f410f1a (diff)
downloadchromium_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.cc10
-rw-r--r--o3d/core/cross/cairo/layer.h14
-rw-r--r--o3d/core/cross/cairo/renderer_cairo.cc22
-rw-r--r--o3d/core/cross/cairo/renderer_cairo.h6
-rw-r--r--o3d/core/cross/cairo/texture_cairo.cc94
-rw-r--r--o3d/core/cross/cairo/texture_cairo.h52
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