1 /**************************************************************************
3 * Copyright 2013 Advanced Micro Devices, Inc.
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 THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 **************************************************************************/
30 * Christian König <christian.koenig@amd.com>
36 #include "glformats.h"
37 #include "hash_table.h"
43 #define MAX_TEXTURES 4
48 struct gl_texture_object
*textures
[MAX_TEXTURES
];
51 const GLvoid
*vdpSurface
;
55 _mesa_VDPAUInitNV(const GLvoid
*vdpDevice
, const GLvoid
*getProcAddress
)
57 GET_CURRENT_CONTEXT(ctx
);
60 _mesa_error(ctx
, GL_INVALID_VALUE
, "vdpDevice");
64 if (!getProcAddress
) {
65 _mesa_error(ctx
, GL_INVALID_VALUE
, "getProcAddress");
69 if (ctx
->vdpDevice
|| ctx
->vdpGetProcAddress
|| ctx
->vdpSurfaces
) {
70 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUInitNV");
74 ctx
->vdpDevice
= vdpDevice
;
75 ctx
->vdpGetProcAddress
= getProcAddress
;
76 ctx
->vdpSurfaces
= _mesa_set_create(NULL
, _mesa_key_pointer_equal
);
80 unregister_surface(struct set_entry
*entry
)
82 struct vdp_surface
*surf
= (struct vdp_surface
*)entry
->key
;
83 GET_CURRENT_CONTEXT(ctx
);
85 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
86 GLintptr surfaces
[] = { (GLintptr
)surf
};
87 _mesa_VDPAUUnmapSurfacesNV(1, surfaces
);
90 _mesa_set_remove(ctx
->vdpSurfaces
, entry
);
95 _mesa_VDPAUFiniNV(void)
97 GET_CURRENT_CONTEXT(ctx
);
99 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
100 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUFiniNV");
104 _mesa_set_destroy(ctx
->vdpSurfaces
, unregister_surface
);
107 ctx
->vdpGetProcAddress
= 0;
108 ctx
->vdpSurfaces
= NULL
;
112 register_surface(struct gl_context
*ctx
, GLboolean isOutput
,
113 const GLvoid
*vdpSurface
, GLenum target
,
114 GLsizei numTextureNames
, const GLuint
*textureNames
)
116 struct vdp_surface
*surf
;
119 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
120 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAURegisterSurfaceNV");
121 return (GLintptr
)NULL
;
124 if (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE
) {
125 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAURegisterSurfaceNV");
126 return (GLintptr
)NULL
;
129 if (target
== GL_TEXTURE_RECTANGLE
&& !ctx
->Extensions
.NV_texture_rectangle
) {
130 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAURegisterSurfaceNV");
131 return (GLintptr
)NULL
;
134 surf
= CALLOC_STRUCT( vdp_surface
);
135 surf
->vdpSurface
= vdpSurface
;
136 surf
->target
= target
;
137 surf
->access
= GL_READ_WRITE
;
138 surf
->state
= GL_SURFACE_REGISTERED_NV
;
139 surf
->output
= isOutput
;
140 for (i
= 0; i
< numTextureNames
; ++i
) {
141 struct gl_texture_object
*tex
;
142 tex
= _mesa_lookup_texture(ctx
, textureNames
[i
]);
144 _mesa_lock_texture(ctx
, tex
);
146 if (tex
->Immutable
) {
147 _mesa_unlock_texture(ctx
, tex
);
149 _mesa_error(ctx
, GL_INVALID_OPERATION
,
150 "VDPAURegisterSurfaceNV(texture is immutable)");
151 return (GLintptr
)NULL
;
154 if (tex
->Target
== 0)
155 tex
->Target
= target
;
156 else if (tex
->Target
!= target
) {
157 _mesa_unlock_texture(ctx
, tex
);
159 _mesa_error(ctx
, GL_INVALID_OPERATION
,
160 "VDPAURegisterSurfaceNV(target mismatch)");
161 return (GLintptr
)NULL
;
164 /* This will disallow respecifying the storage. */
165 tex
->Immutable
= GL_TRUE
;
166 _mesa_unlock_texture(ctx
, tex
);
168 _mesa_reference_texobj(&surf
->textures
[i
], tex
);
171 _mesa_set_add(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
);
173 return (GLintptr
)surf
;
177 _mesa_VDPAURegisterVideoSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
178 GLsizei numTextureNames
,
179 const GLuint
*textureNames
)
181 GET_CURRENT_CONTEXT(ctx
);
183 if (numTextureNames
!= 4) {
184 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
185 return (GLintptr
)NULL
;
188 return register_surface(ctx
, false, vdpSurface
, target
,
189 numTextureNames
, textureNames
);
193 _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
194 GLsizei numTextureNames
,
195 const GLuint
*textureNames
)
197 GET_CURRENT_CONTEXT(ctx
);
199 if (numTextureNames
!= 1) {
200 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
201 return (GLintptr
)NULL
;
204 return register_surface(ctx
, true, vdpSurface
, target
,
205 numTextureNames
, textureNames
);
209 _mesa_VDPAUIsSurfaceNV(GLintptr surface
)
211 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
212 GET_CURRENT_CONTEXT(ctx
);
214 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
215 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUIsSurfaceNV");
219 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
227 _mesa_VDPAUUnregisterSurfaceNV(GLintptr surface
)
229 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
230 struct set_entry
*entry
;
232 GET_CURRENT_CONTEXT(ctx
);
234 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
235 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnregisterSurfaceNV");
239 /* according to the spec it's ok when this is zero */
243 entry
= _mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
);
245 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUUnregisterSurfaceNV");
249 for (i
= 0; i
< MAX_TEXTURES
; i
++) {
250 if (surf
->textures
[i
]) {
251 surf
->textures
[i
]->Immutable
= GL_FALSE
;
252 _mesa_reference_texobj(&surf
->textures
[i
], NULL
);
256 _mesa_set_remove(ctx
->vdpSurfaces
, entry
);
261 _mesa_VDPAUGetSurfaceivNV(GLintptr surface
, GLenum pname
, GLsizei bufSize
,
262 GLsizei
*length
, GLint
*values
)
264 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
265 GET_CURRENT_CONTEXT(ctx
);
267 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
268 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUGetSurfaceivNV");
272 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
273 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
277 if (pname
!= GL_SURFACE_STATE_NV
) {
278 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAUGetSurfaceivNV");
283 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
287 values
[0] = surf
->state
;
294 _mesa_VDPAUSurfaceAccessNV(GLintptr surface
, GLenum access
)
296 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
297 GET_CURRENT_CONTEXT(ctx
);
299 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
300 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
304 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
305 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
309 if (access
!= GL_READ_ONLY
&& access
!= GL_WRITE_ONLY
&&
310 access
!= GL_READ_WRITE
) {
312 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
316 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
317 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
321 surf
->access
= access
;
325 _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
327 GET_CURRENT_CONTEXT(ctx
);
330 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
331 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
335 for (i
= 0; i
< numSurfaces
; ++i
) {
336 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
338 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
339 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
343 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
344 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
349 for (i
= 0; i
< numSurfaces
; ++i
) {
350 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
351 unsigned numTextureNames
= surf
->output
? 1 : 4;
354 for (j
= 0; j
< numTextureNames
; ++j
) {
355 struct gl_texture_object
*tex
= surf
->textures
[j
];
356 struct gl_texture_image
*image
;
358 _mesa_lock_texture(ctx
, tex
);
359 image
= _mesa_get_tex_image(ctx
, tex
, surf
->target
, 0);
361 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "VDPAUMapSurfacesNV");
362 _mesa_unlock_texture(ctx
, tex
);
366 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
368 ctx
->Driver
.VDPAUMapSurface(ctx
, surf
->target
, surf
->access
,
369 surf
->output
, tex
, image
,
370 surf
->vdpSurface
, j
);
372 _mesa_unlock_texture(ctx
, tex
);
374 surf
->state
= GL_SURFACE_MAPPED_NV
;
379 _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
381 GET_CURRENT_CONTEXT(ctx
);
384 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
385 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
389 for (i
= 0; i
< numSurfaces
; ++i
) {
390 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
392 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
393 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
397 if (surf
->state
!= GL_SURFACE_MAPPED_NV
) {
398 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
403 for (i
= 0; i
< numSurfaces
; ++i
) {
404 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
405 unsigned numTextureNames
= surf
->output
? 1 : 4;
408 for (j
= 0; j
< numTextureNames
; ++j
) {
409 struct gl_texture_object
*tex
= surf
->textures
[j
];
410 struct gl_texture_image
*image
;
412 _mesa_lock_texture(ctx
, tex
);
414 image
= _mesa_select_tex_image(ctx
, tex
, surf
->target
, 0);
416 ctx
->Driver
.VDPAUUnmapSurface(ctx
, surf
->target
, surf
->access
,
417 surf
->output
, tex
, image
,
418 surf
->vdpSurface
, j
);
421 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
423 _mesa_unlock_texture(ctx
, tex
);
425 surf
->state
= GL_SURFACE_REGISTERED_NV
;