1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2009 Younes Manton. 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg#include <assert.h> 29848b8605Smrg 30848b8605Smrg#include <X11/Xlibint.h> 31848b8605Smrg#include <X11/extensions/XvMClib.h> 32848b8605Smrg 33848b8605Smrg#include "pipe/p_screen.h" 34848b8605Smrg#include "pipe/p_video_codec.h" 35848b8605Smrg#include "pipe/p_state.h" 36848b8605Smrg 37848b8605Smrg#include "util/u_memory.h" 38848b8605Smrg#include "util/u_math.h" 39848b8605Smrg#include "util/u_format.h" 40848b8605Smrg#include "util/u_sampler.h" 41848b8605Smrg#include "util/u_surface.h" 42848b8605Smrg#include "util/u_rect.h" 43848b8605Smrg#include "vl/vl_winsys.h" 44848b8605Smrg 45848b8605Smrg#include "xvmc_private.h" 46848b8605Smrg 47848b8605Smrg#define FOURCC_RGB 0x0000003 48848b8605Smrg#define FOURCC_AI44 0x34344941 49848b8605Smrg#define FOURCC_IA44 0x34344149 50848b8605Smrg 51b8e80941Smrgstatic enum pipe_format XvIDToPipe(struct pipe_screen *screen, 52b8e80941Smrg int xvimage_id) 53848b8605Smrg{ 54b8e80941Smrg enum pipe_format ret; 55b8e80941Smrg assert(screen); 56848b8605Smrg 57b8e80941Smrg switch (xvimage_id) { 58b8e80941Smrg case FOURCC_RGB: 59b8e80941Smrg ret = PIPE_FORMAT_B8G8R8X8_UNORM; 60b8e80941Smrg break; 61b8e80941Smrg 62b8e80941Smrg case FOURCC_AI44: 63b8e80941Smrg ret = PIPE_FORMAT_R4A4_UNORM; 64b8e80941Smrg if (!screen->is_format_supported( 65b8e80941Smrg screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) 66b8e80941Smrg ret = PIPE_FORMAT_B4G4R4A4_UNORM; 67b8e80941Smrg break; 68b8e80941Smrg 69b8e80941Smrg case FOURCC_IA44: 70b8e80941Smrg ret = PIPE_FORMAT_A4R4_UNORM; 71b8e80941Smrg if (!screen->is_format_supported( 72b8e80941Smrg screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) 73b8e80941Smrg ret = PIPE_FORMAT_B4G4R4A4_UNORM; 74b8e80941Smrg break; 75b8e80941Smrg 76b8e80941Smrg default: 77b8e80941Smrg XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id); 78b8e80941Smrg return PIPE_FORMAT_NONE; 79b8e80941Smrg } 80848b8605Smrg 81b8e80941Smrg if (!screen->is_format_supported( 82b8e80941Smrg screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { 83b8e80941Smrg XVMC_MSG(XVMC_ERR, "[XvMC] Unsupported 2D format %s for Xv image ID 0x%08X.\n", util_format_name(ret), xvimage_id); 84b8e80941Smrg ret = PIPE_FORMAT_NONE; 85848b8605Smrg } 86b8e80941Smrg return ret; 87b8e80941Smrg 88848b8605Smrg} 89848b8605Smrg 90848b8605Smrgstatic unsigned NumPaletteEntries4XvID(int xvimage_id) 91848b8605Smrg{ 92848b8605Smrg switch (xvimage_id) { 93848b8605Smrg case FOURCC_RGB: 94848b8605Smrg return 0; 95848b8605Smrg 96848b8605Smrg case FOURCC_AI44: 97848b8605Smrg case FOURCC_IA44: 98848b8605Smrg return 16; 99848b8605Smrg 100848b8605Smrg default: 101848b8605Smrg XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id); 102848b8605Smrg return 0; 103848b8605Smrg } 104848b8605Smrg} 105848b8605Smrg 106b8e80941Smrgstatic int PipeToComponentOrder(struct pipe_screen *screen, 107b8e80941Smrg enum pipe_format format, 108b8e80941Smrg enum pipe_format *palette_format, 109b8e80941Smrg char *component_order) 110848b8605Smrg{ 111b8e80941Smrg assert(screen); 112848b8605Smrg assert(component_order); 113b8e80941Smrg assert(palette_format); 114848b8605Smrg 115848b8605Smrg switch (format) { 116b8e80941Smrg case PIPE_FORMAT_B8G8R8X8_UNORM: 117b8e80941Smrg return 0; 118b8e80941Smrg 119b8e80941Smrg case PIPE_FORMAT_A4R4_UNORM: 120b8e80941Smrg case PIPE_FORMAT_R4A4_UNORM: 121b8e80941Smrg case PIPE_FORMAT_B4G4R4A4_UNORM: 122b8e80941Smrg *palette_format = PIPE_FORMAT_R8G8B8X8_UNORM; 123b8e80941Smrg component_order[0] = 'Y'; 124b8e80941Smrg component_order[1] = 'U'; 125b8e80941Smrg component_order[2] = 'V'; 126b8e80941Smrg component_order[3] = 'A'; 127b8e80941Smrg if (!screen->is_format_supported( 128b8e80941Smrg screen, *palette_format, PIPE_TEXTURE_1D, 0, 0, 129b8e80941Smrg PIPE_BIND_SAMPLER_VIEW)) { 130b8e80941Smrg /* One of these formats better be supported... */ 131b8e80941Smrg *palette_format = PIPE_FORMAT_B8G8R8X8_UNORM; 132b8e80941Smrg component_order[0] = 'V'; 133b8e80941Smrg component_order[2] = 'Y'; 134b8e80941Smrg } 135b8e80941Smrg return 4; 136b8e80941Smrg 137b8e80941Smrg default: 138b8e80941Smrg XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format); 139b8e80941Smrg component_order[0] = 0; 140b8e80941Smrg component_order[1] = 0; 141b8e80941Smrg component_order[2] = 0; 142b8e80941Smrg component_order[3] = 0; 143b8e80941Smrg return 0; 144848b8605Smrg } 145848b8605Smrg} 146848b8605Smrg 147848b8605Smrgstatic Status Validate(Display *dpy, XvPortID port, int surface_type_id, int xvimage_id) 148848b8605Smrg{ 149848b8605Smrg XvImageFormatValues *subpictures; 150848b8605Smrg int num_subpics; 151b8e80941Smrg int i; 152848b8605Smrg 153848b8605Smrg subpictures = XvMCListSubpictureTypes(dpy, port, surface_type_id, &num_subpics); 154848b8605Smrg if (num_subpics < 1) { 155848b8605Smrg free(subpictures); 156848b8605Smrg return BadMatch; 157848b8605Smrg } 158848b8605Smrg if (!subpictures) 159848b8605Smrg return BadAlloc; 160848b8605Smrg 161848b8605Smrg for (i = 0; i < num_subpics; ++i) { 162848b8605Smrg if (subpictures[i].id == xvimage_id) { 163848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested subpicture format.\n" \ 164848b8605Smrg "[XvMC] port=%u\n" \ 165848b8605Smrg "[XvMC] surface id=0x%08X\n" \ 166848b8605Smrg "[XvMC] image id=0x%08X\n" \ 167848b8605Smrg "[XvMC] type=%08X\n" \ 168848b8605Smrg "[XvMC] byte order=%08X\n" \ 169848b8605Smrg "[XvMC] bits per pixel=%u\n" \ 170848b8605Smrg "[XvMC] format=%08X\n" \ 171848b8605Smrg "[XvMC] num planes=%d\n", 172848b8605Smrg port, surface_type_id, xvimage_id, subpictures[i].type, subpictures[i].byte_order, 173848b8605Smrg subpictures[i].bits_per_pixel, subpictures[i].format, subpictures[i].num_planes); 174848b8605Smrg if (subpictures[i].type == XvRGB) { 175848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] depth=%d\n" \ 176848b8605Smrg "[XvMC] red mask=0x%08X\n" \ 177848b8605Smrg "[XvMC] green mask=0x%08X\n" \ 178848b8605Smrg "[XvMC] blue mask=0x%08X\n", 179848b8605Smrg subpictures[i].depth, subpictures[i].red_mask, 180848b8605Smrg subpictures[i].green_mask, subpictures[i].blue_mask); 181848b8605Smrg } 182848b8605Smrg else if (subpictures[i].type == XvYUV) { 183848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] y sample bits=0x%08X\n" \ 184848b8605Smrg "[XvMC] u sample bits=0x%08X\n" \ 185848b8605Smrg "[XvMC] v sample bits=0x%08X\n" \ 186848b8605Smrg "[XvMC] horz y period=%u\n" \ 187848b8605Smrg "[XvMC] horz u period=%u\n" \ 188848b8605Smrg "[XvMC] horz v period=%u\n" \ 189848b8605Smrg "[XvMC] vert y period=%u\n" \ 190848b8605Smrg "[XvMC] vert u period=%u\n" \ 191848b8605Smrg "[XvMC] vert v period=%u\n", 192848b8605Smrg subpictures[i].y_sample_bits, subpictures[i].u_sample_bits, subpictures[i].v_sample_bits, 193848b8605Smrg subpictures[i].horz_y_period, subpictures[i].horz_u_period, subpictures[i].horz_v_period, 194848b8605Smrg subpictures[i].vert_y_period, subpictures[i].vert_u_period, subpictures[i].vert_v_period); 195848b8605Smrg } 196848b8605Smrg break; 197848b8605Smrg } 198848b8605Smrg } 199848b8605Smrg 200848b8605Smrg free(subpictures); 201848b8605Smrg 202848b8605Smrg return i < num_subpics ? Success : BadMatch; 203848b8605Smrg} 204848b8605Smrg 205848b8605Smrgstatic void 206848b8605Smrgupload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst, 207848b8605Smrg const struct pipe_box *dst_box, const void *src, unsigned src_stride, 208848b8605Smrg unsigned src_x, unsigned src_y) 209848b8605Smrg{ 210848b8605Smrg struct pipe_transfer *transfer; 211848b8605Smrg void *map; 212848b8605Smrg 213848b8605Smrg map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, 214848b8605Smrg dst_box, &transfer); 215848b8605Smrg if (!map) 216848b8605Smrg return; 217848b8605Smrg 218848b8605Smrg util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0, 219848b8605Smrg dst_box->width, dst_box->height, 220848b8605Smrg src, src_stride, src_x, src_y); 221848b8605Smrg 222848b8605Smrg pipe->transfer_unmap(pipe, transfer); 223848b8605Smrg} 224848b8605Smrg 225b8e80941Smrgstatic void 226b8e80941Smrgupload_sampler_convert(struct pipe_context *pipe, struct pipe_sampler_view *dst, 227b8e80941Smrg const struct pipe_box *dst_box, const XvImage *image, 228b8e80941Smrg unsigned src_x, unsigned src_y) 229b8e80941Smrg{ 230b8e80941Smrg struct pipe_transfer *transfer; 231b8e80941Smrg int i, j; 232b8e80941Smrg char *map, *src; 233b8e80941Smrg 234b8e80941Smrg map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, 235b8e80941Smrg dst_box, &transfer); 236b8e80941Smrg if (!map) 237b8e80941Smrg return; 238b8e80941Smrg 239b8e80941Smrg src = image->data; 240b8e80941Smrg src += src_y * image->width + src_x; 241b8e80941Smrg if (image->id == FOURCC_AI44) { 242b8e80941Smrg /* The format matches what we want, we just have to insert dummy 243b8e80941Smrg * bytes. So just copy the same value in twice. 244b8e80941Smrg */ 245b8e80941Smrg for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width) 246b8e80941Smrg for (j = 0; j < dst_box->width; j++) 247b8e80941Smrg map[j * 2 + 0] = map[j * 2 + 1] = src[j]; 248b8e80941Smrg } else { 249b8e80941Smrg assert(image->id == FOURCC_IA44); 250b8e80941Smrg /* Same idea as above, but we have to swap the low and high nibbles. 251b8e80941Smrg */ 252b8e80941Smrg for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width) 253b8e80941Smrg for (j = 0; j < dst_box->width; j++) 254b8e80941Smrg map[j * 2 + 0] = map[j * 2 + 1] = (src[j] >> 4) | (src[j] << 4); 255b8e80941Smrg } 256b8e80941Smrg 257b8e80941Smrg pipe->transfer_unmap(pipe, transfer); 258b8e80941Smrg} 259b8e80941Smrg 260848b8605SmrgPUBLIC 261848b8605SmrgStatus XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture, 262848b8605Smrg unsigned short width, unsigned short height, int xvimage_id) 263848b8605Smrg{ 264848b8605Smrg XvMCContextPrivate *context_priv; 265848b8605Smrg XvMCSubpicturePrivate *subpicture_priv; 266848b8605Smrg struct pipe_context *pipe; 267848b8605Smrg struct pipe_resource tex_templ, *tex; 268848b8605Smrg struct pipe_sampler_view sampler_templ; 269b8e80941Smrg enum pipe_format palette_format; 270848b8605Smrg Status ret; 271848b8605Smrg 272848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture); 273848b8605Smrg 274848b8605Smrg assert(dpy); 275848b8605Smrg 276848b8605Smrg if (!context) 277848b8605Smrg return XvMCBadContext; 278848b8605Smrg 279848b8605Smrg context_priv = context->privData; 280848b8605Smrg pipe = context_priv->pipe; 281848b8605Smrg 282848b8605Smrg if (!subpicture) 283848b8605Smrg return XvMCBadSubpicture; 284848b8605Smrg 285848b8605Smrg if (width > context_priv->subpicture_max_width || 286848b8605Smrg height > context_priv->subpicture_max_height) 287848b8605Smrg return BadValue; 288848b8605Smrg 289848b8605Smrg ret = Validate(dpy, context->port, context->surface_type_id, xvimage_id); 290848b8605Smrg if (ret != Success) 291848b8605Smrg return ret; 292848b8605Smrg 293848b8605Smrg subpicture_priv = CALLOC(1, sizeof(XvMCSubpicturePrivate)); 294848b8605Smrg if (!subpicture_priv) 295848b8605Smrg return BadAlloc; 296848b8605Smrg 297848b8605Smrg memset(&tex_templ, 0, sizeof(tex_templ)); 298848b8605Smrg tex_templ.target = PIPE_TEXTURE_2D; 299b8e80941Smrg tex_templ.format = XvIDToPipe(pipe->screen, xvimage_id); 300848b8605Smrg tex_templ.last_level = 0; 301848b8605Smrg if (pipe->screen->get_video_param(pipe->screen, 302848b8605Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 303848b8605Smrg PIPE_VIDEO_ENTRYPOINT_UNKNOWN, 304848b8605Smrg PIPE_VIDEO_CAP_NPOT_TEXTURES)) { 305848b8605Smrg tex_templ.width0 = width; 306848b8605Smrg tex_templ.height0 = height; 307848b8605Smrg } 308848b8605Smrg else { 309848b8605Smrg tex_templ.width0 = util_next_power_of_two(width); 310848b8605Smrg tex_templ.height0 = util_next_power_of_two(height); 311848b8605Smrg } 312848b8605Smrg tex_templ.depth0 = 1; 313848b8605Smrg tex_templ.array_size = 1; 314848b8605Smrg tex_templ.usage = PIPE_USAGE_DYNAMIC; 315848b8605Smrg tex_templ.bind = PIPE_BIND_SAMPLER_VIEW; 316848b8605Smrg tex_templ.flags = 0; 317848b8605Smrg 318848b8605Smrg tex = pipe->screen->resource_create(pipe->screen, &tex_templ); 319848b8605Smrg 320848b8605Smrg memset(&sampler_templ, 0, sizeof(sampler_templ)); 321848b8605Smrg u_sampler_view_default_template(&sampler_templ, tex, tex->format); 322848b8605Smrg 323848b8605Smrg subpicture_priv->sampler = pipe->create_sampler_view(pipe, tex, &sampler_templ); 324848b8605Smrg pipe_resource_reference(&tex, NULL); 325848b8605Smrg if (!subpicture_priv->sampler) { 326848b8605Smrg FREE(subpicture_priv); 327848b8605Smrg return BadAlloc; 328848b8605Smrg } 329848b8605Smrg 330848b8605Smrg subpicture_priv->context = context; 331848b8605Smrg subpicture->subpicture_id = XAllocID(dpy); 332848b8605Smrg subpicture->context_id = context->context_id; 333848b8605Smrg subpicture->xvimage_id = xvimage_id; 334848b8605Smrg subpicture->width = width; 335848b8605Smrg subpicture->height = height; 336848b8605Smrg subpicture->num_palette_entries = NumPaletteEntries4XvID(xvimage_id); 337b8e80941Smrg subpicture->entry_bytes = PipeToComponentOrder( 338b8e80941Smrg pipe->screen, tex_templ.format, &palette_format, 339b8e80941Smrg subpicture->component_order); 340848b8605Smrg subpicture->privData = subpicture_priv; 341848b8605Smrg 342848b8605Smrg if (subpicture->num_palette_entries > 0) { 343848b8605Smrg tex_templ.target = PIPE_TEXTURE_1D; 344b8e80941Smrg tex_templ.format = palette_format; 345848b8605Smrg tex_templ.width0 = subpicture->num_palette_entries; 346848b8605Smrg tex_templ.height0 = 1; 347848b8605Smrg tex_templ.usage = PIPE_USAGE_DEFAULT; 348848b8605Smrg 349848b8605Smrg tex = pipe->screen->resource_create(pipe->screen, &tex_templ); 350848b8605Smrg 351848b8605Smrg memset(&sampler_templ, 0, sizeof(sampler_templ)); 352848b8605Smrg u_sampler_view_default_template(&sampler_templ, tex, tex->format); 353b8e80941Smrg sampler_templ.swizzle_a = PIPE_SWIZZLE_1; 354848b8605Smrg subpicture_priv->palette = pipe->create_sampler_view(pipe, tex, &sampler_templ); 355848b8605Smrg pipe_resource_reference(&tex, NULL); 356848b8605Smrg if (!subpicture_priv->sampler) { 357848b8605Smrg FREE(subpicture_priv); 358848b8605Smrg return BadAlloc; 359848b8605Smrg } 360848b8605Smrg } 361848b8605Smrg 362848b8605Smrg SyncHandle(); 363848b8605Smrg 364848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p created.\n", subpicture); 365848b8605Smrg 366848b8605Smrg return Success; 367848b8605Smrg} 368848b8605Smrg 369848b8605SmrgPUBLIC 370848b8605SmrgStatus XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y, 371848b8605Smrg unsigned short width, unsigned short height, unsigned int color) 372848b8605Smrg{ 373848b8605Smrg XvMCSubpicturePrivate *subpicture_priv; 374848b8605Smrg XvMCContextPrivate *context_priv; 375848b8605Smrg struct pipe_context *pipe; 376848b8605Smrg struct pipe_sampler_view *dst; 377848b8605Smrg struct pipe_box dst_box = {x, y, 0, width, height, 1}; 378848b8605Smrg struct pipe_transfer *transfer; 379848b8605Smrg union util_color uc; 380848b8605Smrg void *map; 381848b8605Smrg 382848b8605Smrg assert(dpy); 383848b8605Smrg 384848b8605Smrg if (!subpicture) 385848b8605Smrg return XvMCBadSubpicture; 386848b8605Smrg 387848b8605Smrg /* Convert color to float */ 388848b8605Smrg util_format_read_4f(PIPE_FORMAT_B8G8R8A8_UNORM, 389848b8605Smrg uc.f, 1, &color, 4, 390848b8605Smrg 0, 0, 1, 1); 391848b8605Smrg 392848b8605Smrg subpicture_priv = subpicture->privData; 393848b8605Smrg context_priv = subpicture_priv->context->privData; 394848b8605Smrg pipe = context_priv->pipe; 395848b8605Smrg dst = subpicture_priv->sampler; 396848b8605Smrg 397848b8605Smrg /* TODO: Assert clear rect is within bounds? Or clip? */ 398848b8605Smrg map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, 399848b8605Smrg &dst_box, &transfer); 400848b8605Smrg if (!map) 401848b8605Smrg return XvMCBadSubpicture; 402848b8605Smrg 403848b8605Smrg util_fill_rect(map, dst->texture->format, transfer->stride, 0, 0, 404848b8605Smrg dst_box.width, dst_box.height, &uc); 405848b8605Smrg 406848b8605Smrg pipe->transfer_unmap(pipe, transfer); 407848b8605Smrg return Success; 408848b8605Smrg} 409848b8605Smrg 410848b8605SmrgPUBLIC 411848b8605SmrgStatus XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image, 412848b8605Smrg short srcx, short srcy, unsigned short width, unsigned short height, 413848b8605Smrg short dstx, short dsty) 414848b8605Smrg{ 415848b8605Smrg XvMCSubpicturePrivate *subpicture_priv; 416848b8605Smrg XvMCContextPrivate *context_priv; 417848b8605Smrg struct pipe_context *pipe; 418848b8605Smrg struct pipe_box dst_box = {dstx, dsty, 0, width, height, 1}; 419848b8605Smrg unsigned src_stride; 420848b8605Smrg 421848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Compositing subpicture %p.\n", subpicture); 422848b8605Smrg 423848b8605Smrg assert(dpy); 424848b8605Smrg 425848b8605Smrg if (!subpicture) 426848b8605Smrg return XvMCBadSubpicture; 427848b8605Smrg 428848b8605Smrg assert(image); 429848b8605Smrg 430848b8605Smrg if (subpicture->xvimage_id != image->id) 431848b8605Smrg return BadMatch; 432848b8605Smrg 433848b8605Smrg /* No planar support for now */ 434848b8605Smrg if (image->num_planes != 1) 435848b8605Smrg return BadMatch; 436848b8605Smrg 437848b8605Smrg subpicture_priv = subpicture->privData; 438848b8605Smrg context_priv = subpicture_priv->context->privData; 439848b8605Smrg pipe = context_priv->pipe; 440848b8605Smrg 441848b8605Smrg /* clipping should be done by upload_sampler and regardles what the documentation 442848b8605Smrg says image->pitches[0] doesn't seems to be in bytes, so don't use it */ 443b8e80941Smrg if ((image->id == FOURCC_IA44 || image->id == FOURCC_AI44) && 444b8e80941Smrg subpicture_priv->sampler->texture->format == PIPE_FORMAT_B4G4R4A4_UNORM) { 445b8e80941Smrg upload_sampler_convert(pipe, subpicture_priv->sampler, &dst_box, image, srcx, srcy); 446b8e80941Smrg } else { 447b8e80941Smrg src_stride = image->width * util_format_get_blocksize(subpicture_priv->sampler->texture->format); 448b8e80941Smrg upload_sampler(pipe, subpicture_priv->sampler, &dst_box, image->data, src_stride, srcx, srcy); 449b8e80941Smrg } 450848b8605Smrg 451848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture); 452848b8605Smrg 453848b8605Smrg return Success; 454848b8605Smrg} 455848b8605Smrg 456848b8605SmrgPUBLIC 457848b8605SmrgStatus XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture) 458848b8605Smrg{ 459848b8605Smrg XvMCSubpicturePrivate *subpicture_priv; 460848b8605Smrg 461848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying subpicture %p.\n", subpicture); 462848b8605Smrg 463848b8605Smrg assert(dpy); 464848b8605Smrg 465848b8605Smrg if (!subpicture) 466848b8605Smrg return XvMCBadSubpicture; 467848b8605Smrg 468848b8605Smrg subpicture_priv = subpicture->privData; 469848b8605Smrg pipe_sampler_view_reference(&subpicture_priv->sampler, NULL); 470848b8605Smrg pipe_sampler_view_reference(&subpicture_priv->palette, NULL); 471848b8605Smrg FREE(subpicture_priv); 472848b8605Smrg 473848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p destroyed.\n", subpicture); 474848b8605Smrg 475848b8605Smrg return Success; 476848b8605Smrg} 477848b8605Smrg 478848b8605SmrgPUBLIC 479848b8605SmrgStatus XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette) 480848b8605Smrg{ 481848b8605Smrg XvMCSubpicturePrivate *subpicture_priv; 482848b8605Smrg XvMCContextPrivate *context_priv; 483848b8605Smrg struct pipe_context *pipe; 484848b8605Smrg struct pipe_box dst_box = {0, 0, 0, 0, 1, 1}; 485848b8605Smrg 486848b8605Smrg assert(dpy); 487848b8605Smrg assert(palette); 488848b8605Smrg 489848b8605Smrg if (!subpicture) 490848b8605Smrg return XvMCBadSubpicture; 491848b8605Smrg 492848b8605Smrg subpicture_priv = subpicture->privData; 493848b8605Smrg context_priv = subpicture_priv->context->privData; 494848b8605Smrg pipe = context_priv->pipe; 495848b8605Smrg 496848b8605Smrg dst_box.width = subpicture->num_palette_entries; 497848b8605Smrg 498848b8605Smrg upload_sampler(pipe, subpicture_priv->palette, &dst_box, palette, 0, 0, 0); 499848b8605Smrg 500848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Palette of Subpicture %p set.\n", subpicture); 501848b8605Smrg 502848b8605Smrg return Success; 503848b8605Smrg} 504848b8605Smrg 505848b8605SmrgPUBLIC 506848b8605SmrgStatus XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpicture *subpicture, 507848b8605Smrg short subx, short suby, unsigned short subw, unsigned short subh, 508848b8605Smrg short surfx, short surfy, unsigned short surfw, unsigned short surfh) 509848b8605Smrg{ 510848b8605Smrg struct u_rect src_rect = {subx, subx + subw, suby, suby + subh}; 511848b8605Smrg struct u_rect dst_rect = {surfx, surfx + surfw, surfy, surfy + surfh}; 512848b8605Smrg 513848b8605Smrg XvMCSurfacePrivate *surface_priv; 514848b8605Smrg XvMCSubpicturePrivate *subpicture_priv; 515848b8605Smrg 516848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Associating subpicture %p with surface %p.\n", subpicture, target_surface); 517848b8605Smrg 518848b8605Smrg assert(dpy); 519848b8605Smrg 520848b8605Smrg if (!target_surface) 521848b8605Smrg return XvMCBadSurface; 522848b8605Smrg 523848b8605Smrg if (!subpicture) 524848b8605Smrg return XvMCBadSubpicture; 525848b8605Smrg 526848b8605Smrg if (target_surface->context_id != subpicture->context_id) 527848b8605Smrg return BadMatch; 528848b8605Smrg 529848b8605Smrg /* TODO: Verify against subpicture independent scaling */ 530848b8605Smrg 531848b8605Smrg surface_priv = target_surface->privData; 532848b8605Smrg subpicture_priv = subpicture->privData; 533848b8605Smrg 534848b8605Smrg /* TODO: Assert rects are within bounds? Or clip? */ 535848b8605Smrg subpicture_priv->src_rect = src_rect; 536848b8605Smrg subpicture_priv->dst_rect = dst_rect; 537848b8605Smrg 538848b8605Smrg surface_priv->subpicture = subpicture; 539848b8605Smrg subpicture_priv->surface = target_surface; 540848b8605Smrg 541848b8605Smrg return Success; 542848b8605Smrg} 543848b8605Smrg 544848b8605SmrgPUBLIC 545848b8605SmrgStatus XvMCBlendSubpicture2(Display *dpy, XvMCSurface *source_surface, XvMCSurface *target_surface, 546848b8605Smrg XvMCSubpicture *subpicture, short subx, short suby, unsigned short subw, unsigned short subh, 547848b8605Smrg short surfx, short surfy, unsigned short surfw, unsigned short surfh) 548848b8605Smrg{ 549848b8605Smrg assert(dpy); 550848b8605Smrg 551848b8605Smrg if (!source_surface || !target_surface) 552848b8605Smrg return XvMCBadSurface; 553848b8605Smrg 554848b8605Smrg if (!subpicture) 555848b8605Smrg return XvMCBadSubpicture; 556848b8605Smrg 557848b8605Smrg if (source_surface->context_id != subpicture->context_id) 558848b8605Smrg return BadMatch; 559848b8605Smrg 560848b8605Smrg if (source_surface->context_id != subpicture->context_id) 561848b8605Smrg return BadMatch; 562848b8605Smrg 563848b8605Smrg /* TODO: Assert rects are within bounds? Or clip? */ 564848b8605Smrg 565848b8605Smrg return Success; 566848b8605Smrg} 567848b8605Smrg 568848b8605SmrgPUBLIC 569848b8605SmrgStatus XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture) 570848b8605Smrg{ 571848b8605Smrg assert(dpy); 572848b8605Smrg 573848b8605Smrg if (!subpicture) 574848b8605Smrg return XvMCBadSubpicture; 575848b8605Smrg 576848b8605Smrg return Success; 577848b8605Smrg} 578848b8605Smrg 579848b8605SmrgPUBLIC 580848b8605SmrgStatus XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture) 581848b8605Smrg{ 582848b8605Smrg assert(dpy); 583848b8605Smrg 584848b8605Smrg if (!subpicture) 585848b8605Smrg return XvMCBadSubpicture; 586848b8605Smrg 587848b8605Smrg return Success; 588848b8605Smrg} 589848b8605Smrg 590848b8605SmrgPUBLIC 591848b8605SmrgStatus XvMCGetSubpictureStatus(Display *dpy, XvMCSubpicture *subpicture, int *status) 592848b8605Smrg{ 593848b8605Smrg assert(dpy); 594848b8605Smrg 595848b8605Smrg if (!subpicture) 596848b8605Smrg return XvMCBadSubpicture; 597848b8605Smrg 598848b8605Smrg assert(status); 599848b8605Smrg 600848b8605Smrg /* TODO */ 601848b8605Smrg *status = 0; 602848b8605Smrg 603848b8605Smrg return Success; 604848b8605Smrg} 605