-
Notifications
You must be signed in to change notification settings - Fork 289
[WIP] Add support for externally allocated images in the render backend #548
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,14 +6,14 @@ use app_units::Au; | |
use device::TextureId; | ||
use euclid::{Point2D, Matrix4D, Rect, Size2D}; | ||
use gpu_store::{GpuStore, GpuStoreAddress}; | ||
use internal_types::{device_pixel, DeviceRect, DeviceSize}; | ||
use internal_types::{SourceTexture, device_pixel, DeviceRect, DeviceSize}; | ||
use resource_cache::ResourceCache; | ||
use std::mem; | ||
use std::usize; | ||
use texture_cache::TextureCacheItem; | ||
use tiling::RenderTask; | ||
use util::TransformedRect; | ||
use webrender_traits::{AuxiliaryLists, ColorF, ImageKey, ImageRendering}; | ||
use webrender_traits::{AuxiliaryLists, ColorF, ImageKey, ExternalImageKey, ImageRendering}; | ||
use webrender_traits::{FontRenderMode, WebGLContextId}; | ||
use webrender_traits::{ClipRegion, FontKey, ItemRange, ComplexClipRegion, GlyphKey}; | ||
|
||
|
@@ -96,7 +96,7 @@ pub enum ImagePrimitiveKind { | |
#[derive(Debug)] | ||
pub struct ImagePrimitiveCpu { | ||
pub kind: ImagePrimitiveKind, | ||
pub color_texture_id: TextureId, | ||
pub color_texture_id: SourceTexture, | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
|
@@ -346,6 +346,9 @@ pub struct PrimitiveStore { | |
pub cpu_gradients: Vec<GradientPrimitiveCpu>, | ||
pub cpu_metadata: Vec<PrimitiveMetadata>, | ||
pub cpu_borders: Vec<BorderPrimitiveCpu>, | ||
// the indices witihin gpu_data_32 of the image primitives to be resolved by | ||
// the renderer instead of the render backend. | ||
pub deferred_image_primitives: Vec<(ExternalImageKey, GpuStoreAddress)>, | ||
|
||
// Gets uploaded directly to GPU via vertex texture | ||
pub gpu_geometry: GpuStore<PrimitiveGeometry>, | ||
|
@@ -375,6 +378,7 @@ impl PrimitiveStore { | |
gpu_data128: GpuStore::new(), | ||
device_pixel_ratio: device_pixel_ratio, | ||
prims_to_resolve: Vec::new(), | ||
deferred_image_primitives: Vec::new(), | ||
} | ||
} | ||
|
||
|
@@ -610,22 +614,27 @@ impl PrimitiveStore { | |
} | ||
PrimitiveKind::Image => { | ||
let image_cpu = &mut self.cpu_images[metadata.cpu_prim_index.0]; | ||
let image_gpu: &mut ImagePrimitiveGpu = unsafe { | ||
mem::transmute(self.gpu_data32.get_mut(metadata.gpu_prim_index)) | ||
}; | ||
|
||
let cache_item = match image_cpu.kind { | ||
ImagePrimitiveKind::Image(image_key, image_rendering, _) => { | ||
resource_cache.get_image(image_key, image_rendering) | ||
} | ||
ImagePrimitiveKind::WebGL(context_id) => { | ||
resource_cache.get_webgl_texture(&context_id) | ||
} | ||
}; | ||
if let Some(key) = image_cpu.color_texture_id.to_external() { | ||
// If the image primitive uses externally allocated textures, | ||
// we resolve it on the renderer. | ||
self.deferred_image_primitives.push((key, metadata.gpu_prim_index)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you ever force the primitive to appear in the |
||
} else { | ||
let image_gpu: &mut ImagePrimitiveGpu = unsafe { | ||
mem::transmute(self.gpu_data32.get_mut(metadata.gpu_prim_index)) | ||
}; | ||
let cache_item = match image_cpu.kind { | ||
ImagePrimitiveKind::Image(image_key, image_rendering, _) => { | ||
resource_cache.get_image(image_key, image_rendering) | ||
} | ||
ImagePrimitiveKind::WebGL(context_id) => { | ||
resource_cache.get_webgl_texture(&context_id) | ||
} | ||
}; | ||
|
||
image_cpu.color_texture_id = cache_item.texture_id; | ||
image_gpu.uv0 = cache_item.uv0; | ||
image_gpu.uv1 = cache_item.uv1; | ||
image_cpu.color_texture_id = SourceTexture::Id(cache_item.texture_id); | ||
image_gpu.uv0 = cache_item.uv0; | ||
image_gpu.uv1 = cache_item.uv1; | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -825,21 +834,23 @@ impl PrimitiveStore { | |
PrimitiveKind::Image => { | ||
let image_cpu = &mut self.cpu_images[metadata.cpu_prim_index.0]; | ||
|
||
prim_needs_resolve = true; | ||
match image_cpu.kind { | ||
ImagePrimitiveKind::Image(image_key, image_rendering, tile_spacing) => { | ||
resource_cache.request_image(image_key, image_rendering); | ||
|
||
// TODO(gw): This doesn't actually need to be calculated each frame. | ||
// It's cheap enough that it's not worth introducing a cache for images | ||
// right now, but if we introduce a cache for images for some other | ||
// reason then we might as well cache this with it. | ||
let image_properties = resource_cache.get_image_properties(image_key); | ||
metadata.is_opaque = image_properties.is_opaque && | ||
tile_spacing.width == 0.0 && | ||
tile_spacing.height == 0.0; | ||
if !image_cpu.color_texture_id.is_external() { | ||
prim_needs_resolve = true; | ||
match image_cpu.kind { | ||
ImagePrimitiveKind::Image(image_key, image_rendering, tile_spacing) => { | ||
resource_cache.request_image(image_key, image_rendering); | ||
|
||
// TODO(gw): This doesn't actually need to be calculated each frame. | ||
// It's cheap enough that it's not worth introducing a cache for images | ||
// right now, but if we introduce a cache for images for some other | ||
// reason then we might as well cache this with it. | ||
let image_properties = resource_cache.get_image_properties(image_key); | ||
metadata.is_opaque = image_properties.is_opaque && | ||
tile_spacing.width == 0.0 && | ||
tile_spacing.height == 0.0; | ||
} | ||
ImagePrimitiveKind::WebGL(..) => {} | ||
} | ||
ImagePrimitiveKind::WebGL(..) => {} | ||
} | ||
} | ||
PrimitiveKind::Gradient => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,8 +18,9 @@ use fnv::FnvHasher; | |
use internal_types::{RendererFrame, ResultMsg, TextureUpdateOp}; | ||
use internal_types::{TextureUpdateDetails, TextureUpdateList, PackedVertex, RenderTargetMode}; | ||
use internal_types::{ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE, DevicePoint}; | ||
use internal_types::{BatchTextures, TextureSampler, GLContextHandleWrapper}; | ||
use internal_types::{SourceTexture, BatchTextures, TextureSampler, GLContextHandleWrapper}; | ||
use ipc_channel::ipc; | ||
use prim_store::{ImagePrimitiveGpu}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this is a red flag for me. Renderer shouldn't need to know anything about the primitive store, at least directly. |
||
use profiler::{Profiler, BackendProfileCounters}; | ||
use profiler::{GpuProfileTag, RendererProfileTimers, RendererProfileCounters}; | ||
use render_backend::RenderBackend; | ||
|
@@ -951,9 +952,11 @@ impl Renderer { | |
self.device.bind_vao(self.quad_vao_id); | ||
|
||
for i in 0..textures.colors.len() { | ||
self.device.bind_texture(TextureSampler::color(i), textures.colors[i]); | ||
let color_id = self.resolve_texture_id(textures.colors[i]); | ||
self.device.bind_texture(TextureSampler::color(i), color_id); | ||
} | ||
self.device.bind_texture(TextureSampler::Mask, textures.mask); | ||
let mask_id = self.resolve_texture_id(textures.mask); | ||
self.device.bind_texture(TextureSampler::Mask, mask_id); | ||
|
||
for chunk in ubo_data.chunks(max_prim_items) { | ||
let ubo = self.device.create_ubo(&chunk, UBO_BIND_DATA); | ||
|
@@ -967,6 +970,30 @@ impl Renderer { | |
} | ||
} | ||
|
||
fn resolve_texture_id(&self, texture: SourceTexture) -> TextureId { | ||
match texture { | ||
SourceTexture::Id(id) => { id } | ||
SourceTexture::External(_key) => { | ||
//TODO[nical] | ||
unimplemented!(); | ||
} | ||
} | ||
} | ||
|
||
fn resolve_external_image_data(&self, frame: &mut Frame) { | ||
for &(key, prim_index) in &frame.deferred_image_primitives[..] { | ||
let image_gpu: &mut ImagePrimitiveGpu = unsafe { | ||
mem::transmute(frame.gpu_data32.get_mut(prim_index.0 as usize)) | ||
}; | ||
|
||
// TODO: fetch the external UV and and texture id using a callback API | ||
// or some such, and patch up the image_gpu. | ||
|
||
// image_gpu.uv0 = | ||
// image_gpu.uv1 = | ||
} | ||
} | ||
|
||
fn draw_target(&mut self, | ||
render_target: Option<(TextureId, i32)>, | ||
target: &RenderTarget, | ||
|
@@ -1285,6 +1312,8 @@ impl Renderer { | |
None); | ||
} | ||
|
||
self.resolve_external_image_data(frame); | ||
|
||
self.layer_texture.init(&mut self.device, &mut frame.layer_texture_data); | ||
self.render_task_texture.init(&mut self.device, &mut frame.render_task_data); | ||
self.data16_texture.init(&mut self.device, &mut frame.gpu_data16); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to have
primitives
in the name, since technically an external texture can be a part of anything, not necessarily it's ownImage
type primitive. Perhaps,external_images
?