blob: 8faa0403e43055cdec8e5f0009985ef328bd6450 [file] [log] [blame]
* Copyright 2014 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* See the License for the specific language governing permissions and
* limitations under the License.
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "cobalt/math/size.h"
namespace cobalt {
namespace render_tree {
// Formats of pixel data that we support creating images from.
enum PixelFormat {
inline int BytesPerPixel(PixelFormat pixel_format) {
switch (pixel_format) {
case kPixelFormatRGBA8:
return 4;
case kPixelFormatBGRA8:
return 4;
case kPixelFormatY8:
return 1;
case kPixelFormatU8:
return 1;
case kPixelFormatV8:
return 1;
case kPixelFormatUV8:
return 2;
case kPixelFormatInvalid:
DLOG(FATAL) << "Unexpected pixel format.";
return -1;
enum AlphaFormat {
// Premultiplied alpha means that the RGB components (in terms of
// the range [0.0, 1.0]) have already been multiplied by the A component
// (also in the range [0.0, 1.0]). Thus, it is expected that for all
// pixels, each component is less than or equal to the alpha component.
// This alpha format implies standard alpha, where each component is
// independent of the alpha.
// Describes the format of a contiguous block of memory that represents an
// image. This descriptor can only describe image formats where all information
// for a given pixel is stored contiguously in memory, and all pixels are
// sequentially ordered. For image data that is stored within multiple planes,
// see MultiPlaneImageDataDescriptor below.
struct ImageDataDescriptor {
ImageDataDescriptor(const math::Size& size, PixelFormat pixel_format,
AlphaFormat alpha_format, int pitch_in_bytes)
: size(size),
pitch_in_bytes(pitch_in_bytes) {}
math::Size size;
PixelFormat pixel_format;
AlphaFormat alpha_format;
int pitch_in_bytes;
// ImageData is an interface for an object that contains an allocation
// of CPU-accessible memory that is intended to be passed in to CreateImage()
// so that it may be used by the GPU.
class ImageData {
virtual ~ImageData() {}
// Returns information about the kind of data this ImageData is
// intended to store.
virtual const ImageDataDescriptor& GetDescriptor() const = 0;
// Returns a pointer to the image data so that one can set pixel data as
// necessary.
virtual uint8_t* GetMemory() = 0;
class RawImageMemory {
virtual ~RawImageMemory() {}
virtual size_t GetSizeInBytes() const = 0;
virtual uint8_t* GetMemory() = 0;
// Specifies formats for multi-plane images, typically produced by video
// decoders.
enum MultiPlaneImageFormat {
// A YUV image where each channel, Y, U and V, is stored as a separate
// single-channel image plane.
// A YUV image where the Y channel is stored as a single-channel image plane
// and the U and V channels are interleaved in a second image plane.
// Like the ImageDataDescriptor object, a MultiPlaneImageDataDescriptor
// describes the format of a multiplane image pixel data. A multi plane
// image is an image who's pixel data is split among multiple contiguous
// regions of memory (planes). For example, many video decoders output
// YUV image data where each of the three channels, Y, U and V, are stored
// separately as their own single channel images.
// The MultiPlaneImageDataDescriptor describes each channel in terms of a
// standard single plane ImageDataDescriptor object. In addition, a
// MultiPlaneImageFormat label is also assigned to the the image to describe
// how separate channels should be combined to form the final image.
class MultiPlaneImageDataDescriptor {
// For efficiency reasons (to avoid dynamic memory allocations) we define a
// maximum number of supported planes.
static const int kMaxPlanes = 3;
explicit MultiPlaneImageDataDescriptor(MultiPlaneImageFormat image_format)
: image_format_(image_format), num_planes_(0) {}
// Pushes a new plane descriptor onto the list of planes. Multi-plane images
// are defined over one large contiguous region of memory, and each plane
// occupies a subset of that memory. The offset parameter specifies where
// to find the newly added plane relative to a contiguous region of memory.
// For example, in 3 plane YUV, the V plane would have an offset at least
// larger than the size of the data for the Y plane plus the U plane.
void AddPlane(intptr_t offset, const ImageDataDescriptor& descriptor) {
DCHECK_GT(kMaxPlanes, num_planes_);
plane_descriptors_[num_planes_].emplace(offset, descriptor);
// Returns the multi-plane image format of this image as a whole.
MultiPlaneImageFormat image_format() const { return image_format_; }
// Returns the number of planes described by this descriptor (i.e. the number
// of times AddPlane() has been called).
int num_planes() const { return num_planes_; }
// Returns the offset specified by AddPlane() for the given plane_index.
intptr_t GetPlaneOffset(int plane_index) const {
DCHECK_LE(0, plane_index);
DCHECK_GT(num_planes_, plane_index);
return plane_descriptors_[plane_index]->offset;
// Returns the single-plane image descriptor specified by AddPlane() for the
// given plane_index.
const ImageDataDescriptor& GetPlaneDescriptor(int plane_index) const {
DCHECK_LE(0, plane_index);
DCHECK_GT(num_planes_, plane_index);
return plane_descriptors_[plane_index]->descriptor;
struct PlaneInformation {
PlaneInformation(intptr_t offset, const ImageDataDescriptor& descriptor)
: offset(offset), descriptor(descriptor) {}
intptr_t offset;
ImageDataDescriptor descriptor;
MultiPlaneImageFormat image_format_;
int num_planes_;
// We keep an array of base::optionals so that we don't have to specify a
// default constructor for PlaneInformation.
base::optional<PlaneInformation> plane_descriptors_[kMaxPlanes];
// The Image type is an abstract base class that represents a stored image
// and all of its pixel information. When constructing a render tree,
// external images can be introduced by adding an ImageNode and associating it
// with a specific Image object. Examples of concrete Image objects include
// an Image that stores its pixel data in a CPU memory buffer, or one that
// stores its image data as a GPU texture. Regardless, the concrete type of
// an Image objects is not relevant unless the Image is being constructed or
// it is being read by a rasterizer reading a submitted render tree. Since
// the rasterizer may only be compatible with specific concrete Image types,
// it is expected that the object will be safely downcast by the rasterizer
// to a rasterizer-specific Image type using base::polymorphic_downcast().
class Image : public base::RefCountedThreadSafe<Image> {
virtual const math::Size& GetSize() const = 0;
// The default implementation is to estimate the size based on the width and
// height. Derived classes may override this calculation with a more accurate
// one.
virtual uint32 GetEstimatedSizeInBytes() const {
return static_cast<uint32>(GetSize().width() * GetSize().height() *
virtual ~Image() {}
// Allow the reference counting system access to our destructor.
friend class base::RefCountedThreadSafe<Image>;
} // namespace render_tree
} // namespace cobalt