summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbacker@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-02 18:27:27 +0000
committerbacker@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-02 18:27:27 +0000
commit4297bea874c5620b111cd07bb06bd4e256e7e72b (patch)
tree0b934b27d12098ea9bf28c1ffaee7cbd71b86464
parentf8530b797730cca270210117a949a4a06be4009d (diff)
downloadchromium_src-4297bea874c5620b111cd07bb06bd4e256e7e72b.zip
chromium_src-4297bea874c5620b111cd07bb06bd4e256e7e72b.tar.gz
chromium_src-4297bea874c5620b111cd07bb06bd4e256e7e72b.tar.bz2
Enable GL_CHROMIUM_post_sub_buffer for osmesa
Small changes to WGC3DInProcessImpl to pass the extension up to WebKit. BUG=none TEST=with https://bugs.webkit.org/show_bug.cgi?id=67341 and --use-gl=osmesa Review URL: http://codereview.chromium.org/8772021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112738 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/base/x/x11_util.cc56
-rw-r--r--ui/base/x/x11_util.h19
-rw-r--r--ui/gfx/gl/gl_surface_linux.cc55
-rw-r--r--ui/gfx/gl/gl_surface_win.cc50
-rw-r--r--webkit/gpu/webgraphicscontext3d_in_process_impl.cc5
5 files changed, 165 insertions, 20 deletions
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index 53418bd..fed7764 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -584,8 +584,28 @@ XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) {
return picture;
}
-void PutARGBImage(Display* display, void* visual, int depth, XID pixmap,
- void* pixmap_gc, const uint8* data, int width, int height) {
+void PutARGBImage(Display* display,
+ void* visual, int depth,
+ XID pixmap, void* pixmap_gc,
+ const uint8* data,
+ int width, int height) {
+ PutARGBImage(display,
+ visual, depth,
+ pixmap, pixmap_gc,
+ data, width, height,
+ 0, 0, // src_x, src_y
+ 0, 0, // dst_x, dst_y
+ width, height);
+}
+
+void PutARGBImage(Display* display,
+ void* visual, int depth,
+ XID pixmap, void* pixmap_gc,
+ const uint8* data,
+ int data_width, int data_height,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ int copy_width, int copy_height) {
// TODO(scherkus): potential performance impact... consider passing in as a
// parameter.
int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth);
@@ -593,15 +613,15 @@ void PutARGBImage(Display* display, void* visual, int depth, XID pixmap,
XImage image;
memset(&image, 0, sizeof(image));
- image.width = width;
- image.height = height;
+ image.width = data_width;
+ image.height = data_height;
image.format = ZPixmap;
image.byte_order = LSBFirst;
image.bitmap_unit = 8;
image.bitmap_bit_order = LSBFirst;
image.depth = depth;
image.bits_per_pixel = pixmap_bpp;
- image.bytes_per_line = width * pixmap_bpp / 8;
+ image.bytes_per_line = data_width * pixmap_bpp / 8;
if (pixmap_bpp == 32) {
image.red_mask = 0xff0000;
@@ -616,8 +636,8 @@ void PutARGBImage(Display* display, void* visual, int depth, XID pixmap,
image.blue_mask == vis->blue_mask) {
image.data = const_cast<char*>(reinterpret_cast<const char*>(data));
XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
- 0, 0 /* source x, y */, 0, 0 /* dest x, y */,
- width, height);
+ src_x, src_y, dst_x, dst_y,
+ copy_width, copy_height);
} else {
// Otherwise, we need to shuffle the colors around. Assume red and blue
// need to be swapped.
@@ -625,13 +645,14 @@ void PutARGBImage(Display* display, void* visual, int depth, XID pixmap,
// It's possible to use some fancy SSE tricks here, but since this is the
// slow path anyway, we do it slowly.
- uint8_t* bitmap32 = static_cast<uint8_t*>(malloc(4 * width * height));
+ uint8_t* bitmap32 =
+ static_cast<uint8_t*>(malloc(4 * data_width * data_height));
if (!bitmap32)
return;
uint8_t* const orig_bitmap32 = bitmap32;
const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
+ for (int y = 0; y < data_height; ++y) {
+ for (int x = 0; x < data_width; ++x) {
const uint32_t pixel = *(bitmap_in++);
bitmap32[0] = (pixel >> 16) & 0xff; // Red
bitmap32[1] = (pixel >> 8) & 0xff; // Green
@@ -642,21 +663,22 @@ void PutARGBImage(Display* display, void* visual, int depth, XID pixmap,
}
image.data = reinterpret_cast<char*>(orig_bitmap32);
XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
- 0, 0 /* source x, y */, 0, 0 /* dest x, y */,
- width, height);
+ src_x, src_y, dst_x, dst_y,
+ copy_width, copy_height);
free(orig_bitmap32);
}
} else if (pixmap_bpp == 16) {
// Some folks have VNC setups which still use 16-bit visuals and VNC
// doesn't include Xrender.
- uint16_t* bitmap16 = static_cast<uint16_t*>(malloc(2 * width * height));
+ uint16_t* bitmap16 =
+ static_cast<uint16_t*>(malloc(2 * data_width * data_height));
if (!bitmap16)
return;
uint16_t* const orig_bitmap16 = bitmap16;
const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
+ for (int y = 0; y < data_height; ++y) {
+ for (int x = 0; x < data_width; ++x) {
const uint32_t pixel = *(bitmap_in++);
uint16_t out_pixel = ((pixel >> 8) & 0xf800) |
((pixel >> 5) & 0x07e0) |
@@ -671,8 +693,8 @@ void PutARGBImage(Display* display, void* visual, int depth, XID pixmap,
image.blue_mask = 0x001f;
XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
- 0, 0 /* source x, y */, 0, 0 /* dest x, y */,
- width, height);
+ src_x, src_y, dst_x, dst_y,
+ copy_width, copy_height);
free(orig_bitmap16);
} else {
LOG(FATAL) << "Sorry, we don't support your visual depth without "
diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h
index 4f2fe33..29fba7c 100644
--- a/ui/base/x/x11_util.h
+++ b/ui/base/x/x11_util.h
@@ -178,10 +178,25 @@ UI_EXPORT XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap);
// server side visual depth as needed. Destination is assumed to be the same
// dimensions as |data| or larger. |data| is also assumed to be in row order
// with each line being exactly |width| * 4 bytes long.
-UI_EXPORT void PutARGBImage(Display* display, void* visual, int depth,
- XID pixmap, void* pixmap_gc, const uint8* data,
+UI_EXPORT void PutARGBImage(Display* display,
+ void* visual, int depth,
+ XID pixmap, void* pixmap_gc,
+ const uint8* data,
int width, int height);
+// Same as above only more general:
+// - |data_width| and |data_height| refer to the data image
+// - |src_x|, |src_y|, |copy_width| and |copy_height| define source region
+// - |dst_x|, |dst_y|, |copy_width| and |copy_height| define destination region
+UI_EXPORT void PutARGBImage(Display* display,
+ void* visual, int depth,
+ XID pixmap, void* pixmap_gc,
+ const uint8* data,
+ int data_width, int data_height,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ int copy_width, int copy_height);
+
void FreePicture(Display* display, XID picture);
void FreePixmap(Display* display, XID pixmap);
diff --git a/ui/gfx/gl/gl_surface_linux.cc b/ui/gfx/gl/gl_surface_linux.cc
index cf067c2..b152b46 100644
--- a/ui/gfx/gl/gl_surface_linux.cc
+++ b/ui/gfx/gl/gl_surface_linux.cc
@@ -42,6 +42,8 @@ class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa {
virtual void Destroy();
virtual bool IsOffscreen();
virtual bool SwapBuffers();
+ virtual std::string GetExtensions();
+ virtual bool PostSubBuffer(int x, int y, int width, int height);
private:
bool UpdateSize();
@@ -194,6 +196,59 @@ bool NativeViewGLSurfaceOSMesa::SwapBuffers() {
return true;
}
+std::string NativeViewGLSurfaceOSMesa::GetExtensions() {
+ std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions();
+ extensions += extensions.empty() ? "" : " ";
+ extensions += "GL_CHROMIUM_post_sub_buffer";
+ return extensions;
+}
+
+bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
+ int x, int y, int width, int height) {
+ // Update the size before blitting so that the blit size is exactly the same
+ // as the window.
+ if (!UpdateSize()) {
+ LOG(ERROR) << "Failed to update size of GLContextOSMesa.";
+ return false;
+ }
+
+ gfx::Size size = GetSize();
+
+ // Move (0,0) from lower-left to upper-left
+ y = size.height() - y - height;
+
+ XWindowAttributes attributes;
+ if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) {
+ LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
+ return false;
+ }
+
+ // Copy the frame into the pixmap.
+ ui::PutARGBImage(g_osmesa_display,
+ attributes.visual,
+ attributes.depth,
+ pixmap_,
+ pixmap_graphics_context_,
+ static_cast<const uint8*>(GetHandle()),
+ size.width(),
+ size.height(),
+ x, y,
+ x, y,
+ width,
+ height);
+
+ // Copy the pixmap to the window.
+ XCopyArea(g_osmesa_display,
+ pixmap_,
+ window_,
+ window_graphics_context_,
+ x, y,
+ width, height,
+ x, y);
+
+ return true;
+}
+
bool NativeViewGLSurfaceOSMesa::UpdateSize() {
// Get the window size.
XWindowAttributes attributes;
diff --git a/ui/gfx/gl/gl_surface_win.cc b/ui/gfx/gl/gl_surface_win.cc
index e6abf55..08b3396 100644
--- a/ui/gfx/gl/gl_surface_win.cc
+++ b/ui/gfx/gl/gl_surface_win.cc
@@ -30,6 +30,8 @@ class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa {
virtual void Destroy();
virtual bool IsOffscreen();
virtual bool SwapBuffers();
+ virtual std::string GetExtensions();
+ virtual bool PostSubBuffer(int x, int y, int width, int height);
private:
void UpdateSize();
@@ -134,6 +136,54 @@ bool NativeViewGLSurfaceOSMesa::SwapBuffers() {
return true;
}
+std::string NativeViewGLSurfaceOSMesa::GetExtensions() {
+ std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions();
+ extensions += extensions.empty() ? "" : " ";
+ extensions += "GL_CHROMIUM_post_sub_buffer";
+ return extensions;
+}
+
+bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
+ int x, int y, int width, int height) {
+ DCHECK(device_context_);
+
+ // Update the size before blitting so that the blit size is exactly the same
+ // as the window.
+ UpdateSize();
+
+ gfx::Size size = GetSize();
+
+ // Note: negating the height below causes GDI to treat the bitmap data as row
+ // 0 being at the top.
+ BITMAPV4HEADER info = { sizeof(BITMAPV4HEADER) };
+ info.bV4Width = size.width();
+ info.bV4Height = -size.height();
+ info.bV4Planes = 1;
+ info.bV4BitCount = 32;
+ info.bV4V4Compression = BI_BITFIELDS;
+ info.bV4RedMask = 0x000000FF;
+ info.bV4GreenMask = 0x0000FF00;
+ info.bV4BlueMask = 0x00FF0000;
+ info.bV4AlphaMask = 0xFF000000;
+
+ // Copy the back buffer to the window's device context. Do not check whether
+ // StretchDIBits succeeds or not. It will fail if the window has been
+ // destroyed but it is preferable to allow rendering to silently fail if the
+ // window is destroyed. This is because the primary application of this
+ // class of GLContext is for testing and we do not want every GL related ui /
+ // browser test to become flaky if there is a race condition between GL
+ // context destruction and window destruction.
+ StretchDIBits(device_context_,
+ x, size.height() - y - height, width, height,
+ x, y, width, height,
+ GetHandle(),
+ reinterpret_cast<BITMAPINFO*>(&info),
+ DIB_RGB_COLORS,
+ SRCCOPY);
+
+ return true;
+}
+
void NativeViewGLSurfaceOSMesa::UpdateSize() {
// Change back buffer size to that of window. If window handle is invalid, do
// not change the back buffer size.
diff --git a/webkit/gpu/webgraphicscontext3d_in_process_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_impl.cc
index 97e1c58..7ce072f 100644
--- a/webkit/gpu/webgraphicscontext3d_in_process_impl.cc
+++ b/webkit/gpu/webgraphicscontext3d_in_process_impl.cc
@@ -1254,8 +1254,9 @@ WebString WebGraphicsContext3DInProcessImpl::getShaderSource(WebGLId shader) {
WebString WebGraphicsContext3DInProcessImpl::getString(WGC3Denum name) {
makeContextCurrent();
- std::string result(reinterpret_cast<const char*>(glGetString(name)));
+ std::string result;
if (name == GL_EXTENSIONS) {
+ result = gl_context_->GetExtensions();
if (!is_gles2_) {
std::vector<std::string> split;
base::SplitString(result, ' ', &split);
@@ -1265,6 +1266,8 @@ WebString WebGraphicsContext3DInProcessImpl::getString(WGC3Denum name) {
result += " GL_EXT_texture_format_BGRA8888 GL_EXT_read_format_bgra";
}
}
+ } else {
+ result = reinterpret_cast<const char*>(glGetString(name));
}
return WebString::fromUTF8(result.c_str());
}