vdpau.c revision 01e04c3f
1af69d88dSmrg/**************************************************************************
2af69d88dSmrg *
3af69d88dSmrg * Copyright 2013 Advanced Micro Devices, Inc.
4af69d88dSmrg * All Rights Reserved.
5af69d88dSmrg *
6af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
7af69d88dSmrg * copy of this software and associated documentation files (the
8af69d88dSmrg * "Software"), to deal in the Software without restriction, including
9af69d88dSmrg * without limitation the rights to use, copy, modify, merge, publish,
10af69d88dSmrg * distribute, sub license, and/or sell copies of the Software, and to
11af69d88dSmrg * permit persons to whom the Software is furnished to do so, subject to
12af69d88dSmrg * the following conditions:
13af69d88dSmrg *
14af69d88dSmrg * The above copyright notice and this permission notice (including the
15af69d88dSmrg * next paragraph) shall be included in all copies or substantial portions
16af69d88dSmrg * of the Software.
17af69d88dSmrg *
18af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19af69d88dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20af69d88dSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21af69d88dSmrg * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22af69d88dSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23af69d88dSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24af69d88dSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25af69d88dSmrg *
26af69d88dSmrg **************************************************************************/
27af69d88dSmrg
28af69d88dSmrg/*
29af69d88dSmrg * Authors:
30af69d88dSmrg *      Christian König <christian.koenig@amd.com>
31af69d88dSmrg *
32af69d88dSmrg */
33af69d88dSmrg
34af69d88dSmrg#include <stdbool.h>
35af69d88dSmrg#include "util/hash_table.h"
3601e04c3fSmrg#include "util/set.h"
37af69d88dSmrg#include "context.h"
38af69d88dSmrg#include "glformats.h"
39af69d88dSmrg#include "texobj.h"
40af69d88dSmrg#include "teximage.h"
41af69d88dSmrg#include "vdpau.h"
42af69d88dSmrg
43af69d88dSmrg#define MAX_TEXTURES 4
44af69d88dSmrg
45af69d88dSmrgstruct vdp_surface
46af69d88dSmrg{
47af69d88dSmrg   GLenum target;
48af69d88dSmrg   struct gl_texture_object *textures[MAX_TEXTURES];
49af69d88dSmrg   GLenum access, state;
50af69d88dSmrg   GLboolean output;
51af69d88dSmrg   const GLvoid *vdpSurface;
52af69d88dSmrg};
53af69d88dSmrg
54af69d88dSmrgvoid GLAPIENTRY
55af69d88dSmrg_mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress)
56af69d88dSmrg{
57af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
58af69d88dSmrg
59af69d88dSmrg   if (!vdpDevice) {
60af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "vdpDevice");
61af69d88dSmrg      return;
62af69d88dSmrg   }
63af69d88dSmrg
64af69d88dSmrg   if (!getProcAddress) {
65af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "getProcAddress");
66af69d88dSmrg      return;
67af69d88dSmrg   }
68af69d88dSmrg
69af69d88dSmrg   if (ctx->vdpDevice || ctx->vdpGetProcAddress || ctx->vdpSurfaces) {
70af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUInitNV");
71af69d88dSmrg      return;
72af69d88dSmrg   }
73af69d88dSmrg
74af69d88dSmrg   ctx->vdpDevice = vdpDevice;
75af69d88dSmrg   ctx->vdpGetProcAddress = getProcAddress;
7601e04c3fSmrg   ctx->vdpSurfaces = _mesa_set_create(NULL, _mesa_hash_pointer,
7701e04c3fSmrg                                       _mesa_key_pointer_equal);
78af69d88dSmrg}
79af69d88dSmrg
80af69d88dSmrgstatic void
81af69d88dSmrgunregister_surface(struct set_entry *entry)
82af69d88dSmrg{
83af69d88dSmrg   struct vdp_surface *surf = (struct vdp_surface *)entry->key;
84af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
85af69d88dSmrg
86af69d88dSmrg   if (surf->state == GL_SURFACE_MAPPED_NV) {
87af69d88dSmrg      GLintptr surfaces[] = { (GLintptr)surf };
88af69d88dSmrg      _mesa_VDPAUUnmapSurfacesNV(1, surfaces);
89af69d88dSmrg   }
90af69d88dSmrg
91af69d88dSmrg   _mesa_set_remove(ctx->vdpSurfaces, entry);
92af69d88dSmrg   free(surf);
93af69d88dSmrg}
94af69d88dSmrg
95af69d88dSmrgvoid GLAPIENTRY
96af69d88dSmrg_mesa_VDPAUFiniNV(void)
97af69d88dSmrg{
98af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
99af69d88dSmrg
100af69d88dSmrg   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
101af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUFiniNV");
102af69d88dSmrg      return;
103af69d88dSmrg   }
104af69d88dSmrg
105af69d88dSmrg   _mesa_set_destroy(ctx->vdpSurfaces, unregister_surface);
106af69d88dSmrg
107af69d88dSmrg   ctx->vdpDevice = 0;
108af69d88dSmrg   ctx->vdpGetProcAddress = 0;
109af69d88dSmrg   ctx->vdpSurfaces = NULL;
110af69d88dSmrg}
111af69d88dSmrg
112af69d88dSmrgstatic GLintptr
113af69d88dSmrgregister_surface(struct gl_context *ctx, GLboolean isOutput,
114af69d88dSmrg                 const GLvoid *vdpSurface, GLenum target,
115af69d88dSmrg                 GLsizei numTextureNames, const GLuint *textureNames)
116af69d88dSmrg{
117af69d88dSmrg   struct vdp_surface *surf;
118af69d88dSmrg   int i;
119af69d88dSmrg
120af69d88dSmrg   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
121af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAURegisterSurfaceNV");
122af69d88dSmrg      return (GLintptr)NULL;
123af69d88dSmrg   }
124af69d88dSmrg
125af69d88dSmrg   if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE) {
126af69d88dSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV");
127af69d88dSmrg      return (GLintptr)NULL;
128af69d88dSmrg   }
129af69d88dSmrg
130af69d88dSmrg   if (target == GL_TEXTURE_RECTANGLE && !ctx->Extensions.NV_texture_rectangle) {
131af69d88dSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV");
132af69d88dSmrg      return (GLintptr)NULL;
133af69d88dSmrg   }
134af69d88dSmrg
135af69d88dSmrg   surf = CALLOC_STRUCT( vdp_surface );
136af69d88dSmrg   if (surf == NULL) {
137af69d88dSmrg      _mesa_error_no_memory("VDPAURegisterSurfaceNV");
138af69d88dSmrg      return (GLintptr)NULL;
139af69d88dSmrg   }
140af69d88dSmrg
141af69d88dSmrg   surf->vdpSurface = vdpSurface;
142af69d88dSmrg   surf->target = target;
143af69d88dSmrg   surf->access = GL_READ_WRITE;
144af69d88dSmrg   surf->state = GL_SURFACE_REGISTERED_NV;
145af69d88dSmrg   surf->output = isOutput;
146af69d88dSmrg   for (i = 0; i < numTextureNames; ++i) {
147af69d88dSmrg      struct gl_texture_object *tex;
14801e04c3fSmrg
14901e04c3fSmrg      tex = _mesa_lookup_texture_err(ctx, textureNames[i],
15001e04c3fSmrg                                     "VDPAURegisterSurfaceNV");
151af69d88dSmrg      if (tex == NULL) {
152af69d88dSmrg         free(surf);
153af69d88dSmrg         return (GLintptr)NULL;
154af69d88dSmrg      }
155af69d88dSmrg
156af69d88dSmrg      _mesa_lock_texture(ctx, tex);
157af69d88dSmrg
158af69d88dSmrg      if (tex->Immutable) {
159af69d88dSmrg         _mesa_unlock_texture(ctx, tex);
160af69d88dSmrg         free(surf);
161af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
162af69d88dSmrg                     "VDPAURegisterSurfaceNV(texture is immutable)");
163af69d88dSmrg         return (GLintptr)NULL;
164af69d88dSmrg      }
165af69d88dSmrg
16601e04c3fSmrg      if (tex->Target == 0) {
167af69d88dSmrg         tex->Target = target;
16801e04c3fSmrg         tex->TargetIndex = _mesa_tex_target_to_index(ctx, target);
16901e04c3fSmrg      } else if (tex->Target != target) {
170af69d88dSmrg         _mesa_unlock_texture(ctx, tex);
171af69d88dSmrg         free(surf);
172af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
173af69d88dSmrg                     "VDPAURegisterSurfaceNV(target mismatch)");
174af69d88dSmrg         return (GLintptr)NULL;
175af69d88dSmrg      }
176af69d88dSmrg
177af69d88dSmrg      /* This will disallow respecifying the storage. */
178af69d88dSmrg      tex->Immutable = GL_TRUE;
179af69d88dSmrg      _mesa_unlock_texture(ctx, tex);
180af69d88dSmrg
181af69d88dSmrg      _mesa_reference_texobj(&surf->textures[i], tex);
182af69d88dSmrg   }
183af69d88dSmrg
18401e04c3fSmrg   _mesa_set_add(ctx->vdpSurfaces, surf);
185af69d88dSmrg
186af69d88dSmrg   return (GLintptr)surf;
187af69d88dSmrg}
188af69d88dSmrg
189af69d88dSmrgGLintptr GLAPIENTRY
190af69d88dSmrg_mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target,
191af69d88dSmrg                                  GLsizei numTextureNames,
192af69d88dSmrg                                  const GLuint *textureNames)
193af69d88dSmrg{
194af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
195af69d88dSmrg
196af69d88dSmrg   if (numTextureNames != 4) {
197af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV");
198af69d88dSmrg      return (GLintptr)NULL;
199af69d88dSmrg   }
200af69d88dSmrg
201af69d88dSmrg   return register_surface(ctx, false, vdpSurface, target,
202af69d88dSmrg                           numTextureNames, textureNames);
203af69d88dSmrg}
204af69d88dSmrg
205af69d88dSmrgGLintptr GLAPIENTRY
206af69d88dSmrg_mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target,
207af69d88dSmrg                                   GLsizei numTextureNames,
208af69d88dSmrg                                   const GLuint *textureNames)
209af69d88dSmrg{
210af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
211af69d88dSmrg
212af69d88dSmrg   if (numTextureNames != 1) {
213af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV");
214af69d88dSmrg      return (GLintptr)NULL;
215af69d88dSmrg   }
216af69d88dSmrg
217af69d88dSmrg   return register_surface(ctx, true, vdpSurface, target,
218af69d88dSmrg                           numTextureNames, textureNames);
219af69d88dSmrg}
220af69d88dSmrg
221af69d88dSmrgGLboolean GLAPIENTRY
222af69d88dSmrg_mesa_VDPAUIsSurfaceNV(GLintptr surface)
223af69d88dSmrg{
224af69d88dSmrg   struct vdp_surface *surf = (struct vdp_surface *)surface;
225af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
226af69d88dSmrg
227af69d88dSmrg   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
228af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUIsSurfaceNV");
229af69d88dSmrg      return false;
230af69d88dSmrg   }
231af69d88dSmrg
23201e04c3fSmrg   if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
233af69d88dSmrg      return false;
234af69d88dSmrg   }
235af69d88dSmrg
236af69d88dSmrg   return true;
237af69d88dSmrg}
238af69d88dSmrg
239af69d88dSmrgvoid GLAPIENTRY
240af69d88dSmrg_mesa_VDPAUUnregisterSurfaceNV(GLintptr surface)
241af69d88dSmrg{
242af69d88dSmrg   struct vdp_surface *surf = (struct vdp_surface *)surface;
243af69d88dSmrg   struct set_entry *entry;
244af69d88dSmrg   int i;
245af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
246af69d88dSmrg
247af69d88dSmrg   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
248af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnregisterSurfaceNV");
249af69d88dSmrg      return;
250af69d88dSmrg   }
251af69d88dSmrg
252af69d88dSmrg   /* according to the spec it's ok when this is zero */
253af69d88dSmrg   if (surface == 0)
254af69d88dSmrg      return;
255af69d88dSmrg
25601e04c3fSmrg   entry = _mesa_set_search(ctx->vdpSurfaces, surf);
257af69d88dSmrg   if (!entry) {
258af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUUnregisterSurfaceNV");
259af69d88dSmrg      return;
260af69d88dSmrg   }
261af69d88dSmrg
262af69d88dSmrg   for (i = 0; i < MAX_TEXTURES; i++) {
263af69d88dSmrg      if (surf->textures[i]) {
264af69d88dSmrg         surf->textures[i]->Immutable = GL_FALSE;
265af69d88dSmrg         _mesa_reference_texobj(&surf->textures[i], NULL);
266af69d88dSmrg      }
267af69d88dSmrg   }
268af69d88dSmrg
269af69d88dSmrg   _mesa_set_remove(ctx->vdpSurfaces, entry);
270af69d88dSmrg   free(surf);
271af69d88dSmrg}
272af69d88dSmrg
273af69d88dSmrgvoid GLAPIENTRY
274af69d88dSmrg_mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize,
275af69d88dSmrg                          GLsizei *length, GLint *values)
276af69d88dSmrg{
277af69d88dSmrg   struct vdp_surface *surf = (struct vdp_surface *)surface;
278af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
279af69d88dSmrg
280af69d88dSmrg   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
281af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUGetSurfaceivNV");
282af69d88dSmrg      return;
283af69d88dSmrg   }
284af69d88dSmrg
28501e04c3fSmrg   if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
286af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV");
287af69d88dSmrg      return;
288af69d88dSmrg   }
289af69d88dSmrg
290af69d88dSmrg   if (pname != GL_SURFACE_STATE_NV) {
291af69d88dSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "VDPAUGetSurfaceivNV");
292af69d88dSmrg      return;
293af69d88dSmrg   }
294af69d88dSmrg
295af69d88dSmrg   if (bufSize < 1) {
296af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV");
297af69d88dSmrg      return;
298af69d88dSmrg   }
299af69d88dSmrg
300af69d88dSmrg   values[0] = surf->state;
301af69d88dSmrg
302af69d88dSmrg   if (length != NULL)
303af69d88dSmrg      *length = 1;
304af69d88dSmrg}
305af69d88dSmrg
306af69d88dSmrgvoid GLAPIENTRY
307af69d88dSmrg_mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access)
308af69d88dSmrg{
309af69d88dSmrg   struct vdp_surface *surf = (struct vdp_surface *)surface;
310af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
311af69d88dSmrg
312af69d88dSmrg   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
313af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
314af69d88dSmrg      return;
315af69d88dSmrg   }
316af69d88dSmrg
31701e04c3fSmrg   if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
318af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
319af69d88dSmrg      return;
320af69d88dSmrg   }
321af69d88dSmrg
322af69d88dSmrg   if (access != GL_READ_ONLY && access != GL_WRITE_ONLY &&
323af69d88dSmrg       access != GL_READ_WRITE) {
324af69d88dSmrg
325af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
326af69d88dSmrg      return;
327af69d88dSmrg   }
328af69d88dSmrg
329af69d88dSmrg   if (surf->state == GL_SURFACE_MAPPED_NV) {
330af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
331af69d88dSmrg      return;
332af69d88dSmrg   }
333af69d88dSmrg
334af69d88dSmrg   surf->access = access;
335af69d88dSmrg}
336af69d88dSmrg
337af69d88dSmrgvoid GLAPIENTRY
338af69d88dSmrg_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
339af69d88dSmrg{
340af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
341af69d88dSmrg   int i;
342af69d88dSmrg
343af69d88dSmrg   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
344af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
345af69d88dSmrg      return;
346af69d88dSmrg   }
347af69d88dSmrg
348af69d88dSmrg   for (i = 0; i < numSurfaces; ++i) {
349af69d88dSmrg      struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
350af69d88dSmrg
35101e04c3fSmrg      if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
352af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
353af69d88dSmrg         return;
354af69d88dSmrg      }
355af69d88dSmrg
356af69d88dSmrg      if (surf->state == GL_SURFACE_MAPPED_NV) {
357af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
358af69d88dSmrg         return;
359af69d88dSmrg      }
360af69d88dSmrg   }
361af69d88dSmrg
362af69d88dSmrg   for (i = 0; i < numSurfaces; ++i) {
363af69d88dSmrg      struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
364af69d88dSmrg      unsigned numTextureNames = surf->output ? 1 : 4;
365af69d88dSmrg      unsigned j;
366af69d88dSmrg
367af69d88dSmrg      for (j = 0; j < numTextureNames; ++j) {
368af69d88dSmrg         struct gl_texture_object *tex = surf->textures[j];
369af69d88dSmrg         struct gl_texture_image *image;
370af69d88dSmrg
371af69d88dSmrg         _mesa_lock_texture(ctx, tex);
372af69d88dSmrg         image = _mesa_get_tex_image(ctx, tex, surf->target, 0);
373af69d88dSmrg         if (!image) {
374af69d88dSmrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "VDPAUMapSurfacesNV");
375af69d88dSmrg            _mesa_unlock_texture(ctx, tex);
376af69d88dSmrg            return;
377af69d88dSmrg         }
378af69d88dSmrg
379af69d88dSmrg         ctx->Driver.FreeTextureImageBuffer(ctx, image);
380af69d88dSmrg
381af69d88dSmrg         ctx->Driver.VDPAUMapSurface(ctx, surf->target, surf->access,
382af69d88dSmrg                                     surf->output, tex, image,
383af69d88dSmrg                                     surf->vdpSurface, j);
384af69d88dSmrg
385af69d88dSmrg         _mesa_unlock_texture(ctx, tex);
386af69d88dSmrg      }
387af69d88dSmrg      surf->state = GL_SURFACE_MAPPED_NV;
388af69d88dSmrg   }
389af69d88dSmrg}
390af69d88dSmrg
391af69d88dSmrgvoid GLAPIENTRY
392af69d88dSmrg_mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
393af69d88dSmrg{
394af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
395af69d88dSmrg   int i;
396af69d88dSmrg
397af69d88dSmrg   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
398af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
399af69d88dSmrg      return;
400af69d88dSmrg   }
401af69d88dSmrg
402af69d88dSmrg   for (i = 0; i < numSurfaces; ++i) {
403af69d88dSmrg      struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
404af69d88dSmrg
40501e04c3fSmrg      if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
406af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
407af69d88dSmrg         return;
408af69d88dSmrg      }
409af69d88dSmrg
410af69d88dSmrg      if (surf->state != GL_SURFACE_MAPPED_NV) {
411af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
412af69d88dSmrg         return;
413af69d88dSmrg      }
414af69d88dSmrg   }
415af69d88dSmrg
416af69d88dSmrg   for (i = 0; i < numSurfaces; ++i) {
417af69d88dSmrg      struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
418af69d88dSmrg      unsigned numTextureNames = surf->output ? 1 : 4;
419af69d88dSmrg      unsigned j;
420af69d88dSmrg
421af69d88dSmrg      for (j = 0; j < numTextureNames; ++j) {
422af69d88dSmrg         struct gl_texture_object *tex = surf->textures[j];
423af69d88dSmrg         struct gl_texture_image *image;
424af69d88dSmrg
425af69d88dSmrg         _mesa_lock_texture(ctx, tex);
426af69d88dSmrg
42701e04c3fSmrg         image = _mesa_select_tex_image(tex, surf->target, 0);
428af69d88dSmrg
429af69d88dSmrg         ctx->Driver.VDPAUUnmapSurface(ctx, surf->target, surf->access,
430af69d88dSmrg                                       surf->output, tex, image,
431af69d88dSmrg                                       surf->vdpSurface, j);
432af69d88dSmrg
433af69d88dSmrg         if (image)
434af69d88dSmrg            ctx->Driver.FreeTextureImageBuffer(ctx, image);
435af69d88dSmrg
436af69d88dSmrg         _mesa_unlock_texture(ctx, tex);
437af69d88dSmrg      }
438af69d88dSmrg      surf->state = GL_SURFACE_REGISTERED_NV;
439af69d88dSmrg   }
440af69d88dSmrg}
441