blob: d8cba665affcd828168a2984379882f39976e8ea [file] [log] [blame]
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PPAPI_CPP_PAINT_MANAGER_H_
#define PPAPI_CPP_PAINT_MANAGER_H_
#include <vector>
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/graphics_2d.h"
#include "ppapi/cpp/paint_aggregator.h"
namespace pp {
class Graphics2D;
class Instance;
class Point;
class Rect;
// This class converts the "plugin push" model of painting in PPAPI to a paint
// request at a later time. Usage is that you call Invalidate and Scroll, and
// implement the Client interface. Your OnPaint handler will then get called
// with coalesced paint events.
//
// This class is basically a PaintAggregator that groups updates, plus
// management of callbacks for scheduling paints.
//
// Typical usage:
//
// class MyClass : public pp::Instance, public PaintManager::Client {
// public:
// MyClass() {
// paint_manager_.Initialize(this, this, false);
// }
//
// void ViewChanged(const pp::Rect& position, const pp::Rect& clip) {
// paint_manager_.SetSize(position.size());
// }
//
// void DoSomething() {
// // This function does something like respond to an event that causes
// // the screen to need updating.
// paint_manager_.InvalidateRect(some_rect);
// }
//
// // Implementation of PaintManager::Client
// virtual bool OnPaint(pp::Graphics2D& device,
// const pp::PaintUpdate& update) {
// // If our app needed scrolling, we would apply that first here.
//
// // Then we would either repaint the area returned by GetPaintBounds or
// // iterate through all the paint_rects.
//
// // The caller will call Flush() for us, so don't do that here.
// return true;
// }
//
// private:
// pp::PaintManager paint_manager_;
// };
class PaintManager {
public:
class Client {
public:
// Paints the given invalid area of the plugin to the given graphics
// device. Returns true if anything was painted.
//
// You are given the list of rects to paint in |paint_rects|, and the
// union of all of these rects in |paint_bounds|. You only have to paint
// the area inside each of the |paint_rects|, but can paint more if you
// want (some apps may just want to paint the union).
//
// Do not call Flush() on the graphics device, this will be done
// automatically if you return true from this function since the
// PaintManager needs to handle the callback.
//
// It is legal for you to cause invalidates inside of Paint which will
// then get executed as soon as the Flush for this update has completed.
// However, this is not very nice to the host system since it will spin the
// CPU, possibly updating much faster than necessary. It is best to have a
// 1/60 second timer to do an invalidate instead. This will limit your
// animation to the slower of 60Hz or "however fast Flush can complete."
virtual bool OnPaint(Graphics2D& graphics,
const std::vector<Rect>& paint_rects,
const Rect& paint_bounds) = 0;
protected:
// You shouldn't be doing deleting through this interface.
virtual ~Client() {}
};
// If you use this version of the constructor, you must call Initialize()
// below.
PaintManager();
// The instance is the plugin instance using this paint manager to do its
// painting. Painting will automatically go to this instance and you don't
// have to manually bind any device context (this is all handled by the
// paint manager).
//
// The Client is a non-owning pointer and must remain valid (normally the
// object implementing the Client interface will own the paint manager).
//
// The is_always_opaque flag will be passed to the device contexts that this
// class creates. Set this to true if your plugin always draws an opaque
// image to the device. This is used as a hint to the browser that it does
// not need to do alpha blending, which speeds up painting. If you generate
// non-opqaue pixels or aren't sure, set this to false for more general
// blending.
//
// If you set is_always_opaque, your alpha channel should always be set to
// 0xFF or there may be painting artifacts. Being opaque will allow the
// browser to do a memcpy rather than a blend to paint the plugin, and this
// means your alpha values will get set on the page backing store. If these
// values are incorrect, it could mess up future blending. If you aren't
// sure, it is always correct to specify that it it not opaque.
//
// You will need to call SetSize before this class will do anything. Normally
// you do this from the ViewChanged method of your plugin instance.
PaintManager(Instance* instance, Client* client, bool is_always_opaque);
~PaintManager();
// You must call this function before using if you use the 0-arg constructor.
// See the constructor for what these arguments mean.
void Initialize(Instance* instance, Client* client, bool is_always_opaque);
// Setters for the configuration settings in the paint aggregator.
// See paint_aggregator.h for what these mean.
void set_max_redundant_paint_to_scroll_area(float area) {
aggregator_.set_max_redundant_paint_to_scroll_area(area);
}
void set_max_paint_rects(size_t max_rects) {
aggregator_.set_max_paint_rects(max_rects);
}
// Sets the size of the plugin. If the size is the same as the previous call,
// this will be a NOP. If the size has changed, a new device will be
// allocated to the given size and a paint to that device will be scheduled.
//
// This is intended to be called from ViewChanged with the size of the
// plugin. Since it tracks the old size and only allocates when the size
// changes, you can always call this function without worrying about whether
// the size changed or ViewChanged is called for another reason (like the
// position changed).
void SetSize(const Size& new_size);
// Provides access to the underlying device in case you need it. Note: if
// you call Flush on this device the paint manager will get very confused,
// don't do this!
const Graphics2D& graphics() const { return graphics_; }
Graphics2D& graphics() { return graphics_; }
// Invalidate the entire plugin.
void Invalidate();
// Invalidate the given rect.
void InvalidateRect(const Rect& rect);
// The given rect should be scrolled by the given amounts.
void ScrollRect(const Rect& clip_rect, const Point& amount);
private:
// Disallow copy and assign (these are unimplemented).
PaintManager(const PaintManager&);
PaintManager& operator=(const PaintManager&);
// Makes sure there is a callback that will trigger a paint at a later time.
// This will be either a Flush callback telling us we're allowed to generate
// more data, or, if there's no flush callback pending, a manual call back
// to the message loop via ExecuteOnMainThread.
void EnsureCallbackPending();
// Does the client paint and executes a Flush if necessary.
void DoPaint();
// Callback for asynchronous completion of Flush.
void OnFlushComplete(int32_t);
// Callback for manual scheduling of paints when there is no flush callback
// pending.
void OnManualCallbackComplete(int32_t);
Instance* instance_;
// Non-owning pointer. See the constructor.
Client* client_;
bool is_always_opaque_;
CompletionCallbackFactory<PaintManager> callback_factory_;
// This graphics device will be is_null() if no graphics has been manually
// set yet.
Graphics2D graphics_;
PaintAggregator aggregator_;
// See comment for EnsureCallbackPending for more on how these work.
bool manual_callback_pending_;
bool flush_pending_;
};
} // namespace pp
#endif // PPAPI_CPP_PAINT_MANAGER_H_