Bug 1319170. Readback gpu directly into shared texture buffer for reftests. r=sotaro?

This commit is contained in:
Mason Chang 2016-12-02 10:39:40 -08:00
Родитель fd474dd602
Коммит 8225e91629
3 изменённых файлов: 25 добавлений и 64 удалений

Просмотреть файл

@ -273,39 +273,21 @@ WebRenderBridgeParent::RecvDPGetSnapshot(PTextureParent* aTexture,
MOZ_ASSERT(bufferTexture->GetBufferDescriptor().type() == BufferDescriptor::TRGBDescriptor);
uint32_t stride = ImageDataSerializer::GetRGBStride(bufferTexture->GetBufferDescriptor().get_RGBDescriptor());
RefPtr<DrawTarget> target =
Factory::CreateDrawTargetForData(gfx::BackendType::SKIA,
bufferTexture->GetBuffer(),
bufferTexture->GetSize(),
stride,
bufferTexture->GetFormat());
MOZ_ASSERT(target);
if (!target) {
// We kill the content process rather than have it continue with an invalid
// snapshot, that may be too harsh and we could decide to return some sort
// of error to the child process and let it deal with it...
return IPC_FAIL_NO_REASON(this);
}
uint8_t* buffer = bufferTexture->GetBuffer();
IntSize size = bufferTexture->GetSize();
// We only support B8G8R8A8 for now.
MOZ_ASSERT(buffer);
MOZ_ASSERT(bufferTexture->GetFormat() == SurfaceFormat::B8G8R8A8);
uint32_t buffer_size = size.width * size.height * 4;
// Assert the size and stride of the buffer is what webrender expects
MOZ_ASSERT(size == aRect.Size());
MOZ_ASSERT((uint32_t)(size.width * 4) == stride);
MOZ_ASSERT(mWRState);
mGLContext->MakeCurrent();
uint32_t length = 0;
uint32_t capacity = 0;
const uint8_t* webrenderSnapshot = wr_readback_buffer(mWRWindowState, aRect.width, aRect.height, &length, &capacity);
// TODO: fixup for proper surface format.
RefPtr<DataSourceSurface> snapshot =
Factory::CreateWrappingDataSourceSurface(const_cast<uint8_t*>(webrenderSnapshot),
aRect.width * 4,
IntSize(aRect.width, aRect.height),
SurfaceFormat::B8G8R8A8);
Rect floatRect = Rect(0, 0, aRect.width, aRect.height);
target->DrawSurface(snapshot, floatRect, floatRect, DrawSurfaceOptions(), DrawOptions(1.0f, CompositionOp::OP_SOURCE));
target->Flush();
wr_free_buffer(webrenderSnapshot, length, capacity);
wr_readback_into_buffer(mWRWindowState, aRect.width, aRect.height, buffer, buffer_size);
return IPC_OK();
}

Просмотреть файл

@ -1,6 +1,5 @@
use std::ffi::CStr;
use std::{mem, slice};
use std::os::raw::c_uchar;
use std::os::raw::c_void;
use gleam::gl;
use euclid::{Size2D, Point2D, Rect, Matrix4D};
@ -603,33 +602,19 @@ fn force_sync_composite(window: &mut WrWindowState) {
}
#[no_mangle]
// read the function definition to make sure we free this memory correctly.
pub extern fn wr_readback_buffer(window: &mut WrWindowState, width: u32, height: u32,
out_length: *mut u32, out_capacity: *mut u32) -> *const c_uchar {
pub extern fn wr_readback_into_buffer(window: &mut WrWindowState, width: u32, height: u32,
dst_buffer: *mut u8, buffer_size: usize) {
assert!( unsafe { is_in_compositor_thread() });
force_sync_composite(window);
let mut pixels = gl::read_pixels(0, 0,
width as gl::GLsizei,
height as gl::GLsizei,
gl::BGRA,
gl::UNSIGNED_BYTE);
let pointer = pixels.as_mut_ptr();
unsafe {
*out_length = pixels.len() as u32;
*out_capacity = pixels.capacity() as u32;
mem::forget(pixels); // Ensure rust doesn't clean this up.
}
return pointer;
}
#[no_mangle]
pub extern fn wr_free_buffer(vec_ptr: *mut c_uchar, length: u32, capacity: u32)
{
assert!( unsafe { is_in_compositor_thread() });
// note that vec_ptr loses its const here because we're doing unsafe things.
unsafe {
let rebuilt = Vec::from_raw_parts(vec_ptr, length as usize, capacity as usize);
let mut slice = slice::from_raw_parts_mut(dst_buffer, buffer_size);
gl::read_pixels_into_buffer(0, 0,
width as gl::GLsizei,
height as gl::GLsizei,
gl::BGRA,
gl::UNSIGNED_BYTE,
slice);
}
}

Просмотреть файл

@ -173,17 +173,11 @@ wr_dp_push_iframe(wrstate* wrState, WRRect bounds, WRRect clip,
uint64_t layers_id)
WR_FUNC;
// The pointer returned by wr_readback_buffer must be freed by rust, not C.
// After using the data, it is the responsibility of the caller to free the memory
// by giving the pointer, out_length, out_capacity to wr_free_buffer.
// It is the responsibility of the caller to manage the dst_buffer memory
// and also free it at the proper time.
WR_INLINE const uint8_t*
wr_readback_buffer(wrwindowstate* wrWindow, uint32_t width, uint32_t height,
uint32_t* out_length, uint32_t* out_capacity)
WR_FUNC;
WR_INLINE void
wr_free_buffer(const uint8_t* pointer, uint32_t length, uint32_t capacity)
wr_readback_into_buffer(wrwindowstate* wrWindow, uint32_t width, uint32_t height,
uint8_t* dst_buffer, uint32_t buffer_length);
WR_FUNC;
WR_INLINE void