mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-21 14:40:49 +01:00
Merge revision 743 changes:
- Optimize the cefclient off-screen rendering example (issue #697). git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/963@744 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
4292533524
commit
90472b1155
@ -14,82 +14,21 @@
|
||||
#error Platform is not supported.
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
#ifndef GL_BGR
|
||||
#define GL_BGR 0x80E0
|
||||
#endif
|
||||
#ifndef GL_BGRA
|
||||
#define GL_BGRA 0x80E1
|
||||
#endif
|
||||
#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
|
||||
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
|
||||
#endif
|
||||
|
||||
// Convert from BGRA to RGBA format and from upper-left to lower-left origin.
|
||||
void ConvertToRGBA(const unsigned char* src, unsigned char* dst,
|
||||
int width, int height) {
|
||||
int sp = 0, dp = (height-1) * width * 4;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++, dp += 4, sp += 4) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
dst[dp+3] = src[sp+3]; // A
|
||||
}
|
||||
dp -= width * 8;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertToRGBARect(const CefRect& clipRect,
|
||||
const unsigned char* src, unsigned char* dst,
|
||||
int width, int height) {
|
||||
int sp = 0, dp = (height-1) * width * 4;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++, dp += 4, sp += 4) {
|
||||
if ((clipRect.x <= j) && (clipRect.x + clipRect.width > j) &&
|
||||
(clipRect.y <= i) && (clipRect.y + clipRect.height > i)) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
dst[dp+3] = src[sp+3]; // A
|
||||
}
|
||||
}
|
||||
dp -= width * 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert from BGRA to RGB format and from upper-left to lower-left origin.
|
||||
void ConvertToRGB(const unsigned char* src, unsigned char* dst,
|
||||
int width, int height) {
|
||||
int sp = 0, dp = (height-1) * width * 3;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++, dp += 3, sp += 4) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
}
|
||||
dp -= width * 6;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertToRGBRect(const CefRect& clipRect,
|
||||
const unsigned char* src, unsigned char* dst,
|
||||
int width, int height) {
|
||||
int sp = 0, dp = (height-1) * width * 3;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++, dp += 3, sp += 4) {
|
||||
if ((clipRect.x <= j) && (clipRect.x + clipRect.width > j) &&
|
||||
(clipRect.y <= i) && (clipRect.y + clipRect.height > i)) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
}
|
||||
}
|
||||
dp -= width * 6;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ClientOSRenderer::ClientOSRenderer(bool transparent)
|
||||
: transparent_(transparent),
|
||||
initialized_(false),
|
||||
texture_id_(0),
|
||||
view_buffer_(NULL),
|
||||
view_buffer_size_(0),
|
||||
popup_buffer_(NULL),
|
||||
popup_buffer_size_(0),
|
||||
view_width_(0),
|
||||
view_height_(0),
|
||||
spin_x_(0),
|
||||
@ -104,104 +43,44 @@ void ClientOSRenderer::Initialize() {
|
||||
if (initialized_)
|
||||
return;
|
||||
|
||||
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Necessary for non-power-of-2 textures to render correctly.
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
if (transparent_) {
|
||||
// Alpha blending style. Texture values have premultiplied alpha.
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
// Create the texture.
|
||||
glGenTextures(1, &texture_id_);
|
||||
ASSERT(texture_id_ != 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id_);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
void ClientOSRenderer::Cleanup() {
|
||||
if (view_buffer_) {
|
||||
delete [] view_buffer_;
|
||||
view_buffer_ = NULL;
|
||||
view_buffer_size_ = 0;
|
||||
}
|
||||
if (popup_buffer_) {
|
||||
delete [] popup_buffer_;
|
||||
popup_buffer_ = NULL;
|
||||
popup_buffer_size_ = 0;
|
||||
}
|
||||
|
||||
if (texture_id_ != 0)
|
||||
glDeleteTextures(1, &texture_id_);
|
||||
}
|
||||
|
||||
void ClientOSRenderer::SetSize(int width, int height) {
|
||||
if (!initialized_)
|
||||
Initialize();
|
||||
|
||||
// Match GL units to screen coordinates.
|
||||
glViewport(0, 0, width, height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 0, width, height, 0.1, 100.0);
|
||||
|
||||
if (transparent_) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
GLuint new_texture_id = 0;
|
||||
|
||||
// Create a new texture.
|
||||
glGenTextures(1, &new_texture_id);
|
||||
ASSERT(new_texture_id != 0);
|
||||
glBindTexture(GL_TEXTURE_2D, new_texture_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
// Start with all white contents.
|
||||
{
|
||||
int size = width * height * (transparent_?4:3);
|
||||
unsigned char* buffer = new unsigned char[size];
|
||||
memset(buffer, 255, size);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
||||
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
delete [] buffer;
|
||||
}
|
||||
|
||||
if (texture_id_ != 0) {
|
||||
// Draw the existing view buffer to the new texture.
|
||||
DrawViewBuffer(width, height);
|
||||
|
||||
// Delete the old texture.
|
||||
glDeleteTextures(1, &texture_id_);
|
||||
}
|
||||
|
||||
texture_id_ = new_texture_id;
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (transparent_) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientOSRenderer::Render() {
|
||||
if (view_width_ == 0 || view_height_ == 0)
|
||||
return;
|
||||
|
||||
ASSERT(initialized_);
|
||||
|
||||
struct {
|
||||
float tu, tv;
|
||||
float x, y, z;
|
||||
} static vertices[] = {
|
||||
{0.0f, 0.0f, -1.0f, -1.0f, 0.0f},
|
||||
{1.0f, 0.0f, 1.0f, -1.0f, 0.0f},
|
||||
{1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
|
||||
{0.0f, 1.0f, -1.0f, 1.0f, 0.0f}
|
||||
{0.0f, 1.0f, -1.0f, -1.0f, 0.0f},
|
||||
{1.0f, 1.0f, 1.0f, -1.0f, 0.0f},
|
||||
{1.0f, 0.0f, 1.0f, 1.0f, 0.0f},
|
||||
{0.0f, 0.0f, -1.0f, 1.0f, 0.0f}
|
||||
};
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
@ -209,6 +88,12 @@ void ClientOSRenderer::Render() {
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// Match GL units to screen coordinates.
|
||||
glViewport(0, 0, view_width_, view_height_);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 0, view_width_, view_height_, 0.1, 100.0);
|
||||
|
||||
// Draw the background gradient.
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
glBegin(GL_QUADS);
|
||||
@ -222,10 +107,15 @@ void ClientOSRenderer::Render() {
|
||||
glPopAttrib();
|
||||
|
||||
// Rotate the view based on the mouse spin.
|
||||
glRotatef(-spin_x_, 1.0f, 0.0f, 0.0f);
|
||||
glRotatef(-spin_y_, 0.0f, 1.0f, 0.0f);
|
||||
if (spin_x_ != 0)
|
||||
glRotatef(-spin_x_, 1.0f, 0.0f, 0.0f);
|
||||
if (spin_y_ != 0)
|
||||
glRotatef(-spin_y_, 0.0f, 1.0f, 0.0f);
|
||||
|
||||
if (transparent_) {
|
||||
// Alpha blending style. Texture values have premultiplied alpha.
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
@ -253,34 +143,26 @@ void ClientOSRenderer::Render() {
|
||||
void ClientOSRenderer::OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
bool show) {
|
||||
if (!show) {
|
||||
// Clear the popup buffer.
|
||||
// Invalidate the previous popup rectangle so that it will be repainted.
|
||||
browser->Invalidate(popup_rect_);
|
||||
|
||||
// Clear the popup rectangle.
|
||||
popup_rect_.Set(0, 0, 0, 0);
|
||||
if (popup_buffer_) {
|
||||
delete [] popup_buffer_;
|
||||
popup_buffer_ = NULL;
|
||||
popup_buffer_size_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientOSRenderer::OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect) {
|
||||
if (rect.width > 0) {
|
||||
// Update the popup rectange. It should always be inside the view.
|
||||
ASSERT(rect.x + rect.width < view_width_ &&
|
||||
rect.y + rect.height < view_height_);
|
||||
if (rect.width > 0 && rect.height > 0)
|
||||
popup_rect_ = rect;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientOSRenderer::OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::PaintElementType type,
|
||||
const CefRenderHandler::RectList& dirtyRects,
|
||||
const void* buffer) {
|
||||
ASSERT(initialized_);
|
||||
|
||||
// Retrieve the current size of the browser view.
|
||||
browser->GetSize(type, view_width_, view_height_);
|
||||
if (!initialized_)
|
||||
Initialize();
|
||||
|
||||
if (transparent_) {
|
||||
// Enable alpha blending.
|
||||
@ -294,46 +176,59 @@ void ClientOSRenderer::OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id_);
|
||||
|
||||
if (type == PET_VIEW) {
|
||||
SetBufferSize(view_width_, view_height_, true);
|
||||
int old_width = view_width_;
|
||||
int old_height = view_height_;
|
||||
|
||||
// Paint the view.
|
||||
if (transparent_) {
|
||||
CefRenderHandler::RectList::const_iterator i = dirtyRects.begin();
|
||||
for (; i != dirtyRects.end(); ++i) {
|
||||
ConvertToRGBARect(*i, (unsigned char*)buffer, view_buffer_,
|
||||
view_width_, view_height_);
|
||||
}
|
||||
// Retrieve the current size of the browser view.
|
||||
browser->GetSize(type, view_width_, view_height_);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, view_width_);
|
||||
|
||||
if (old_width != view_width_ || old_height != view_height_) {
|
||||
// Update/resize the whole texture.
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width_, view_height_, 0,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
|
||||
} else {
|
||||
// Update just the dirty rectangles.
|
||||
CefRenderHandler::RectList::const_iterator i = dirtyRects.begin();
|
||||
for (; i != dirtyRects.end(); ++i) {
|
||||
ConvertToRGBRect(*i, (unsigned char*)buffer, view_buffer_,
|
||||
view_width_, view_height_);
|
||||
const CefRect& rect = *i;
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x);
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width,
|
||||
rect.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
buffer);
|
||||
}
|
||||
}
|
||||
} else if (type == PET_POPUP && popup_rect_.width > 0 &&
|
||||
popup_rect_.height > 0) {
|
||||
int skip_pixels = 0, x = popup_rect_.x;
|
||||
int skip_rows = 0, y = popup_rect_.y;
|
||||
int width = popup_rect_.width;
|
||||
int height = popup_rect_.height;
|
||||
|
||||
// Update the whole texture. This is done for simplicity instead of
|
||||
// updating just the dirty region.
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, view_width_, view_height_,
|
||||
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, view_buffer_);
|
||||
}
|
||||
|
||||
if (popup_rect_.width > 0) {
|
||||
if (type == PET_POPUP) {
|
||||
// Paint the popup.
|
||||
if (transparent_)
|
||||
SetRGBA(buffer, popup_rect_.width, popup_rect_.height, false);
|
||||
else
|
||||
SetRGB(buffer, popup_rect_.width, popup_rect_.height, false);
|
||||
// Adjust the popup to fit inside the view.
|
||||
if (x < 0) {
|
||||
skip_pixels = -x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (popup_buffer_) {
|
||||
// Update the popup region.
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, popup_rect_.x,
|
||||
view_height_ - popup_rect_.y - popup_rect_.height,
|
||||
popup_rect_.width, popup_rect_.height,
|
||||
transparent_?GL_RGBA:GL_RGB,
|
||||
GL_UNSIGNED_BYTE, popup_buffer_);
|
||||
if (y < 0) {
|
||||
skip_rows = -y;
|
||||
y = 0;
|
||||
}
|
||||
if (x + width > view_width_)
|
||||
width -= x + width - view_width_;
|
||||
if (y + height > view_height_)
|
||||
height -= y + height - view_height_;
|
||||
|
||||
// Update the popup rectangle.
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, popup_rect_.width);
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_BGRA,
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
|
||||
}
|
||||
|
||||
// Disable 2D textures.
|
||||
@ -354,79 +249,3 @@ void ClientOSRenderer::IncrementSpin(float spinDX, float spinDY) {
|
||||
spin_x_ -= spinDX;
|
||||
spin_y_ -= spinDY;
|
||||
}
|
||||
|
||||
bool ClientOSRenderer::GetPixelValue(int x, int y, unsigned char& r,
|
||||
unsigned char& g, unsigned char& b,
|
||||
unsigned char& a) {
|
||||
if (!view_buffer_)
|
||||
return false;
|
||||
|
||||
ASSERT(x >= 0 && x < view_width_);
|
||||
ASSERT(y >= 0 && y < view_height_);
|
||||
|
||||
int pixel_bytes = transparent_ ? 4 : 3;
|
||||
int y_flipped = view_height_ - y;
|
||||
int index = (view_width_ * y_flipped * pixel_bytes) + (x * pixel_bytes);
|
||||
|
||||
r = view_buffer_[index];
|
||||
g = view_buffer_[index+1];
|
||||
b = view_buffer_[index+2];
|
||||
if (transparent_)
|
||||
a = view_buffer_[index+3];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientOSRenderer::SetBufferSize(int width, int height, bool view) {
|
||||
int dst_size = width * height * (transparent_?4:3);
|
||||
|
||||
// Allocate a new buffer if necesary.
|
||||
if (view) {
|
||||
if (dst_size > view_buffer_size_) {
|
||||
if (view_buffer_)
|
||||
delete [] view_buffer_;
|
||||
view_buffer_ = new unsigned char[dst_size];
|
||||
view_buffer_size_ = dst_size;
|
||||
}
|
||||
} else {
|
||||
if (dst_size > popup_buffer_size_) {
|
||||
if (popup_buffer_)
|
||||
delete [] popup_buffer_;
|
||||
popup_buffer_ = new unsigned char[dst_size];
|
||||
popup_buffer_size_ = dst_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the contents of the RGBA buffer.
|
||||
void ClientOSRenderer::SetRGBA(const void* src, int width, int height,
|
||||
bool view) {
|
||||
SetBufferSize(width, height, view);
|
||||
ConvertToRGBA((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
|
||||
height);
|
||||
}
|
||||
|
||||
// Set the contents of the RGB buffer.
|
||||
void ClientOSRenderer::SetRGB(const void* src, int width, int height,
|
||||
bool view) {
|
||||
SetBufferSize(width, height, view);
|
||||
ConvertToRGB((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
|
||||
height);
|
||||
}
|
||||
|
||||
void ClientOSRenderer::DrawViewBuffer(int max_width, int max_height) {
|
||||
if (max_width < view_width_ || max_height < view_height_) {
|
||||
// The requested max size is smaller than the current view buffer.
|
||||
int width = std::min(max_width, view_width_);
|
||||
int height = std::min(max_height, view_height_);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, view_width_);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
|
||||
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE,
|
||||
view_buffer_);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
} else {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, view_width_, view_height_,
|
||||
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, view_buffer_);
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,6 @@ class ClientOSRenderer {
|
||||
// Clean up the OpenGL environment.
|
||||
void Cleanup();
|
||||
|
||||
// Set the size of the viewport.
|
||||
void SetSize(int width, int height);
|
||||
|
||||
// Render to the screen.
|
||||
void Render();
|
||||
|
||||
@ -39,29 +36,18 @@ class ClientOSRenderer {
|
||||
void SetSpin(float spinX, float spinY);
|
||||
void IncrementSpin(float spinDX, float spinDY);
|
||||
|
||||
// Retrieve the pixel value from the view buffer. |x| and |y| are relative to
|
||||
// the upper-left corner of the view.
|
||||
bool GetPixelValue(int x, int y, unsigned char& r, unsigned char& g,
|
||||
unsigned char& b, unsigned char& a);
|
||||
|
||||
bool IsTransparent() { return transparent_; }
|
||||
|
||||
int GetViewWidth() { return view_width_; }
|
||||
int GetViewHeight() { return view_height_; }
|
||||
|
||||
private:
|
||||
void SetBufferSize(int width, int height, bool view);
|
||||
void SetRGBA(const void* src, int width, int height, bool view);
|
||||
void SetRGB(const void* src, int width, int height, bool view);
|
||||
void DrawViewBuffer(int max_width, int max_height);
|
||||
|
||||
bool transparent_;
|
||||
bool initialized_;
|
||||
unsigned int texture_id_;
|
||||
unsigned char* view_buffer_;
|
||||
int view_buffer_size_;
|
||||
unsigned char* popup_buffer_;
|
||||
int popup_buffer_size_;
|
||||
CefRect popup_rect_;
|
||||
int view_width_;
|
||||
int view_height_;
|
||||
CefRect popup_rect_;
|
||||
float spin_x_;
|
||||
float spin_y_;
|
||||
};
|
||||
|
@ -58,7 +58,8 @@ class ClientOSRHandler : public CefClient,
|
||||
public CefRenderHandler {
|
||||
public:
|
||||
explicit ClientOSRHandler(ClientPlugin* plugin)
|
||||
: plugin_(plugin) {
|
||||
: plugin_(plugin),
|
||||
want_pixel_value_(false) {
|
||||
}
|
||||
~ClientOSRHandler() {
|
||||
}
|
||||
@ -68,6 +69,21 @@ class ClientOSRHandler : public CefClient,
|
||||
plugin_ = NULL;
|
||||
}
|
||||
|
||||
// Retrieve the pixel value at the requested coordinate the next time that
|
||||
// the view is painted.
|
||||
void WantPixelValue(int x, int y) {
|
||||
if (!want_pixel_value_) {
|
||||
want_pixel_value_ = true;
|
||||
|
||||
// Trigger a call to OnPaint.
|
||||
if (g_offscreenBrowser.get())
|
||||
g_offscreenBrowser->Invalidate(CefRect(0,0,1,1));
|
||||
}
|
||||
|
||||
coord_x_ = x;
|
||||
coord_y_ = y;
|
||||
}
|
||||
|
||||
// CefClient methods
|
||||
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
|
||||
return this;
|
||||
@ -274,6 +290,42 @@ class ClientOSRHandler : public CefClient,
|
||||
|
||||
wglMakeCurrent(plugin_->hDC, plugin_->hRC);
|
||||
plugin_->renderer.OnPaint(browser, type, dirtyRects, buffer);
|
||||
plugin_->renderer.Render();
|
||||
|
||||
SwapBuffers(plugin_->hDC);
|
||||
|
||||
if (type == PET_VIEW && want_pixel_value_) {
|
||||
// Retrieve the pixel value at the requested coordinate.
|
||||
int width = plugin_->renderer.GetViewWidth();
|
||||
int height = plugin_->renderer.GetViewHeight();
|
||||
|
||||
if(coord_x_ >= 0 && coord_x_ < width &&
|
||||
coord_y_ >= 0 && coord_y_ < height) {
|
||||
bool transparent = plugin_->renderer.IsTransparent();
|
||||
|
||||
int index = (width * coord_y_ * 4) + (coord_x_ * 4);
|
||||
const unsigned char *pBuf = static_cast<const unsigned char*>(buffer);
|
||||
unsigned char r, g, b, a;
|
||||
|
||||
b = pBuf[index];
|
||||
g = pBuf[index+1];
|
||||
r = pBuf[index+2];
|
||||
if (transparent)
|
||||
a = pBuf[index+3];
|
||||
|
||||
std::stringstream ss;
|
||||
ss << coord_x_ << "," << coord_y_ << " = R:" << static_cast<int>(r)
|
||||
<< " G:" << static_cast<int>(g) << " B:" << static_cast<int>(b);
|
||||
if (transparent)
|
||||
ss << " A:" << static_cast<int>(a);
|
||||
|
||||
std::string js =
|
||||
"document.getElementById('pixel').innerText = '" + ss.str() + "';";
|
||||
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(js, "", 0);
|
||||
}
|
||||
|
||||
want_pixel_value_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
|
||||
@ -302,6 +354,11 @@ class ClientOSRHandler : public CefClient,
|
||||
|
||||
ClientPlugin* plugin_;
|
||||
|
||||
// Used for retrieving the pixel value.
|
||||
bool want_pixel_value_;
|
||||
int coord_x_;
|
||||
int coord_y_;
|
||||
|
||||
// Include the default reference counting implementation.
|
||||
IMPLEMENT_REFCOUNTING(ClientOSRPlugin);
|
||||
};
|
||||
@ -348,23 +405,10 @@ void DisableGL(ClientPlugin* plugin) {
|
||||
|
||||
// Size the GL view.
|
||||
void SizeGL(ClientPlugin* plugin, int width, int height) {
|
||||
wglMakeCurrent(plugin->hDC, plugin->hRC);
|
||||
|
||||
plugin->renderer.SetSize(width, height);
|
||||
|
||||
if (g_offscreenBrowser.get())
|
||||
g_offscreenBrowser->SetSize(PET_VIEW, width, height);
|
||||
}
|
||||
|
||||
// Render the view contents.
|
||||
void RenderGL(ClientPlugin* plugin) {
|
||||
wglMakeCurrent(plugin->hDC, plugin->hRC);
|
||||
|
||||
plugin->renderer.Render();
|
||||
|
||||
SwapBuffers(plugin->hDC);
|
||||
}
|
||||
|
||||
NPError NPP_NewImpl(NPMIMEType plugin_type, NPP instance, uint16 mode,
|
||||
int16 argc, char* argn[], char* argv[],
|
||||
NPSavedData* saved) {
|
||||
@ -471,24 +515,12 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
reinterpret_cast<ClientPlugin*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
|
||||
|
||||
switch (message) {
|
||||
case WM_CREATE:
|
||||
// Start the timer that's used for redrawing.
|
||||
SetTimer(hWnd, 1, 20, NULL);
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
// Stop the timer that's used for redrawing.
|
||||
KillTimer(hWnd, 1);
|
||||
|
||||
// Explicitly close the offscreen browser and release the reference.
|
||||
g_offscreenBrowser->CloseBrowser();
|
||||
g_offscreenBrowser = NULL;
|
||||
return 0;
|
||||
|
||||
case WM_TIMER:
|
||||
RenderGL(plugin);
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
SetCapture(hWnd);
|
||||
@ -502,18 +534,9 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
// Retrieve the pixel value.
|
||||
int x = LOWORD(lParam);
|
||||
int y = HIWORD(lParam);
|
||||
unsigned char r, g, b, a;
|
||||
if (plugin->renderer.GetPixelValue(x, y, r, g, b, a)) {
|
||||
std::stringstream ss;
|
||||
ss << x << "," << y << " = R:" << static_cast<int>(r) << " G:" <<
|
||||
static_cast<int>(g) << " B:" << static_cast<int>(b);
|
||||
if (plugin->renderer.IsTransparent())
|
||||
ss << " A:" << static_cast<int>(a);
|
||||
|
||||
std::string js =
|
||||
"document.getElementById('pixel').innerText = '" + ss.str() + "';";
|
||||
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(js, "", 0);
|
||||
}
|
||||
CefRefPtr<ClientOSRHandler> handler =
|
||||
static_cast<ClientOSRHandler*>(g_offscreenBrowser->GetClient().get());
|
||||
handler->WantPixelValue(x, y);
|
||||
} else {
|
||||
if (g_offscreenBrowser.get()) {
|
||||
g_offscreenBrowser->SendMouseClickEvent(LOWORD(lParam), HIWORD(lParam),
|
||||
|
@ -254,18 +254,13 @@ class ClientOSRHandler : public CefClient,
|
||||
if (!view_)
|
||||
return;
|
||||
|
||||
[[view_ openGLContext] makeCurrentContext];
|
||||
NSOpenGLContext* context = [view_ openGLContext];
|
||||
[context makeCurrentContext];
|
||||
|
||||
view_->renderer_->OnPaint(browser, type, dirtyRects, buffer);
|
||||
view_->renderer_->Render();
|
||||
|
||||
// Notify the view to redraw the invalidated regions.
|
||||
{
|
||||
RectList::const_iterator i = dirtyRects.begin();
|
||||
for (; i != dirtyRects.end(); ++i) {
|
||||
NSRect rect = {{i->x, i->y}, {i->width, i->height}};
|
||||
[view_ setNeedsDisplayInRect:rect];
|
||||
}
|
||||
}
|
||||
[context flushBuffer];
|
||||
}
|
||||
|
||||
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
|
||||
@ -329,24 +324,11 @@ class ClientOSRHandler : public CefClient,
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)drawRect: (NSRect)bounds {
|
||||
NSOpenGLContext* context = [self openGLContext];
|
||||
[context makeCurrentContext];
|
||||
|
||||
renderer_->Render();
|
||||
|
||||
[context flushBuffer];
|
||||
}
|
||||
|
||||
- (void)setFrame:(NSRect)frameRect {
|
||||
[super setFrame:frameRect];
|
||||
|
||||
int width = frameRect.size.width;
|
||||
int height = frameRect.size.height;
|
||||
|
||||
[[self openGLContext] makeCurrentContext];
|
||||
|
||||
renderer_->SetSize(width, height);
|
||||
|
||||
if (browser_)
|
||||
browser_->SetSize(PET_VIEW, width, height);
|
||||
|
Loading…
x
Reference in New Issue
Block a user