diff options
author | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-02 18:27:27 +0000 |
---|---|---|
committer | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-02 18:27:27 +0000 |
commit | 4297bea874c5620b111cd07bb06bd4e256e7e72b (patch) | |
tree | 0b934b27d12098ea9bf28c1ffaee7cbd71b86464 | |
parent | f8530b797730cca270210117a949a4a06be4009d (diff) | |
download | chromium_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.cc | 56 | ||||
-rw-r--r-- | ui/base/x/x11_util.h | 19 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface_linux.cc | 55 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface_win.cc | 50 | ||||
-rw-r--r-- | webkit/gpu/webgraphicscontext3d_in_process_impl.cc | 5 |
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()); } |