1 // Copyright 2015 The Gfx-rs Developers.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #![allow(missing_docs)]
16
17 use gl;
18 use core::{self as c, command, state as s};
19 use core::target::{ColorValue, Depth, Mirror, Rect, Stencil};
20 use core::texture::TextureCopyRegion;
21 use {Buffer, BufferElement, Program, FrameBuffer, Texture,
22 NewTexture, Resources, PipelineState, ResourceView, TargetView};
23
24
primitive_to_gl(primitive: c::Primitive) -> gl::types::GLenum25 fn primitive_to_gl(primitive: c::Primitive) -> gl::types::GLenum {
26 use core::Primitive::*;
27 match primitive {
28 PointList => gl::POINTS,
29 LineList => gl::LINES,
30 LineStrip => gl::LINE_STRIP,
31 TriangleList => gl::TRIANGLES,
32 TriangleStrip => gl::TRIANGLE_STRIP,
33 LineListAdjacency => gl::LINES_ADJACENCY,
34 LineStripAdjacency => gl::LINE_STRIP_ADJACENCY,
35 TriangleListAdjacency => gl::TRIANGLES_ADJACENCY,
36 TriangleStripAdjacency => gl::TRIANGLE_STRIP_ADJACENCY,
37 //TriangleFan => gl::TRIANGLE_FAN,
38 PatchList(_) => gl::PATCHES
39 }
40 }
41
42 pub type Access = gl::types::GLenum;
43
44 #[derive(Clone, Copy, Debug)]
45 pub struct RawOffset(pub *const gl::types::GLvoid);
46 unsafe impl Send for RawOffset {}
47
48 /// The place of some data in the data buffer.
49 #[derive(Clone, Copy, PartialEq, Debug)]
50 pub struct DataPointer {
51 offset: u32,
52 size: u32,
53 }
54
55 pub struct DataBuffer(Vec<u8>);
56 impl DataBuffer {
57 /// Create a new empty data buffer.
new() -> DataBuffer58 pub fn new() -> DataBuffer {
59 DataBuffer(Vec::new())
60 }
61 /// Copy a given vector slice into the buffer.
add(&mut self, data: &[u8]) -> DataPointer62 fn add(&mut self, data: &[u8]) -> DataPointer {
63 self.0.extend_from_slice(data);
64 DataPointer {
65 offset: (self.0.len() - data.len()) as u32,
66 size: data.len() as u32,
67 }
68 }
69 /// Return a reference to a stored data object.
get(&self, ptr: DataPointer) -> &[u8]70 pub fn get(&self, ptr: DataPointer) -> &[u8] {
71 &self.0[ptr.offset as usize..(ptr.offset + ptr.size) as usize]
72 }
73 }
74
75
76 /// Serialized device command.
77 #[derive(Clone, Debug)]
78 pub enum Command {
79 // states
80 BindProgram(Program),
81 BindConstantBuffer(c::pso::ConstantBufferParam<Resources>),
82 BindResourceView(c::pso::ResourceViewParam<Resources>),
83 BindUnorderedView(c::pso::UnorderedViewParam<Resources>),
84 BindSampler(c::pso::SamplerParam<Resources>, Option<gl::types::GLenum>),
85 BindPixelTargets(c::pso::PixelTargetSet<Resources>),
86 BindVao,
87 BindAttribute(c::AttributeSlot, Buffer, BufferElement),
88 UnbindAttribute(c::AttributeSlot),
89 BindIndex(Buffer),
90 BindFrameBuffer(Access, FrameBuffer),
91 BindUniform(c::shade::Location, c::shade::UniformValue),
92 SetDrawColorBuffers(c::ColorSlot),
93 SetRasterizer(s::Rasterizer),
94 SetViewport(Rect),
95 SetScissor(Option<Rect>),
96 SetDepthState(Option<s::Depth>),
97 SetStencilState(Option<s::Stencil>, (Stencil, Stencil), s::CullFace),
98 SetBlendState(c::ColorSlot, s::Color),
99 SetBlendColor(ColorValue),
100 SetPatches(c::PatchSize),
101 SetOutputMasks { color: bool, depth: bool, stencil: bool },
102 CopyBuffer(Buffer, Buffer,
103 gl::types::GLintptr, gl::types::GLintptr,
104 gl::types::GLsizeiptr),
105 CopyBufferToTexture(Buffer, gl::types::GLintptr,
106 TextureCopyRegion<Texture>),
107 CopyTextureToBuffer(TextureCopyRegion<NewTexture>,
108 Buffer, gl::types::GLintptr,
109 FrameBuffer),
110 CopyTextureToTexture(TextureCopyRegion<NewTexture>,
111 TextureCopyRegion<Texture>,
112 FrameBuffer),
113 // resource updates
114 UpdateBuffer(Buffer, DataPointer, usize),
115 UpdateTexture(TextureCopyRegion<Texture>, DataPointer),
116 GenerateMipmap(ResourceView),
117 // drawing
118 Clear(Option<command::ClearColor>, Option<Depth>, Option<Stencil>),
119 Draw(gl::types::GLenum, c::VertexCount, c::VertexCount, Option<command::InstanceParams>),
120 DrawIndexed(gl::types::GLenum,
121 gl::types::GLenum,
122 RawOffset,
123 c::VertexCount,
124 c::VertexCount,
125 Option<command::InstanceParams>),
126 _Blit(Rect, Rect, Mirror, usize),
127 }
128
generate_reset() -> Vec<Command>129 pub fn generate_reset() -> Vec<Command> {
130 let color = s::Color {
131 mask: s::ColorMask::all(),
132 blend: None,
133 };
134 vec![
135 Command::BindProgram(0),
136 Command::BindVao,
137 // Command::UnbindAttribute, //not needed, handled by the cache
138 Command::BindIndex(0),
139 Command::BindFrameBuffer(gl::FRAMEBUFFER, 0),
140 Command::SetRasterizer(s::Rasterizer {
141 front_face: s::FrontFace::CounterClockwise,
142 cull_face: s::CullFace::Back,
143 method: s::RasterMethod::Fill,
144 offset: None,
145 samples: None,
146 }),
147 Command::SetViewport(Rect {
148 x: 0,
149 y: 0,
150 w: 0,
151 h: 0,
152 }),
153 Command::SetScissor(None),
154 Command::SetDepthState(None),
155 Command::SetStencilState(None, (0, 0), s::CullFace::Nothing),
156 Command::SetBlendState(0, color),
157 Command::SetBlendState(1, color),
158 Command::SetBlendState(2, color),
159 Command::SetBlendState(3, color),
160 Command::SetBlendColor([0f32; 4]),
161 ]
162 }
163
164 struct Cache {
165 primitive: gl::types::GLenum,
166 index_type: c::IndexType,
167 current_vbs: Option<c::pso::VertexBufferSet<Resources>>,
168 attributes: [Option<BufferElement>; c::MAX_VERTEX_ATTRIBUTES],
169 resource_binds: [Option<gl::types::GLenum>; c::MAX_RESOURCE_VIEWS],
170 scissor: bool,
171 target_dim: (u16, u16, u16),
172 stencil: Option<s::Stencil>,
173 // blend: Option<s::Blend>,
174 cull_face: s::CullFace,
175 draw_mask: u32,
176
177 program: Program,
178 constant_buffer: Option<c::pso::ConstantBufferParam<Resources>>,
179 resource_view: Option<c::pso::ResourceViewParam<Resources>>,
180 scissor_test: Option<Rect>,
181 depth_state: Option<s::Depth>,
182 blend_state: Option<(c::ColorSlot, s::Color)>,
183 blend_color: Option<ColorValue>,
184 viewport: Option<Rect>,
185 rasterizer: Option<s::Rasterizer>,
186 framebuffer: Option<(Access, FrameBuffer)>,
187 index: Buffer,
188 }
189
190 impl Cache {
new() -> Cache191 pub fn new() -> Cache {
192 Cache {
193 primitive: 0,
194 index_type: c::IndexType::U16,
195 current_vbs: None,
196 attributes: [None; c::MAX_VERTEX_ATTRIBUTES],
197 resource_binds: [None; c::MAX_RESOURCE_VIEWS],
198 scissor: false,
199 target_dim: (0, 0, 0),
200 stencil: None,
201 cull_face: s::CullFace::Nothing,
202 // blend: None,
203 draw_mask: 0,
204
205 program: 0,
206 constant_buffer: None,
207 resource_view: None,
208 scissor_test: None,
209 depth_state: None,
210 blend_state: None,
211 blend_color: None,
212 viewport: None,
213 rasterizer: None,
214 framebuffer: None,
215 index: 0,
216 }
217 }
218
bind_program(&mut self, program: Program) -> Option<Command>219 fn bind_program(&mut self, program: Program) -> Option<Command> {
220 if program == self.program {
221 return None;
222 }
223 self.program = program;
224 Some(Command::BindProgram(program))
225 }
226
bind_constant_buffer(&mut self, constant_buffer: c::pso::ConstantBufferParam<Resources>) -> Option<Command>227 fn bind_constant_buffer(&mut self, constant_buffer: c::pso::ConstantBufferParam<Resources>) -> Option<Command> {
228 if self.constant_buffer == Some(constant_buffer) {
229 return None;
230 }
231 self.constant_buffer = Some(constant_buffer);
232 Some(Command::BindConstantBuffer(constant_buffer))
233 }
234
bind_resource_view(&mut self, resource_view: c::pso::ResourceViewParam<Resources>) -> Option<Command>235 fn bind_resource_view(&mut self, resource_view: c::pso::ResourceViewParam<Resources>) -> Option<Command> {
236 if self.resource_view == Some(resource_view) {
237 return None;
238 }
239 self.resource_view = Some(resource_view);
240 Some(Command::BindResourceView(resource_view))
241 }
242
bind_index(&mut self, buffer: Buffer, itype: c::IndexType) -> Option<Command>243 fn bind_index(&mut self, buffer: Buffer, itype: c::IndexType) -> Option<Command> {
244 if self.index == buffer && itype == self.index_type {
245 return None;
246 }
247 self.index_type = itype;
248 self.index = buffer;
249 Some(Command::BindIndex(buffer))
250 }
251
bind_framebuffer(&mut self, access: Access, fb: FrameBuffer) -> Option<Command>252 fn bind_framebuffer(&mut self, access: Access, fb: FrameBuffer) -> Option<Command> {
253 if self.framebuffer == Some((access, fb)) {
254 return None;
255 }
256 self.framebuffer = Some((access, fb));
257 Some(Command::BindFrameBuffer(access, fb))
258 }
259
set_rasterizer(&mut self, rasterizer: s::Rasterizer) -> Option<Command>260 fn set_rasterizer(&mut self, rasterizer: s::Rasterizer) -> Option<Command> {
261 if self.rasterizer == Some(rasterizer) {
262 return None;
263 }
264 self.rasterizer = Some(rasterizer);
265 Some(Command::SetRasterizer(rasterizer))
266 }
267
set_viewport(&mut self, rect: Rect) -> Option<Command>268 fn set_viewport(&mut self, rect: Rect) -> Option<Command> {
269 if self.viewport == Some(rect) {
270 return None;
271 }
272 self.viewport = Some(rect);
273 Some(Command::SetViewport(rect))
274 }
275
set_scissor(&mut self, rect: Option<Rect>) -> Option<Command>276 fn set_scissor(&mut self, rect: Option<Rect>) -> Option<Command> {
277 if self.scissor_test == rect {
278 return None;
279 }
280 self.scissor_test = rect;
281 Some(Command::SetScissor(rect))
282 }
set_depth_state(&mut self, depth: Option<s::Depth>) -> Option<Command>283 fn set_depth_state(&mut self, depth: Option<s::Depth>) -> Option<Command> {
284 if self.depth_state == depth {
285 return None;
286 }
287 self.depth_state = depth;
288 Some(Command::SetDepthState(depth))
289 }
set_stencil_state(&mut self, option_stencil: Option<s::Stencil>, stencils: (Stencil, Stencil), cullface: s:: CullFace) -> Option<Command>290 fn set_stencil_state(&mut self, option_stencil: Option<s::Stencil>, stencils: (Stencil, Stencil), cullface: s:: CullFace) -> Option<Command> {
291 // This is a little more complex 'cause if option_stencil
292 // is None the stencil state is disabled, it it's Some
293 // then it's enabled and parameters are set.
294 // That's actually bad because it makes it impossible
295 // to completely remove all redundant calls if the
296 // stencil is enabled;
297 // we'll be re-enabling it over and over.
298 // For now though, we just don't handle it.
299 Some(Command::SetStencilState(option_stencil, stencils, cullface))
300 }
set_blend_state(&mut self, color_slot: c::ColorSlot, color: s::Color) -> Option<Command>301 fn set_blend_state(&mut self, color_slot: c::ColorSlot, color: s::Color) -> Option<Command> {
302 if self.blend_state == Some((color_slot, color)) {
303 return None;
304 }
305 self.blend_state = Some((color_slot, color));
306 Some(Command::SetBlendState(color_slot, color))
307 }
set_blend_color(&mut self, color_value: ColorValue) -> Option<Command>308 fn set_blend_color(&mut self, color_value: ColorValue) -> Option<Command> {
309 if self.blend_color == Some(color_value) {
310 return None;
311 }
312 self.blend_color = Some(color_value);
313 Some(Command::SetBlendColor(color_value))
314 }
315 }
316
317 #[derive(Clone, Debug, Default)]
318 pub struct Workarounds {
319 // On some systems (OSX), the driver may still output something even if the shader does not,
320 // so we need to explicitly mask out the outputs according to the views being bound.
321 pub main_fbo_mask: bool,
322 }
323
324 /// A command buffer abstraction for OpenGL.
325 ///
326 /// Manages a list of commands that will be executed when submitted to a `Device`. Usually it is
327 /// best to use a `Encoder` to manage the command buffer which implements `From<CommandBuffer>`.
328 ///
329 /// If you want to display your rendered results to a framebuffer created externally, see the
330 /// `display_fb` field.
331 pub struct CommandBuffer {
332 pub buf: Vec<Command>,
333 pub data: DataBuffer,
334 fbo: FrameBuffer,
335 /// The framebuffer to use for rendering to the main targets (0 by default).
336 ///
337 /// Use this to set the framebuffer that will be used for the screen display targets created
338 /// with `create_main_targets_raw`. Usually you don't need to set this field directly unless
339 /// your OS doesn't provide a default framebuffer with name 0 and you have to render to a
340 /// different framebuffer object that can be made visible on the screen (iOS/tvOS need this).
341 ///
342 /// This framebuffer must exist and be configured correctly (with renderbuffer attachments,
343 /// etc.) so that rendering to it can occur immediately.
344 pub display_fb: FrameBuffer,
345 cache: Cache,
346 active_attribs: usize,
347 workarounds: Workarounds,
348 }
349
350 impl CommandBuffer {
new(fbo: FrameBuffer, workarounds: Workarounds) -> CommandBuffer351 pub fn new(fbo: FrameBuffer, workarounds: Workarounds) -> CommandBuffer {
352 CommandBuffer {
353 buf: Vec::new(),
354 data: DataBuffer::new(),
355 fbo,
356 display_fb: 0 as FrameBuffer,
357 cache: Cache::new(),
358 active_attribs: 0,
359 workarounds,
360 }
361 }
is_main_target(&self, tv: Option<TargetView>) -> bool362 fn is_main_target(&self, tv: Option<TargetView>) -> bool {
363 match tv {
364 Some(TargetView::Surface(0)) |
365 None => true,
366 Some(_) => false,
367 }
368 }
369 }
370
371 impl command::Buffer<Resources> for CommandBuffer {
reset(&mut self)372 fn reset(&mut self) {
373 self.buf.clear();
374 self.data.0.clear();
375 self.cache = Cache::new();
376 self.active_attribs = (1 << c::MAX_VERTEX_ATTRIBUTES) - 1;
377 }
378
bind_pipeline_state(&mut self, pso: PipelineState)379 fn bind_pipeline_state(&mut self, pso: PipelineState) {
380 let cull = pso.rasterizer.cull_face;
381 self.cache.primitive = primitive_to_gl(pso.primitive);
382 self.cache.attributes = pso.input;
383 self.cache.stencil = pso.output.stencil;
384 self.cache.cull_face = cull;
385 self.cache.draw_mask = pso.output.draw_mask;
386 self.buf.extend(self.cache.bind_program(pso.program));
387 self.cache.scissor = pso.scissor;
388 self.buf.extend(self.cache.set_rasterizer(pso.rasterizer));
389 self.buf.extend(self.cache.set_depth_state(pso.output.depth));
390 self.buf.extend(self.cache.set_stencil_state(pso.output.stencil, (0, 0), cull));
391 for i in 0..c::MAX_COLOR_TARGETS {
392 if pso.output.draw_mask & (1 << i) != 0 {
393 self.buf.extend(self.cache.set_blend_state(i as c::ColorSlot,
394 pso.output.colors[i]));
395 }
396 }
397 if let c::Primitive::PatchList(num) = pso.primitive {
398 self.buf.push(Command::SetPatches(num));
399 }
400 }
401
bind_vertex_buffers(&mut self, vbs: c::pso::VertexBufferSet<Resources>)402 fn bind_vertex_buffers(&mut self, vbs: c::pso::VertexBufferSet<Resources>) {
403 if self.cache.current_vbs == Some(vbs) {
404 return;
405 }
406 self.cache.current_vbs = Some(vbs);
407 for i in 0..c::MAX_VERTEX_ATTRIBUTES {
408 match (vbs.0[i], self.cache.attributes[i]) {
409 (None, Some(fm)) => {
410 error!("No vertex input provided for slot {} of format {:?}", i, fm)
411 }
412 (Some((buffer, offset)), Some(mut bel)) => {
413 bel.elem.offset += offset as gl::types::GLuint;
414 self.buf.push(Command::BindAttribute(
415 i as c::AttributeSlot,
416 buffer,
417 bel));
418 self.active_attribs |= 1 << i;
419 }
420 (_, None) if self.active_attribs & (1 << i) != 0 => {
421 self.buf.push(Command::UnbindAttribute(i as c::AttributeSlot));
422 self.active_attribs ^= 1 << i;
423 }
424 (_, None) => (),
425 }
426 }
427 }
428
bind_constant_buffers(&mut self, cbs: &[c::pso::ConstantBufferParam<Resources>])429 fn bind_constant_buffers(&mut self, cbs: &[c::pso::ConstantBufferParam<Resources>]) {
430 for param in cbs.iter() {
431 self.buf.extend(self.cache.bind_constant_buffer(param.clone()));
432 }
433 }
434
bind_global_constant(&mut self, loc: c::shade::Location, value: c::shade::UniformValue)435 fn bind_global_constant(&mut self, loc: c::shade::Location, value: c::shade::UniformValue) {
436 self.buf.push(Command::BindUniform(loc, value));
437 }
438
bind_resource_views(&mut self, srvs: &[c::pso::ResourceViewParam<Resources>])439 fn bind_resource_views(&mut self, srvs: &[c::pso::ResourceViewParam<Resources>]) {
440 for i in 0..c::MAX_RESOURCE_VIEWS {
441 self.cache.resource_binds[i] = None;
442 }
443 for param in srvs.iter() {
444 self.cache.resource_binds[param.2 as usize] = Some(param.0.bind);
445 self.buf.extend(self.cache.bind_resource_view(param.clone()));
446 }
447 }
448
bind_unordered_views(&mut self, uavs: &[c::pso::UnorderedViewParam<Resources>])449 fn bind_unordered_views(&mut self, uavs: &[c::pso::UnorderedViewParam<Resources>]) {
450 for param in uavs.iter() {
451 self.buf.push(Command::BindUnorderedView(param.clone()));
452 }
453 }
454
bind_samplers(&mut self, ss: &[c::pso::SamplerParam<Resources>])455 fn bind_samplers(&mut self, ss: &[c::pso::SamplerParam<Resources>]) {
456 for param in ss.iter() {
457 let bind = self.cache.resource_binds[param.2 as usize];
458 self.buf.push(Command::BindSampler(param.clone(), bind));
459 }
460 }
461
bind_pixel_targets(&mut self, pts: c::pso::PixelTargetSet<Resources>)462 fn bind_pixel_targets(&mut self, pts: c::pso::PixelTargetSet<Resources>) {
463 let is_main = pts.colors.iter().skip(1).find(|c| c.is_some()).is_none() &&
464 self.is_main_target(pts.colors[0]) &&
465 self.is_main_target(pts.depth) &&
466 self.is_main_target(pts.stencil);
467 if is_main {
468 self.buf.extend(self.cache.bind_framebuffer(gl::DRAW_FRAMEBUFFER, self.display_fb));
469 if self.workarounds.main_fbo_mask {
470 // Note: this will only allow less stuff to reach the framebuffer, not more
471 self.buf.push(Command::SetOutputMasks {
472 color: pts.colors[0].is_some(),
473 depth: pts.depth.is_some(),
474 stencil: pts.stencil.is_some(),
475 });
476 // Now that we bound a different mask, invalidate the cached states.
477 if pts.colors[0].is_none() {
478 self.cache.blend_state = None;
479 }
480 if pts.depth.is_none() {
481 self.cache.depth_state = None;
482 }
483 if pts.stencil.is_none() {
484 //self.cache.stencil_state = None;
485 }
486 }
487 } else {
488 let num = pts.colors
489 .iter()
490 .position(|c| c.is_none())
491 .unwrap_or(pts.colors.len()) as c::ColorSlot;
492 self.buf.extend(self.cache.bind_framebuffer(gl::DRAW_FRAMEBUFFER, self.fbo));
493 self.buf.push(Command::BindPixelTargets(pts));
494 self.buf.push(Command::SetDrawColorBuffers(num));
495 }
496 let view = pts.get_view();
497 self.cache.target_dim = view;
498 self.buf.extend(
499 self.cache.set_viewport(Rect {
500 x: 0,
501 y: 0,
502 w: view.0,
503 h: view.1,
504 }));
505 }
506
bind_index(&mut self, buf: Buffer, itype: c::IndexType)507 fn bind_index(&mut self, buf: Buffer, itype: c::IndexType) {
508 self.buf.extend(self.cache.bind_index(buf, itype));
509 }
510
set_scissor(&mut self, rect: Rect)511 fn set_scissor(&mut self, rect: Rect) {
512 use std::cmp;
513 let scissor = self.cache.scissor;
514 let target_dim = self.cache.target_dim;
515 let scissor_rect = if scissor {
516 Some(Rect {
517 // inverting the Y axis in order to match D3D11
518 y: cmp::max(target_dim.1, rect.y + rect.h) -
519 rect.y -
520 rect.h,
521 ..rect
522 })
523 } else {
524 None //TODO: assert?
525 };
526 self.buf.extend(self.cache.set_scissor(scissor_rect));
527 }
528
set_ref_values(&mut self, rv: s::RefValues)529 fn set_ref_values(&mut self, rv: s::RefValues) {
530 let stencil = self.cache.stencil;
531 let cull_face = self.cache.cull_face;
532 self.buf.extend(self.cache.set_stencil_state(stencil,
533 rv.stencil,
534 cull_face));
535 self.buf.extend(self.cache.set_blend_color(rv.blend));
536 }
537
copy_buffer(&mut self, src: Buffer, dst: Buffer, src_offset_bytes: usize, dst_offset_bytes: usize, size_bytes: usize)538 fn copy_buffer(&mut self,
539 src: Buffer,
540 dst: Buffer,
541 src_offset_bytes: usize,
542 dst_offset_bytes: usize,
543 size_bytes: usize) {
544 self.buf.push(Command::CopyBuffer(src, dst,
545 src_offset_bytes as gl::types::GLintptr,
546 dst_offset_bytes as gl::types::GLintptr,
547 size_bytes as gl::types::GLsizeiptr));
548 }
549
copy_buffer_to_texture(&mut self, src: Buffer, src_offset_bytes: usize, dst: TextureCopyRegion<NewTexture>)550 fn copy_buffer_to_texture(&mut self,
551 src: Buffer, src_offset_bytes: usize,
552 dst: TextureCopyRegion<NewTexture>) {
553 match dst.texture {
554 NewTexture::Texture(raw) => {
555 let dst = dst.with_texture(raw);
556 self.buf.push(Command::CopyBufferToTexture(
557 src, src_offset_bytes as _, dst
558 ));
559 }
560 NewTexture::Surface(s) => {
561 error!("GL: Cannot copy to a Surface({})", s)
562 }
563 }
564 }
565
copy_texture_to_buffer(&mut self, src: TextureCopyRegion<NewTexture>, dst: Buffer, dst_offset_bytes: usize)566 fn copy_texture_to_buffer(&mut self,
567 src: TextureCopyRegion<NewTexture>,
568 dst: Buffer, dst_offset_bytes: usize) {
569 self.buf.push(Command::CopyTextureToBuffer(
570 src, dst, dst_offset_bytes as _, self.fbo
571 ));
572 self.cache.framebuffer = None; // reset in the cache
573 }
574
copy_texture_to_texture(&mut self, src: TextureCopyRegion<NewTexture>, dst: TextureCopyRegion<NewTexture>)575 fn copy_texture_to_texture(&mut self,
576 src: TextureCopyRegion<NewTexture>,
577 dst: TextureCopyRegion<NewTexture>) {
578 match dst.texture {
579 NewTexture::Texture(raw) => {
580 let dst = dst.with_texture(raw);
581 self.buf.push(Command::CopyTextureToTexture(src, dst, self.fbo));
582 self.cache.framebuffer = None; // reset in the cache
583 }
584 NewTexture::Surface(s) => {
585 error!("GL: Cannot copy to a Surface({})", s)
586 }
587 }
588 }
589
update_buffer(&mut self, buf: Buffer, data: &[u8], offset_bytes: usize)590 fn update_buffer(&mut self, buf: Buffer, data: &[u8], offset_bytes: usize) {
591 let ptr = self.data.add(data);
592 self.buf.push(Command::UpdateBuffer(buf, ptr, offset_bytes));
593 }
594
update_texture(&mut self, dst: TextureCopyRegion<NewTexture>, data: &[u8])595 fn update_texture(&mut self,
596 dst: TextureCopyRegion<NewTexture>,
597 data: &[u8]) {
598 let ptr = self.data.add(data);
599 match dst.texture {
600 NewTexture::Texture(raw) => {
601 let dst = dst.with_texture(raw);
602 self.buf.push(Command::UpdateTexture(dst, ptr))
603 }
604 NewTexture::Surface(s) => {
605 error!("GL: unable to update the contents of a Surface({})", s)
606 }
607 }
608 }
609
generate_mipmap(&mut self, srv: ResourceView)610 fn generate_mipmap(&mut self, srv: ResourceView) {
611 self.buf.push(Command::GenerateMipmap(srv));
612 }
613
clear_color(&mut self, target: TargetView, value: command::ClearColor)614 fn clear_color(&mut self, target: TargetView, value: command::ClearColor) {
615 // this could be optimized by deferring the actual clear call
616 let mut pts = c::pso::PixelTargetSet::new();
617 pts.colors[0] = Some(target);
618 self.bind_pixel_targets(pts);
619 self.buf.push(Command::Clear(Some(value), None, None));
620 }
621
clear_depth_stencil(&mut self, target: TargetView, depth: Option<Depth>, stencil: Option<Stencil>)622 fn clear_depth_stencil(&mut self,
623 target: TargetView,
624 depth: Option<Depth>,
625 stencil: Option<Stencil>) {
626 let mut pts = c::pso::PixelTargetSet::new();
627 if depth.is_some() {
628 pts.depth = Some(target);
629 }
630 if stencil.is_some() {
631 pts.stencil = Some(target);
632 }
633 self.bind_pixel_targets(pts);
634 self.buf.push(Command::Clear(None, depth, stencil));
635 }
636
call_draw(&mut self, start: c::VertexCount, count: c::VertexCount, instances: Option<command::InstanceParams>)637 fn call_draw(&mut self,
638 start: c::VertexCount,
639 count: c::VertexCount,
640 instances: Option<command::InstanceParams>) {
641 self.buf.push(Command::Draw(self.cache.primitive, start, count, instances));
642 }
643
call_draw_indexed(&mut self, start: c::VertexCount, count: c::VertexCount, base: c::VertexCount, instances: Option<command::InstanceParams>)644 fn call_draw_indexed(&mut self,
645 start: c::VertexCount,
646 count: c::VertexCount,
647 base: c::VertexCount,
648 instances: Option<command::InstanceParams>) {
649 let (offset, gl_index) = match self.cache.index_type {
650 c::IndexType::U16 => (start * 2u32, gl::UNSIGNED_SHORT),
651 c::IndexType::U32 => (start * 4u32, gl::UNSIGNED_INT),
652 };
653 self.buf.push(
654 Command::DrawIndexed(
655 self.cache.primitive,
656 gl_index,
657 RawOffset(offset as *const gl::types::GLvoid),
658 count,
659 base,
660 instances));
661 }
662 }
663