зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1319170. Readback gpu directly into shared texture buffer for reftests. r=sotaro?
This commit is contained in:
Родитель
fd474dd602
Коммит
8225e91629
|
@ -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,
|
||||
unsafe {
|
||||
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);
|
||||
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);
|
||||
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
|
||||
|
|
Загрузка…
Ссылка в новой задаче