blob: acca4ed7b14f55038d9710206cfebd8f936c283c [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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef COBALT_RENDER_TREE_IMAGE_H_
#define COBALT_RENDER_TREE_IMAGE_H_
#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 {
kPixelFormatRGBA8,
kPixelFormatBGRA8,
kPixelFormatUYVY,
kPixelFormatY8,
kPixelFormatU8,
kPixelFormatV8,
kPixelFormatUV8,
kPixelFormatInvalid,
};
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 kPixelFormatUYVY:
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.
kAlphaFormatPremultiplied,
// This alpha format implies standard alpha, where each component is
// independent of the alpha.
kAlphaFormatUnpremultiplied,
// Indicates that all alpha values in the image data are opaque. If
// non-opaque alpha data is used with this format, visual output will be
// undefined. This information may be used to enable optimizations, and can
// result in Image::IsOpaque() returning true.
kAlphaFormatOpaque,
};
// 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),
pixel_format(pixel_format),
alpha_format(alpha_format),
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 {
public:
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 {
public:
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.
kMultiPlaneImageFormatYUV3PlaneBT709,
// 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.
kMultiPlaneImageFormatYUV2PlaneBT709,
};
// 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 {
public:
// 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);
++num_planes_;
}
// 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;
}
private:
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> {
public:
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() *
BytesPerPixel(kPixelFormatRGBA8));
}
// If an Image is able to know that it contains no alpha data (e.g. if it
// was constructed from ImageData whose alpha format is set to
// kAlphaFormatOpaque), then this method can return true, and code can
// be written to take advantage of this and perform optimizations.
virtual bool IsOpaque() const { return false; }
protected:
virtual ~Image() {}
// Allow the reference counting system access to our destructor.
friend class base::RefCountedThreadSafe<Image>;
};
} // namespace render_tree
} // namespace cobalt
#endif // COBALT_RENDER_TREE_IMAGE_H_