1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include "util/u_inlines.h"
29 #include "util/u_memory.h"
31 #include "sp_video_context.h"
32 #include <util/u_inlines.h>
33 #include <util/u_memory.h>
34 #include <util/u_keymap.h>
35 #include <util/u_rect.h>
36 #include <util/u_video.h>
37 #include <util/u_surface.h>
38 #include "sp_public.h"
39 #include "sp_texture.h"
44 flush_buffer(struct sp_mpeg12_context
*ctx
)
48 if(ctx
->mc_buffer
!= NULL
) {
50 vl_mpeg12_mc_unmap_buffer(&ctx
->mc_renderer
, ctx
->mc_buffer
);
51 vl_mpeg12_mc_renderer_flush(&ctx
->mc_renderer
, ctx
->mc_buffer
);
53 ctx
->mc_buffer
= NULL
;
58 rotate_buffer(struct sp_mpeg12_context
*ctx
)
60 static unsigned key
= 0;
61 struct vl_mpeg12_mc_buffer
*buffer
;
67 buffer
= (struct vl_mpeg12_mc_buffer
*)util_keymap_lookup(ctx
->buffer_map
, &key
);
71 buffer
= CALLOC_STRUCT(vl_mpeg12_mc_buffer
);
75 if(!vl_mpeg12_mc_init_buffer(&ctx
->mc_renderer
, buffer
)) {
80 added_to_map
= util_keymap_insert(ctx
->buffer_map
, &key
, buffer
, ctx
);
85 ctx
->mc_buffer
= buffer
;
87 vl_mpeg12_mc_map_buffer(&ctx
->mc_renderer
, ctx
->mc_buffer
);
91 delete_buffer(const struct keymap
*map
,
92 const void *key
, void *data
,
95 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)user
;
96 struct vl_mpeg12_mc_buffer
*buf
= (struct vl_mpeg12_mc_buffer
*)data
;
103 vl_mpeg12_mc_cleanup_buffer(&ctx
->mc_renderer
, buf
);
107 sp_mpeg12_destroy(struct pipe_video_context
*vpipe
)
109 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
115 /* Asserted in softpipe_delete_fs_state() for some reason */
116 ctx
->pipe
->bind_vs_state(ctx
->pipe
, NULL
);
117 ctx
->pipe
->bind_fs_state(ctx
->pipe
, NULL
);
119 ctx
->pipe
->delete_blend_state(ctx
->pipe
, ctx
->blend
);
120 ctx
->pipe
->delete_rasterizer_state(ctx
->pipe
, ctx
->rast
);
121 ctx
->pipe
->delete_depth_stencil_alpha_state(ctx
->pipe
, ctx
->dsa
);
123 pipe_surface_reference(&ctx
->decode_target
, NULL
);
124 vl_compositor_cleanup(&ctx
->compositor
);
125 util_delete_keymap(ctx
->buffer_map
, ctx
);
126 vl_mpeg12_mc_renderer_cleanup(&ctx
->mc_renderer
);
127 ctx
->pipe
->destroy(ctx
->pipe
);
133 sp_mpeg12_get_param(struct pipe_video_context
*vpipe
, int param
)
135 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
140 case PIPE_CAP_NPOT_TEXTURES
:
141 /* XXX: Temporary; not all paths are NPOT-tested */
143 return ctx
->pipe
->screen
->get_param(ctx
->pipe
->screen
, param
);
146 case PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT
:
147 return ctx
->decode_format
;
150 debug_printf("Softpipe: Unknown PIPE_CAP %d\n", param
);
156 static struct pipe_surface
*
157 sp_mpeg12_create_surface(struct pipe_video_context
*vpipe
,
158 struct pipe_resource
*resource
,
159 const struct pipe_surface
*templat
)
161 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
165 return ctx
->pipe
->create_surface(ctx
->pipe
, resource
, templat
);
169 sp_mpeg12_is_format_supported(struct pipe_video_context
*vpipe
,
170 enum pipe_format format
,
174 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
178 /* XXX: Temporary; not all paths are NPOT-tested */
179 if (geom
& PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO
)
182 return ctx
->pipe
->screen
->is_format_supported(ctx
->pipe
->screen
, format
, PIPE_TEXTURE_2D
,
187 sp_mpeg12_decode_macroblocks(struct pipe_video_context
*vpipe
,
188 struct pipe_surface
*past
,
189 struct pipe_surface
*future
,
190 unsigned num_macroblocks
,
191 struct pipe_macroblock
*macroblocks
,
192 struct pipe_fence_handle
**fence
)
194 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
195 struct pipe_mpeg12_macroblock
*mpeg12_macroblocks
= (struct pipe_mpeg12_macroblock
*)macroblocks
;
198 assert(num_macroblocks
);
200 assert(macroblocks
->codec
== PIPE_VIDEO_CODEC_MPEG12
);
201 assert(ctx
->decode_target
);
202 assert(ctx
->mc_buffer
);
204 vl_mpeg12_mc_renderer_render_macroblocks(&ctx
->mc_renderer
,
207 past
, future
, num_macroblocks
,
208 mpeg12_macroblocks
, fence
);
212 sp_mpeg12_surface_fill(struct pipe_video_context
*vpipe
,
213 struct pipe_surface
*dst
,
214 unsigned dstx
, unsigned dsty
,
215 unsigned width
, unsigned height
,
218 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
219 float rgba
[4] = { 0, 0, 0, 0 };
224 if (ctx
->pipe
->clear_render_target
)
225 ctx
->pipe
->clear_render_target(ctx
->pipe
, dst
, rgba
, dstx
, dsty
, width
, height
);
227 util_clear_render_target(ctx
->pipe
, dst
, rgba
, dstx
, dsty
, width
, height
);
231 sp_mpeg12_surface_copy(struct pipe_video_context
*vpipe
,
232 struct pipe_surface
*dst
,
233 unsigned dstx
, unsigned dsty
,
234 struct pipe_surface
*src
,
235 unsigned srcx
, unsigned srcy
,
236 unsigned width
, unsigned height
)
238 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
250 if (ctx
->pipe
->resource_copy_region
)
251 ctx
->pipe
->resource_copy_region(ctx
->pipe
, dst
->texture
, dst
->u
.tex
.level
,
252 dstx
, dsty
, dst
->u
.tex
.first_layer
,
253 src
->texture
, src
->u
.tex
.level
, &box
);
255 util_resource_copy_region(ctx
->pipe
, dst
->texture
, dst
->u
.tex
.level
,
256 dstx
, dsty
, dst
->u
.tex
.first_layer
,
257 src
->texture
, src
->u
.tex
.level
, &box
);
260 static struct pipe_transfer
*
261 sp_mpeg12_get_transfer(struct pipe_video_context
*vpipe
,
262 struct pipe_resource
*resource
,
264 unsigned usage
, /* a combination of PIPE_TRANSFER_x */
265 const struct pipe_box
*box
)
267 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
273 return ctx
->pipe
->get_transfer(ctx
->pipe
, resource
, level
, usage
, box
);
277 sp_mpeg12_transfer_destroy(struct pipe_video_context
*vpipe
,
278 struct pipe_transfer
*transfer
)
280 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
285 ctx
->pipe
->transfer_destroy(ctx
->pipe
, transfer
);
289 sp_mpeg12_transfer_map(struct pipe_video_context
*vpipe
,
290 struct pipe_transfer
*transfer
)
292 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
297 return ctx
->pipe
->transfer_map(ctx
->pipe
, transfer
);
301 sp_mpeg12_transfer_flush_region(struct pipe_video_context
*vpipe
,
302 struct pipe_transfer
*transfer
,
303 const struct pipe_box
*box
)
305 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
311 ctx
->pipe
->transfer_flush_region(ctx
->pipe
, transfer
, box
);
315 sp_mpeg12_transfer_unmap(struct pipe_video_context
*vpipe
,
316 struct pipe_transfer
*transfer
)
318 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
323 ctx
->pipe
->transfer_unmap(ctx
->pipe
, transfer
);
327 sp_mpeg12_transfer_inline_write(struct pipe_video_context
*vpipe
,
328 struct pipe_resource
*resource
,
330 unsigned usage
, /* a combination of PIPE_TRANSFER_x */
331 const struct pipe_box
*box
,
334 unsigned slice_stride
)
336 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
342 assert(ctx
->pipe
->transfer_inline_write
);
344 ctx
->pipe
->transfer_inline_write(ctx
->pipe
, resource
, level
, usage
,
345 box
, data
, stride
, slice_stride
);
349 sp_mpeg12_render_picture(struct pipe_video_context
*vpipe
,
350 struct pipe_surface
*src_surface
,
351 enum pipe_mpeg12_picture_type picture_type
,
352 /*unsigned num_past_surfaces,
353 struct pipe_surface *past_surfaces,
354 unsigned num_future_surfaces,
355 struct pipe_surface *future_surfaces,*/
356 struct pipe_video_rect
*src_area
,
357 struct pipe_surface
*dst_surface
,
358 struct pipe_video_rect
*dst_area
,
359 struct pipe_fence_handle
**fence
)
361 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
371 vl_compositor_render(&ctx
->compositor
, src_surface
,
372 picture_type
, src_area
, dst_surface
, dst_area
, fence
);
376 sp_mpeg12_set_picture_background(struct pipe_video_context
*vpipe
,
377 struct pipe_surface
*bg
,
378 struct pipe_video_rect
*bg_src_rect
)
380 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
386 vl_compositor_set_background(&ctx
->compositor
, bg
, bg_src_rect
);
390 sp_mpeg12_set_picture_layers(struct pipe_video_context
*vpipe
,
391 struct pipe_surface
*layers
[],
392 struct pipe_video_rect
*src_rects
[],
393 struct pipe_video_rect
*dst_rects
[],
396 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
399 assert((layers
&& src_rects
&& dst_rects
) ||
400 (!layers
&& !src_rects
&& !dst_rects
));
402 vl_compositor_set_layers(&ctx
->compositor
, layers
, src_rects
, dst_rects
, num_layers
);
406 sp_mpeg12_set_decode_target(struct pipe_video_context
*vpipe
,
407 struct pipe_surface
*dt
)
409 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
414 if (ctx
->decode_target
!= dt
|| ctx
->mc_buffer
== NULL
) {
417 pipe_surface_reference(&ctx
->decode_target
, dt
);
422 sp_mpeg12_set_csc_matrix(struct pipe_video_context
*vpipe
, const float *mat
)
424 struct sp_mpeg12_context
*ctx
= (struct sp_mpeg12_context
*)vpipe
;
428 vl_compositor_set_csc_matrix(&ctx
->compositor
, mat
);
432 init_pipe_state(struct sp_mpeg12_context
*ctx
)
434 struct pipe_rasterizer_state rast
;
435 struct pipe_blend_state blend
;
436 struct pipe_depth_stencil_alpha_state dsa
;
441 memset(&rast
, 0, sizeof rast
);
443 rast
.flatshade_first
= 0;
444 rast
.light_twoside
= 0;
446 rast
.cull_face
= PIPE_FACE_NONE
;
447 rast
.fill_back
= PIPE_POLYGON_MODE_FILL
;
448 rast
.fill_front
= PIPE_POLYGON_MODE_FILL
;
449 rast
.offset_point
= 0;
450 rast
.offset_line
= 0;
452 rast
.poly_smooth
= 0;
453 rast
.poly_stipple_enable
= 0;
454 rast
.sprite_coord_enable
= 0;
455 rast
.point_size_per_vertex
= 0;
456 rast
.multisample
= 0;
457 rast
.line_smooth
= 0;
458 rast
.line_stipple_enable
= 0;
459 rast
.line_stipple_factor
= 0;
460 rast
.line_stipple_pattern
= 0;
461 rast
.line_last_pixel
= 0;
463 rast
.point_smooth
= 0;
464 rast
.point_quad_rasterization
= 0;
466 rast
.offset_units
= 1;
467 rast
.offset_scale
= 1;
468 rast
.gl_rasterization_rules
= 1;
469 ctx
->rast
= ctx
->pipe
->create_rasterizer_state(ctx
->pipe
, &rast
);
470 ctx
->pipe
->bind_rasterizer_state(ctx
->pipe
, ctx
->rast
);
472 memset(&blend
, 0, sizeof blend
);
473 blend
.independent_blend_enable
= 0;
474 blend
.rt
[0].blend_enable
= 0;
475 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
476 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
477 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ONE
;
478 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
479 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
480 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
481 blend
.logicop_enable
= 0;
482 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
483 /* Needed to allow color writes to FB, even if blending disabled */
484 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
486 ctx
->blend
= ctx
->pipe
->create_blend_state(ctx
->pipe
, &blend
);
487 ctx
->pipe
->bind_blend_state(ctx
->pipe
, ctx
->blend
);
489 memset(&dsa
, 0, sizeof dsa
);
490 dsa
.depth
.enabled
= 0;
491 dsa
.depth
.writemask
= 0;
492 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
493 for (i
= 0; i
< 2; ++i
) {
494 dsa
.stencil
[i
].enabled
= 0;
495 dsa
.stencil
[i
].func
= PIPE_FUNC_ALWAYS
;
496 dsa
.stencil
[i
].fail_op
= PIPE_STENCIL_OP_KEEP
;
497 dsa
.stencil
[i
].zpass_op
= PIPE_STENCIL_OP_KEEP
;
498 dsa
.stencil
[i
].zfail_op
= PIPE_STENCIL_OP_KEEP
;
499 dsa
.stencil
[i
].valuemask
= 0;
500 dsa
.stencil
[i
].writemask
= 0;
502 dsa
.alpha
.enabled
= 0;
503 dsa
.alpha
.func
= PIPE_FUNC_ALWAYS
;
504 dsa
.alpha
.ref_value
= 0;
505 ctx
->dsa
= ctx
->pipe
->create_depth_stencil_alpha_state(ctx
->pipe
, &dsa
);
506 ctx
->pipe
->bind_depth_stencil_alpha_state(ctx
->pipe
, ctx
->dsa
);
511 static struct pipe_video_context
*
512 sp_mpeg12_create(struct pipe_context
*pipe
, enum pipe_video_profile profile
,
513 enum pipe_video_chroma_format chroma_format
,
514 unsigned width
, unsigned height
,
515 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode
,
517 enum pipe_format decode_format
)
519 unsigned buffer_width
, buffer_height
;
520 struct sp_mpeg12_context
*ctx
;
522 assert(u_reduce_video_profile(profile
) == PIPE_VIDEO_CODEC_MPEG12
);
524 ctx
= CALLOC_STRUCT(sp_mpeg12_context
);
529 /* TODO: Non-pot buffers untested, probably doesn't work without changes to texcoord generation, vert shader, etc */
532 buffer_width
= pot_buffers
? util_next_power_of_two(width
) : width
;
533 buffer_height
= pot_buffers
? util_next_power_of_two(height
) : height
;
535 ctx
->base
.profile
= profile
;
536 ctx
->base
.chroma_format
= chroma_format
;
537 ctx
->base
.width
= width
;
538 ctx
->base
.height
= height
;
540 ctx
->base
.screen
= pipe
->screen
;
541 ctx
->base
.destroy
= sp_mpeg12_destroy
;
542 ctx
->base
.get_param
= sp_mpeg12_get_param
;
543 ctx
->base
.is_format_supported
= sp_mpeg12_is_format_supported
;
544 ctx
->base
.create_surface
= sp_mpeg12_create_surface
;
545 ctx
->base
.decode_macroblocks
= sp_mpeg12_decode_macroblocks
;
546 ctx
->base
.render_picture
= sp_mpeg12_render_picture
;
547 ctx
->base
.surface_fill
= sp_mpeg12_surface_fill
;
548 ctx
->base
.surface_copy
= sp_mpeg12_surface_copy
;
549 ctx
->base
.get_transfer
= sp_mpeg12_get_transfer
;
550 ctx
->base
.transfer_destroy
= sp_mpeg12_transfer_destroy
;
551 ctx
->base
.transfer_map
= sp_mpeg12_transfer_map
;
552 ctx
->base
.transfer_flush_region
= sp_mpeg12_transfer_flush_region
;
553 ctx
->base
.transfer_unmap
= sp_mpeg12_transfer_unmap
;
554 if (pipe
->transfer_inline_write
)
555 ctx
->base
.transfer_inline_write
= sp_mpeg12_transfer_inline_write
;
556 ctx
->base
.set_picture_background
= sp_mpeg12_set_picture_background
;
557 ctx
->base
.set_picture_layers
= sp_mpeg12_set_picture_layers
;
558 ctx
->base
.set_decode_target
= sp_mpeg12_set_decode_target
;
559 ctx
->base
.set_csc_matrix
= sp_mpeg12_set_csc_matrix
;
562 ctx
->decode_format
= decode_format
;
564 if (!vl_mpeg12_mc_renderer_init(&ctx
->mc_renderer
, ctx
->pipe
,
565 buffer_width
, buffer_height
, chroma_format
,
567 ctx
->pipe
->destroy(ctx
->pipe
);
572 ctx
->buffer_map
= util_new_keymap(sizeof(unsigned), -1, delete_buffer
);
573 if (!ctx
->buffer_map
) {
574 vl_mpeg12_mc_renderer_cleanup(&ctx
->mc_renderer
);
575 ctx
->pipe
->destroy(ctx
->pipe
);
580 if (!vl_compositor_init(&ctx
->compositor
, ctx
->pipe
)) {
581 util_delete_keymap(ctx
->buffer_map
, ctx
);
582 vl_mpeg12_mc_renderer_cleanup(&ctx
->mc_renderer
);
583 ctx
->pipe
->destroy(ctx
->pipe
);
588 if (!init_pipe_state(ctx
)) {
589 vl_compositor_cleanup(&ctx
->compositor
);
590 util_delete_keymap(ctx
->buffer_map
, ctx
);
591 vl_mpeg12_mc_renderer_cleanup(&ctx
->mc_renderer
);
592 ctx
->pipe
->destroy(ctx
->pipe
);
600 struct pipe_video_context
*
601 sp_video_create(struct pipe_screen
*screen
, enum pipe_video_profile profile
,
602 enum pipe_video_chroma_format chroma_format
,
603 unsigned width
, unsigned height
, void *priv
)
605 struct pipe_context
*pipe
;
608 assert(width
&& height
);
610 pipe
= screen
->context_create(screen
, NULL
);
614 /* TODO: Use slice buffering for softpipe when implemented, no advantage to buffering an entire picture with softpipe */
615 return sp_video_create_ex(pipe
, profile
,
618 VL_MPEG12_MC_RENDERER_BUFFER_PICTURE
,
623 struct pipe_video_context
*
624 sp_video_create_ex(struct pipe_context
*pipe
, enum pipe_video_profile profile
,
625 enum pipe_video_chroma_format chroma_format
,
626 unsigned width
, unsigned height
,
627 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode
,
629 enum pipe_format decode_format
)
632 assert(width
&& height
);
634 switch (u_reduce_video_profile(profile
)) {
635 case PIPE_VIDEO_CODEC_MPEG12
:
636 return sp_mpeg12_create(pipe
, profile
,