17ec681f3Smrg/************************************************************************** 27ec681f3Smrg * 37ec681f3Smrg * Copyright 2010 Younes Manton og Thomas Balling Sørensen. 47ec681f3Smrg * All Rights Reserved. 57ec681f3Smrg * 67ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 77ec681f3Smrg * copy of this software and associated documentation files (the 87ec681f3Smrg * "Software"), to deal in the Software without restriction, including 97ec681f3Smrg * without limitation the rights to use, copy, modify, merge, publish, 107ec681f3Smrg * distribute, sub license, and/or sell copies of the Software, and to 117ec681f3Smrg * permit persons to whom the Software is furnished to do so, subject to 127ec681f3Smrg * the following conditions: 137ec681f3Smrg * 147ec681f3Smrg * The above copyright notice and this permission notice (including the 157ec681f3Smrg * next paragraph) shall be included in all copies or substantial portions 167ec681f3Smrg * of the Software. 177ec681f3Smrg * 187ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 197ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 207ec681f3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 217ec681f3Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 227ec681f3Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 237ec681f3Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 247ec681f3Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 257ec681f3Smrg * 267ec681f3Smrg **************************************************************************/ 277ec681f3Smrg 287ec681f3Smrg#include "pipe/p_compiler.h" 297ec681f3Smrg 307ec681f3Smrg#include "util/u_memory.h" 317ec681f3Smrg#include "util/u_debug.h" 327ec681f3Smrg#include "util/format/u_format.h" 337ec681f3Smrg#include "util/u_sampler.h" 347ec681f3Smrg 357ec681f3Smrg#include "vdpau_private.h" 367ec681f3Smrg 377ec681f3Smrg/** 387ec681f3Smrg * Create a VdpDevice object for use with X11. 397ec681f3Smrg */ 407ec681f3SmrgPUBLIC VdpStatus 417ec681f3Smrgvdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device, 427ec681f3Smrg VdpGetProcAddress **get_proc_address) 437ec681f3Smrg{ 447ec681f3Smrg struct pipe_screen *pscreen; 457ec681f3Smrg struct pipe_resource *res, res_tmpl; 467ec681f3Smrg struct pipe_sampler_view sv_tmpl; 477ec681f3Smrg vlVdpDevice *dev = NULL; 487ec681f3Smrg VdpStatus ret; 497ec681f3Smrg 507ec681f3Smrg if (!(display && device && get_proc_address)) 517ec681f3Smrg return VDP_STATUS_INVALID_POINTER; 527ec681f3Smrg 537ec681f3Smrg if (!vlCreateHTAB()) { 547ec681f3Smrg ret = VDP_STATUS_RESOURCES; 557ec681f3Smrg goto no_htab; 567ec681f3Smrg } 577ec681f3Smrg 587ec681f3Smrg dev = CALLOC(1, sizeof(vlVdpDevice)); 597ec681f3Smrg if (!dev) { 607ec681f3Smrg ret = VDP_STATUS_RESOURCES; 617ec681f3Smrg goto no_dev; 627ec681f3Smrg } 637ec681f3Smrg 647ec681f3Smrg pipe_reference_init(&dev->reference, 1); 657ec681f3Smrg 667ec681f3Smrg dev->vscreen = vl_dri3_screen_create(display, screen); 677ec681f3Smrg if (!dev->vscreen) 687ec681f3Smrg dev->vscreen = vl_dri2_screen_create(display, screen); 697ec681f3Smrg if (!dev->vscreen) { 707ec681f3Smrg ret = VDP_STATUS_RESOURCES; 717ec681f3Smrg goto no_vscreen; 727ec681f3Smrg } 737ec681f3Smrg 747ec681f3Smrg pscreen = dev->vscreen->pscreen; 757ec681f3Smrg dev->context = pipe_create_multimedia_context(pscreen); 767ec681f3Smrg if (!dev->context) { 777ec681f3Smrg ret = VDP_STATUS_RESOURCES; 787ec681f3Smrg goto no_context; 797ec681f3Smrg } 807ec681f3Smrg 817ec681f3Smrg if (!pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES)) { 827ec681f3Smrg ret = VDP_STATUS_NO_IMPLEMENTATION; 837ec681f3Smrg goto no_context; 847ec681f3Smrg } 857ec681f3Smrg 867ec681f3Smrg memset(&res_tmpl, 0, sizeof(res_tmpl)); 877ec681f3Smrg 887ec681f3Smrg res_tmpl.target = PIPE_TEXTURE_2D; 897ec681f3Smrg res_tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM; 907ec681f3Smrg res_tmpl.width0 = 1; 917ec681f3Smrg res_tmpl.height0 = 1; 927ec681f3Smrg res_tmpl.depth0 = 1; 937ec681f3Smrg res_tmpl.array_size = 1; 947ec681f3Smrg res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 957ec681f3Smrg res_tmpl.usage = PIPE_USAGE_DEFAULT; 967ec681f3Smrg 977ec681f3Smrg if (!CheckSurfaceParams(pscreen, &res_tmpl)) { 987ec681f3Smrg ret = VDP_STATUS_NO_IMPLEMENTATION; 997ec681f3Smrg goto no_resource; 1007ec681f3Smrg } 1017ec681f3Smrg 1027ec681f3Smrg res = pscreen->resource_create(pscreen, &res_tmpl); 1037ec681f3Smrg if (!res) { 1047ec681f3Smrg ret = VDP_STATUS_RESOURCES; 1057ec681f3Smrg goto no_resource; 1067ec681f3Smrg } 1077ec681f3Smrg 1087ec681f3Smrg memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 1097ec681f3Smrg u_sampler_view_default_template(&sv_tmpl, res, res->format); 1107ec681f3Smrg 1117ec681f3Smrg sv_tmpl.swizzle_r = PIPE_SWIZZLE_1; 1127ec681f3Smrg sv_tmpl.swizzle_g = PIPE_SWIZZLE_1; 1137ec681f3Smrg sv_tmpl.swizzle_b = PIPE_SWIZZLE_1; 1147ec681f3Smrg sv_tmpl.swizzle_a = PIPE_SWIZZLE_1; 1157ec681f3Smrg 1167ec681f3Smrg dev->dummy_sv = dev->context->create_sampler_view(dev->context, res, &sv_tmpl); 1177ec681f3Smrg pipe_resource_reference(&res, NULL); 1187ec681f3Smrg if (!dev->dummy_sv) { 1197ec681f3Smrg ret = VDP_STATUS_RESOURCES; 1207ec681f3Smrg goto no_resource; 1217ec681f3Smrg } 1227ec681f3Smrg 1237ec681f3Smrg *device = vlAddDataHTAB(dev); 1247ec681f3Smrg if (*device == 0) { 1257ec681f3Smrg ret = VDP_STATUS_ERROR; 1267ec681f3Smrg goto no_handle; 1277ec681f3Smrg } 1287ec681f3Smrg 1297ec681f3Smrg if (!vl_compositor_init(&dev->compositor, dev->context)) { 1307ec681f3Smrg ret = VDP_STATUS_ERROR; 1317ec681f3Smrg goto no_compositor; 1327ec681f3Smrg } 1337ec681f3Smrg 1347ec681f3Smrg (void) mtx_init(&dev->mutex, mtx_plain); 1357ec681f3Smrg 1367ec681f3Smrg *get_proc_address = &vlVdpGetProcAddress; 1377ec681f3Smrg 1387ec681f3Smrg return VDP_STATUS_OK; 1397ec681f3Smrg 1407ec681f3Smrgno_compositor: 1417ec681f3Smrg vlRemoveDataHTAB(*device); 1427ec681f3Smrgno_handle: 1437ec681f3Smrg pipe_sampler_view_reference(&dev->dummy_sv, NULL); 1447ec681f3Smrgno_resource: 1457ec681f3Smrg dev->context->destroy(dev->context); 1467ec681f3Smrgno_context: 1477ec681f3Smrg dev->vscreen->destroy(dev->vscreen); 1487ec681f3Smrgno_vscreen: 1497ec681f3Smrg FREE(dev); 1507ec681f3Smrgno_dev: 1517ec681f3Smrg vlDestroyHTAB(); 1527ec681f3Smrgno_htab: 1537ec681f3Smrg return ret; 1547ec681f3Smrg} 1557ec681f3Smrg 1567ec681f3Smrg/** 1577ec681f3Smrg * Create a VdpPresentationQueueTarget for use with X11. 1587ec681f3Smrg */ 1597ec681f3SmrgVdpStatus 1607ec681f3SmrgvlVdpPresentationQueueTargetCreateX11(VdpDevice device, Drawable drawable, 1617ec681f3Smrg VdpPresentationQueueTarget *target) 1627ec681f3Smrg{ 1637ec681f3Smrg vlVdpPresentationQueueTarget *pqt; 1647ec681f3Smrg VdpStatus ret; 1657ec681f3Smrg 1667ec681f3Smrg if (!drawable) 1677ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 1687ec681f3Smrg 1697ec681f3Smrg vlVdpDevice *dev = vlGetDataHTAB(device); 1707ec681f3Smrg if (!dev) 1717ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 1727ec681f3Smrg 1737ec681f3Smrg pqt = CALLOC(1, sizeof(vlVdpPresentationQueueTarget)); 1747ec681f3Smrg if (!pqt) 1757ec681f3Smrg return VDP_STATUS_RESOURCES; 1767ec681f3Smrg 1777ec681f3Smrg DeviceReference(&pqt->device, dev); 1787ec681f3Smrg pqt->drawable = drawable; 1797ec681f3Smrg 1807ec681f3Smrg *target = vlAddDataHTAB(pqt); 1817ec681f3Smrg if (*target == 0) { 1827ec681f3Smrg ret = VDP_STATUS_ERROR; 1837ec681f3Smrg goto no_handle; 1847ec681f3Smrg } 1857ec681f3Smrg 1867ec681f3Smrg return VDP_STATUS_OK; 1877ec681f3Smrg 1887ec681f3Smrgno_handle: 1897ec681f3Smrg FREE(pqt); 1907ec681f3Smrg return ret; 1917ec681f3Smrg} 1927ec681f3Smrg 1937ec681f3Smrg/** 1947ec681f3Smrg * Destroy a VdpPresentationQueueTarget. 1957ec681f3Smrg */ 1967ec681f3SmrgVdpStatus 1977ec681f3SmrgvlVdpPresentationQueueTargetDestroy(VdpPresentationQueueTarget presentation_queue_target) 1987ec681f3Smrg{ 1997ec681f3Smrg vlVdpPresentationQueueTarget *pqt; 2007ec681f3Smrg 2017ec681f3Smrg pqt = vlGetDataHTAB(presentation_queue_target); 2027ec681f3Smrg if (!pqt) 2037ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 2047ec681f3Smrg 2057ec681f3Smrg vlRemoveDataHTAB(presentation_queue_target); 2067ec681f3Smrg DeviceReference(&pqt->device, NULL); 2077ec681f3Smrg FREE(pqt); 2087ec681f3Smrg 2097ec681f3Smrg return VDP_STATUS_OK; 2107ec681f3Smrg} 2117ec681f3Smrg 2127ec681f3Smrg/** 2137ec681f3Smrg * Destroy a VdpDevice. 2147ec681f3Smrg */ 2157ec681f3SmrgVdpStatus 2167ec681f3SmrgvlVdpDeviceDestroy(VdpDevice device) 2177ec681f3Smrg{ 2187ec681f3Smrg vlVdpDevice *dev = vlGetDataHTAB(device); 2197ec681f3Smrg if (!dev) 2207ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 2217ec681f3Smrg 2227ec681f3Smrg vlRemoveDataHTAB(device); 2237ec681f3Smrg DeviceReference(&dev, NULL); 2247ec681f3Smrg 2257ec681f3Smrg return VDP_STATUS_OK; 2267ec681f3Smrg} 2277ec681f3Smrg 2287ec681f3Smrg/** 2297ec681f3Smrg * Free a VdpDevice. 2307ec681f3Smrg */ 2317ec681f3Smrgvoid 2327ec681f3SmrgvlVdpDeviceFree(vlVdpDevice *dev) 2337ec681f3Smrg{ 2347ec681f3Smrg mtx_destroy(&dev->mutex); 2357ec681f3Smrg vl_compositor_cleanup(&dev->compositor); 2367ec681f3Smrg pipe_sampler_view_reference(&dev->dummy_sv, NULL); 2377ec681f3Smrg dev->context->destroy(dev->context); 2387ec681f3Smrg dev->vscreen->destroy(dev->vscreen); 2397ec681f3Smrg FREE(dev); 2407ec681f3Smrg vlDestroyHTAB(); 2417ec681f3Smrg} 2427ec681f3Smrg 2437ec681f3Smrg/** 2447ec681f3Smrg * Retrieve a VDPAU function pointer. 2457ec681f3Smrg */ 2467ec681f3SmrgVdpStatus 2477ec681f3SmrgvlVdpGetProcAddress(VdpDevice device, VdpFuncId function_id, void **function_pointer) 2487ec681f3Smrg{ 2497ec681f3Smrg vlVdpDevice *dev = vlGetDataHTAB(device); 2507ec681f3Smrg if (!dev) 2517ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 2527ec681f3Smrg 2537ec681f3Smrg if (!function_pointer) 2547ec681f3Smrg return VDP_STATUS_INVALID_POINTER; 2557ec681f3Smrg 2567ec681f3Smrg if (!vlGetFuncFTAB(function_id, function_pointer)) 2577ec681f3Smrg return VDP_STATUS_INVALID_FUNC_ID; 2587ec681f3Smrg 2597ec681f3Smrg VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Got proc address %p for id %d\n", *function_pointer, function_id); 2607ec681f3Smrg 2617ec681f3Smrg return VDP_STATUS_OK; 2627ec681f3Smrg} 2637ec681f3Smrg 2647ec681f3Smrg#define _ERROR_TYPE(TYPE,STRING) case TYPE: return STRING; 2657ec681f3Smrg 2667ec681f3Smrg/** 2677ec681f3Smrg * Retrieve a string describing an error code. 2687ec681f3Smrg */ 2697ec681f3Smrgchar const * 2707ec681f3SmrgvlVdpGetErrorString (VdpStatus status) 2717ec681f3Smrg{ 2727ec681f3Smrg switch (status) { 2737ec681f3Smrg _ERROR_TYPE(VDP_STATUS_OK,"The operation completed successfully; no error."); 2747ec681f3Smrg _ERROR_TYPE(VDP_STATUS_NO_IMPLEMENTATION,"No backend implementation could be loaded."); 2757ec681f3Smrg _ERROR_TYPE(VDP_STATUS_DISPLAY_PREEMPTED,"The display was preempted, or a fatal error occurred. The application must re-initialize VDPAU."); 2767ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_HANDLE,"An invalid handle value was provided. Either the handle does not exist at all, or refers to an object of an incorrect type."); 2777ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_POINTER,"An invalid pointer was provided. Typically, this means that a NULL pointer was provided for an 'output' parameter."); 2787ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_CHROMA_TYPE,"An invalid/unsupported VdpChromaType value was supplied."); 2797ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_Y_CB_CR_FORMAT,"An invalid/unsupported VdpYCbCrFormat value was supplied."); 2807ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_RGBA_FORMAT,"An invalid/unsupported VdpRGBAFormat value was supplied."); 2817ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_INDEXED_FORMAT,"An invalid/unsupported VdpIndexedFormat value was supplied."); 2827ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_STANDARD,"An invalid/unsupported VdpColorStandard value was supplied."); 2837ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_TABLE_FORMAT,"An invalid/unsupported VdpColorTableFormat value was supplied."); 2847ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_FACTOR,"An invalid/unsupported VdpOutputSurfaceRenderBlendFactor value was supplied."); 2857ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_EQUATION,"An invalid/unsupported VdpOutputSurfaceRenderBlendEquation value was supplied."); 2867ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_FLAG,"An invalid/unsupported flag value/combination was supplied."); 2877ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_DECODER_PROFILE,"An invalid/unsupported VdpDecoderProfile value was supplied."); 2887ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE,"An invalid/unsupported VdpVideoMixerFeature value was supplied."); 2897ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER,"An invalid/unsupported VdpVideoMixerParameter value was supplied."); 2907ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE,"An invalid/unsupported VdpVideoMixerAttribute value was supplied."); 2917ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE,"An invalid/unsupported VdpVideoMixerPictureStructure value was supplied."); 2927ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_FUNC_ID,"An invalid/unsupported VdpFuncId value was supplied."); 2937ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_SIZE,"The size of a supplied object does not match the object it is being used with.\ 2947ec681f3Smrg For example, a VdpVideoMixer is configured to process VdpVideoSurface objects of a specific size.\ 2957ec681f3Smrg If presented with a VdpVideoSurface of a different size, this error will be raised."); 2967ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_VALUE,"An invalid/unsupported value was supplied.\ 2977ec681f3Smrg This is a catch-all error code for values of type other than those with a specific error code."); 2987ec681f3Smrg _ERROR_TYPE(VDP_STATUS_INVALID_STRUCT_VERSION,"An invalid/unsupported structure version was specified in a versioned structure. \ 2997ec681f3Smrg This implies that the implementation is older than the header file the application was built against."); 3007ec681f3Smrg _ERROR_TYPE(VDP_STATUS_RESOURCES,"The system does not have enough resources to complete the requested operation at this time."); 3017ec681f3Smrg _ERROR_TYPE(VDP_STATUS_HANDLE_DEVICE_MISMATCH,"The set of handles supplied are not all related to the same VdpDevice.When performing operations \ 3027ec681f3Smrg that operate on multiple surfaces, such as VdpOutputSurfaceRenderOutputSurface or VdpVideoMixerRender, \ 3037ec681f3Smrg all supplied surfaces must have been created within the context of the same VdpDevice object. \ 3047ec681f3Smrg This error is raised if they were not."); 3057ec681f3Smrg _ERROR_TYPE(VDP_STATUS_ERROR,"A catch-all error, used when no other error code applies."); 3067ec681f3Smrg default: return "Unknown Error"; 3077ec681f3Smrg } 3087ec681f3Smrg} 3097ec681f3Smrg 3107ec681f3Smrgvoid 3117ec681f3SmrgvlVdpDefaultSamplerViewTemplate(struct pipe_sampler_view *templ, struct pipe_resource *res) 3127ec681f3Smrg{ 3137ec681f3Smrg const struct util_format_description *desc; 3147ec681f3Smrg 3157ec681f3Smrg memset(templ, 0, sizeof(*templ)); 3167ec681f3Smrg u_sampler_view_default_template(templ, res, res->format); 3177ec681f3Smrg 3187ec681f3Smrg desc = util_format_description(res->format); 3197ec681f3Smrg if (desc->swizzle[0] == PIPE_SWIZZLE_0) 3207ec681f3Smrg templ->swizzle_r = PIPE_SWIZZLE_1; 3217ec681f3Smrg if (desc->swizzle[1] == PIPE_SWIZZLE_0) 3227ec681f3Smrg templ->swizzle_g = PIPE_SWIZZLE_1; 3237ec681f3Smrg if (desc->swizzle[2] == PIPE_SWIZZLE_0) 3247ec681f3Smrg templ->swizzle_b = PIPE_SWIZZLE_1; 3257ec681f3Smrg if (desc->swizzle[3] == PIPE_SWIZZLE_0) 3267ec681f3Smrg templ->swizzle_a = PIPE_SWIZZLE_1; 3277ec681f3Smrg} 328