1/************************************************************************** 2 * 3 * Copyright 2010 Younes Manton og Thomas Balling Sørensen. 4 * All Rights Reserved. 5 * 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: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 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 VMWARE 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. 25 * 26 **************************************************************************/ 27 28#include "pipe/p_compiler.h" 29 30#include "util/u_memory.h" 31#include "util/u_debug.h" 32#include "util/format/u_format.h" 33#include "util/u_sampler.h" 34 35#include "vdpau_private.h" 36 37/** 38 * Create a VdpDevice object for use with X11. 39 */ 40PUBLIC VdpStatus 41vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device, 42 VdpGetProcAddress **get_proc_address) 43{ 44 struct pipe_screen *pscreen; 45 struct pipe_resource *res, res_tmpl; 46 struct pipe_sampler_view sv_tmpl; 47 vlVdpDevice *dev = NULL; 48 VdpStatus ret; 49 50 if (!(display && device && get_proc_address)) 51 return VDP_STATUS_INVALID_POINTER; 52 53 if (!vlCreateHTAB()) { 54 ret = VDP_STATUS_RESOURCES; 55 goto no_htab; 56 } 57 58 dev = CALLOC(1, sizeof(vlVdpDevice)); 59 if (!dev) { 60 ret = VDP_STATUS_RESOURCES; 61 goto no_dev; 62 } 63 64 pipe_reference_init(&dev->reference, 1); 65 66 dev->vscreen = vl_dri3_screen_create(display, screen); 67 if (!dev->vscreen) 68 dev->vscreen = vl_dri2_screen_create(display, screen); 69 if (!dev->vscreen) { 70 ret = VDP_STATUS_RESOURCES; 71 goto no_vscreen; 72 } 73 74 pscreen = dev->vscreen->pscreen; 75 dev->context = pipe_create_multimedia_context(pscreen); 76 if (!dev->context) { 77 ret = VDP_STATUS_RESOURCES; 78 goto no_context; 79 } 80 81 if (!pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES)) { 82 ret = VDP_STATUS_NO_IMPLEMENTATION; 83 goto no_context; 84 } 85 86 memset(&res_tmpl, 0, sizeof(res_tmpl)); 87 88 res_tmpl.target = PIPE_TEXTURE_2D; 89 res_tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM; 90 res_tmpl.width0 = 1; 91 res_tmpl.height0 = 1; 92 res_tmpl.depth0 = 1; 93 res_tmpl.array_size = 1; 94 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 95 res_tmpl.usage = PIPE_USAGE_DEFAULT; 96 97 if (!CheckSurfaceParams(pscreen, &res_tmpl)) { 98 ret = VDP_STATUS_NO_IMPLEMENTATION; 99 goto no_resource; 100 } 101 102 res = pscreen->resource_create(pscreen, &res_tmpl); 103 if (!res) { 104 ret = VDP_STATUS_RESOURCES; 105 goto no_resource; 106 } 107 108 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 109 u_sampler_view_default_template(&sv_tmpl, res, res->format); 110 111 sv_tmpl.swizzle_r = PIPE_SWIZZLE_1; 112 sv_tmpl.swizzle_g = PIPE_SWIZZLE_1; 113 sv_tmpl.swizzle_b = PIPE_SWIZZLE_1; 114 sv_tmpl.swizzle_a = PIPE_SWIZZLE_1; 115 116 dev->dummy_sv = dev->context->create_sampler_view(dev->context, res, &sv_tmpl); 117 pipe_resource_reference(&res, NULL); 118 if (!dev->dummy_sv) { 119 ret = VDP_STATUS_RESOURCES; 120 goto no_resource; 121 } 122 123 *device = vlAddDataHTAB(dev); 124 if (*device == 0) { 125 ret = VDP_STATUS_ERROR; 126 goto no_handle; 127 } 128 129 if (!vl_compositor_init(&dev->compositor, dev->context)) { 130 ret = VDP_STATUS_ERROR; 131 goto no_compositor; 132 } 133 134 (void) mtx_init(&dev->mutex, mtx_plain); 135 136 *get_proc_address = &vlVdpGetProcAddress; 137 138 return VDP_STATUS_OK; 139 140no_compositor: 141 vlRemoveDataHTAB(*device); 142no_handle: 143 pipe_sampler_view_reference(&dev->dummy_sv, NULL); 144no_resource: 145 dev->context->destroy(dev->context); 146no_context: 147 dev->vscreen->destroy(dev->vscreen); 148no_vscreen: 149 FREE(dev); 150no_dev: 151 vlDestroyHTAB(); 152no_htab: 153 return ret; 154} 155 156/** 157 * Create a VdpPresentationQueueTarget for use with X11. 158 */ 159VdpStatus 160vlVdpPresentationQueueTargetCreateX11(VdpDevice device, Drawable drawable, 161 VdpPresentationQueueTarget *target) 162{ 163 vlVdpPresentationQueueTarget *pqt; 164 VdpStatus ret; 165 166 if (!drawable) 167 return VDP_STATUS_INVALID_HANDLE; 168 169 vlVdpDevice *dev = vlGetDataHTAB(device); 170 if (!dev) 171 return VDP_STATUS_INVALID_HANDLE; 172 173 pqt = CALLOC(1, sizeof(vlVdpPresentationQueueTarget)); 174 if (!pqt) 175 return VDP_STATUS_RESOURCES; 176 177 DeviceReference(&pqt->device, dev); 178 pqt->drawable = drawable; 179 180 *target = vlAddDataHTAB(pqt); 181 if (*target == 0) { 182 ret = VDP_STATUS_ERROR; 183 goto no_handle; 184 } 185 186 return VDP_STATUS_OK; 187 188no_handle: 189 FREE(pqt); 190 return ret; 191} 192 193/** 194 * Destroy a VdpPresentationQueueTarget. 195 */ 196VdpStatus 197vlVdpPresentationQueueTargetDestroy(VdpPresentationQueueTarget presentation_queue_target) 198{ 199 vlVdpPresentationQueueTarget *pqt; 200 201 pqt = vlGetDataHTAB(presentation_queue_target); 202 if (!pqt) 203 return VDP_STATUS_INVALID_HANDLE; 204 205 vlRemoveDataHTAB(presentation_queue_target); 206 DeviceReference(&pqt->device, NULL); 207 FREE(pqt); 208 209 return VDP_STATUS_OK; 210} 211 212/** 213 * Destroy a VdpDevice. 214 */ 215VdpStatus 216vlVdpDeviceDestroy(VdpDevice device) 217{ 218 vlVdpDevice *dev = vlGetDataHTAB(device); 219 if (!dev) 220 return VDP_STATUS_INVALID_HANDLE; 221 222 vlRemoveDataHTAB(device); 223 DeviceReference(&dev, NULL); 224 225 return VDP_STATUS_OK; 226} 227 228/** 229 * Free a VdpDevice. 230 */ 231void 232vlVdpDeviceFree(vlVdpDevice *dev) 233{ 234 mtx_destroy(&dev->mutex); 235 vl_compositor_cleanup(&dev->compositor); 236 pipe_sampler_view_reference(&dev->dummy_sv, NULL); 237 dev->context->destroy(dev->context); 238 dev->vscreen->destroy(dev->vscreen); 239 FREE(dev); 240 vlDestroyHTAB(); 241} 242 243/** 244 * Retrieve a VDPAU function pointer. 245 */ 246VdpStatus 247vlVdpGetProcAddress(VdpDevice device, VdpFuncId function_id, void **function_pointer) 248{ 249 vlVdpDevice *dev = vlGetDataHTAB(device); 250 if (!dev) 251 return VDP_STATUS_INVALID_HANDLE; 252 253 if (!function_pointer) 254 return VDP_STATUS_INVALID_POINTER; 255 256 if (!vlGetFuncFTAB(function_id, function_pointer)) 257 return VDP_STATUS_INVALID_FUNC_ID; 258 259 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Got proc address %p for id %d\n", *function_pointer, function_id); 260 261 return VDP_STATUS_OK; 262} 263 264#define _ERROR_TYPE(TYPE,STRING) case TYPE: return STRING; 265 266/** 267 * Retrieve a string describing an error code. 268 */ 269char const * 270vlVdpGetErrorString (VdpStatus status) 271{ 272 switch (status) { 273 _ERROR_TYPE(VDP_STATUS_OK,"The operation completed successfully; no error."); 274 _ERROR_TYPE(VDP_STATUS_NO_IMPLEMENTATION,"No backend implementation could be loaded."); 275 _ERROR_TYPE(VDP_STATUS_DISPLAY_PREEMPTED,"The display was preempted, or a fatal error occurred. The application must re-initialize VDPAU."); 276 _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."); 277 _ERROR_TYPE(VDP_STATUS_INVALID_POINTER,"An invalid pointer was provided. Typically, this means that a NULL pointer was provided for an 'output' parameter."); 278 _ERROR_TYPE(VDP_STATUS_INVALID_CHROMA_TYPE,"An invalid/unsupported VdpChromaType value was supplied."); 279 _ERROR_TYPE(VDP_STATUS_INVALID_Y_CB_CR_FORMAT,"An invalid/unsupported VdpYCbCrFormat value was supplied."); 280 _ERROR_TYPE(VDP_STATUS_INVALID_RGBA_FORMAT,"An invalid/unsupported VdpRGBAFormat value was supplied."); 281 _ERROR_TYPE(VDP_STATUS_INVALID_INDEXED_FORMAT,"An invalid/unsupported VdpIndexedFormat value was supplied."); 282 _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_STANDARD,"An invalid/unsupported VdpColorStandard value was supplied."); 283 _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_TABLE_FORMAT,"An invalid/unsupported VdpColorTableFormat value was supplied."); 284 _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_FACTOR,"An invalid/unsupported VdpOutputSurfaceRenderBlendFactor value was supplied."); 285 _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_EQUATION,"An invalid/unsupported VdpOutputSurfaceRenderBlendEquation value was supplied."); 286 _ERROR_TYPE(VDP_STATUS_INVALID_FLAG,"An invalid/unsupported flag value/combination was supplied."); 287 _ERROR_TYPE(VDP_STATUS_INVALID_DECODER_PROFILE,"An invalid/unsupported VdpDecoderProfile value was supplied."); 288 _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE,"An invalid/unsupported VdpVideoMixerFeature value was supplied."); 289 _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER,"An invalid/unsupported VdpVideoMixerParameter value was supplied."); 290 _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE,"An invalid/unsupported VdpVideoMixerAttribute value was supplied."); 291 _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE,"An invalid/unsupported VdpVideoMixerPictureStructure value was supplied."); 292 _ERROR_TYPE(VDP_STATUS_INVALID_FUNC_ID,"An invalid/unsupported VdpFuncId value was supplied."); 293 _ERROR_TYPE(VDP_STATUS_INVALID_SIZE,"The size of a supplied object does not match the object it is being used with.\ 294 For example, a VdpVideoMixer is configured to process VdpVideoSurface objects of a specific size.\ 295 If presented with a VdpVideoSurface of a different size, this error will be raised."); 296 _ERROR_TYPE(VDP_STATUS_INVALID_VALUE,"An invalid/unsupported value was supplied.\ 297 This is a catch-all error code for values of type other than those with a specific error code."); 298 _ERROR_TYPE(VDP_STATUS_INVALID_STRUCT_VERSION,"An invalid/unsupported structure version was specified in a versioned structure. \ 299 This implies that the implementation is older than the header file the application was built against."); 300 _ERROR_TYPE(VDP_STATUS_RESOURCES,"The system does not have enough resources to complete the requested operation at this time."); 301 _ERROR_TYPE(VDP_STATUS_HANDLE_DEVICE_MISMATCH,"The set of handles supplied are not all related to the same VdpDevice.When performing operations \ 302 that operate on multiple surfaces, such as VdpOutputSurfaceRenderOutputSurface or VdpVideoMixerRender, \ 303 all supplied surfaces must have been created within the context of the same VdpDevice object. \ 304 This error is raised if they were not."); 305 _ERROR_TYPE(VDP_STATUS_ERROR,"A catch-all error, used when no other error code applies."); 306 default: return "Unknown Error"; 307 } 308} 309 310void 311vlVdpDefaultSamplerViewTemplate(struct pipe_sampler_view *templ, struct pipe_resource *res) 312{ 313 const struct util_format_description *desc; 314 315 memset(templ, 0, sizeof(*templ)); 316 u_sampler_view_default_template(templ, res, res->format); 317 318 desc = util_format_description(res->format); 319 if (desc->swizzle[0] == PIPE_SWIZZLE_0) 320 templ->swizzle_r = PIPE_SWIZZLE_1; 321 if (desc->swizzle[1] == PIPE_SWIZZLE_0) 322 templ->swizzle_g = PIPE_SWIZZLE_1; 323 if (desc->swizzle[2] == PIPE_SWIZZLE_0) 324 templ->swizzle_b = PIPE_SWIZZLE_1; 325 if (desc->swizzle[3] == PIPE_SWIZZLE_0) 326 templ->swizzle_a = PIPE_SWIZZLE_1; 327} 328