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