Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/**************************************************************************
2
 *
3
 * Copyright 2010 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 
29
#include 
30
 
31
#include "util/u_debug.h"
32
#include "util/u_memory.h"
33
 
34
#include "vdpau_private.h"
35
 
36
/**
37
 * Create a VdpPresentationQueue.
38
 */
39
VdpStatus
40
vlVdpPresentationQueueCreate(VdpDevice device,
41
                             VdpPresentationQueueTarget presentation_queue_target,
42
                             VdpPresentationQueue *presentation_queue)
43
{
44
   vlVdpPresentationQueue *pq = NULL;
45
   VdpStatus ret;
46
 
47
   if (!presentation_queue)
48
      return VDP_STATUS_INVALID_POINTER;
49
 
50
   vlVdpDevice *dev = vlGetDataHTAB(device);
51
   if (!dev)
52
      return VDP_STATUS_INVALID_HANDLE;
53
 
54
   vlVdpPresentationQueueTarget *pqt = vlGetDataHTAB(presentation_queue_target);
55
   if (!pqt)
56
      return VDP_STATUS_INVALID_HANDLE;
57
 
58
   if (dev != pqt->device)
59
      return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
60
 
61
   pq = CALLOC(1, sizeof(vlVdpPresentationQueue));
62
   if (!pq)
63
      return VDP_STATUS_RESOURCES;
64
 
65
   DeviceReference(&pq->device, dev);
66
   pq->drawable = pqt->drawable;
67
 
68
   pipe_mutex_lock(dev->mutex);
69
   if (!vl_compositor_init_state(&pq->cstate, dev->context)) {
70
      pipe_mutex_unlock(dev->mutex);
71
      ret = VDP_STATUS_ERROR;
72
      goto no_compositor;
73
   }
74
   pipe_mutex_unlock(dev->mutex);
75
 
76
   *presentation_queue = vlAddDataHTAB(pq);
77
   if (*presentation_queue == 0) {
78
      ret = VDP_STATUS_ERROR;
79
      goto no_handle;
80
   }
81
 
82
   return VDP_STATUS_OK;
83
 
84
no_handle:
85
no_compositor:
86
   DeviceReference(&pq->device, NULL);
87
   FREE(pq);
88
   return ret;
89
}
90
 
91
/**
92
 * Destroy a VdpPresentationQueue.
93
 */
94
VdpStatus
95
vlVdpPresentationQueueDestroy(VdpPresentationQueue presentation_queue)
96
{
97
   vlVdpPresentationQueue *pq;
98
 
99
   pq = vlGetDataHTAB(presentation_queue);
100
   if (!pq)
101
      return VDP_STATUS_INVALID_HANDLE;
102
 
103
   pipe_mutex_lock(pq->device->mutex);
104
   vl_compositor_cleanup_state(&pq->cstate);
105
   pipe_mutex_unlock(pq->device->mutex);
106
 
107
   vlRemoveDataHTAB(presentation_queue);
108
   DeviceReference(&pq->device, NULL);
109
   FREE(pq);
110
 
111
   return VDP_STATUS_OK;
112
}
113
 
114
/**
115
 * Configure the background color setting.
116
 */
117
VdpStatus
118
vlVdpPresentationQueueSetBackgroundColor(VdpPresentationQueue presentation_queue,
119
                                         VdpColor *const background_color)
120
{
121
   vlVdpPresentationQueue *pq;
122
   union pipe_color_union color;
123
 
124
   if (!background_color)
125
      return VDP_STATUS_INVALID_POINTER;
126
 
127
   pq = vlGetDataHTAB(presentation_queue);
128
   if (!pq)
129
      return VDP_STATUS_INVALID_HANDLE;
130
 
131
   color.f[0] = background_color->red;
132
   color.f[1] = background_color->green;
133
   color.f[2] = background_color->blue;
134
   color.f[3] = background_color->alpha;
135
 
136
   pipe_mutex_lock(pq->device->mutex);
137
   vl_compositor_set_clear_color(&pq->cstate, &color);
138
   pipe_mutex_unlock(pq->device->mutex);
139
 
140
   return VDP_STATUS_OK;
141
}
142
 
143
/**
144
 * Retrieve the current background color setting.
145
 */
146
VdpStatus
147
vlVdpPresentationQueueGetBackgroundColor(VdpPresentationQueue presentation_queue,
148
                                         VdpColor *const background_color)
149
{
150
   vlVdpPresentationQueue *pq;
151
   union pipe_color_union color;
152
 
153
   if (!background_color)
154
      return VDP_STATUS_INVALID_POINTER;
155
 
156
   pq = vlGetDataHTAB(presentation_queue);
157
   if (!pq)
158
      return VDP_STATUS_INVALID_HANDLE;
159
 
160
   pipe_mutex_lock(pq->device->mutex);
161
   vl_compositor_get_clear_color(&pq->cstate, &color);
162
   pipe_mutex_unlock(pq->device->mutex);
163
 
164
   background_color->red = color.f[0];
165
   background_color->green = color.f[1];
166
   background_color->blue = color.f[2];
167
   background_color->alpha = color.f[3];
168
 
169
   return VDP_STATUS_OK;
170
}
171
 
172
/**
173
 * Retrieve the presentation queue's "current" time.
174
 */
175
VdpStatus
176
vlVdpPresentationQueueGetTime(VdpPresentationQueue presentation_queue,
177
                              VdpTime *current_time)
178
{
179
   vlVdpPresentationQueue *pq;
180
 
181
   if (!current_time)
182
      return VDP_STATUS_INVALID_POINTER;
183
 
184
   pq = vlGetDataHTAB(presentation_queue);
185
   if (!pq)
186
      return VDP_STATUS_INVALID_HANDLE;
187
 
188
   pipe_mutex_lock(pq->device->mutex);
189
   *current_time = vl_screen_get_timestamp(pq->device->vscreen, pq->drawable);
190
   pipe_mutex_unlock(pq->device->mutex);
191
 
192
   return VDP_STATUS_OK;
193
}
194
 
195
/**
196
 * Enter a surface into the presentation queue.
197
 */
198
VdpStatus
199
vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue,
200
                              VdpOutputSurface surface,
201
                              uint32_t clip_width,
202
                              uint32_t clip_height,
203
                              VdpTime  earliest_presentation_time)
204
{
205
   static int dump_window = -1;
206
 
207
   vlVdpPresentationQueue *pq;
208
   vlVdpOutputSurface *surf;
209
 
210
   struct pipe_context *pipe;
211
   struct pipe_resource *tex;
212
   struct pipe_surface surf_templ, *surf_draw;
213
   struct u_rect src_rect, dst_clip, *dirty_area;
214
 
215
   struct vl_compositor *compositor;
216
   struct vl_compositor_state *cstate;
217
 
218
   pq = vlGetDataHTAB(presentation_queue);
219
   if (!pq)
220
      return VDP_STATUS_INVALID_HANDLE;
221
 
222
   surf = vlGetDataHTAB(surface);
223
   if (!surf)
224
      return VDP_STATUS_INVALID_HANDLE;
225
 
226
   pipe = pq->device->context;
227
   compositor = &pq->device->compositor;
228
   cstate = &pq->cstate;
229
 
230
   pipe_mutex_lock(pq->device->mutex);
231
   tex = vl_screen_texture_from_drawable(pq->device->vscreen, pq->drawable);
232
   if (!tex) {
233
      pipe_mutex_unlock(pq->device->mutex);
234
      return VDP_STATUS_INVALID_HANDLE;
235
   }
236
 
237
   dirty_area = vl_screen_get_dirty_area(pq->device->vscreen);
238
 
239
   memset(&surf_templ, 0, sizeof(surf_templ));
240
   surf_templ.format = tex->format;
241
   surf_draw = pipe->create_surface(pipe, tex, &surf_templ);
242
 
243
   dst_clip.x0 = 0;
244
   dst_clip.y0 = 0;
245
   dst_clip.x1 = clip_width ? clip_width : surf_draw->width;
246
   dst_clip.y1 = clip_height ? clip_height : surf_draw->height;
247
 
248
   if (pq->device->delayed_rendering.surface == surface &&
249
       dst_clip.x1 == surf_draw->width && dst_clip.y1 == surf_draw->height) {
250
 
251
      // TODO: we correctly support the clipping here, but not the pq background color in the clipped area....
252
      cstate = pq->device->delayed_rendering.cstate;
253
      vl_compositor_set_dst_clip(cstate, &dst_clip);
254
      vlVdpResolveDelayedRendering(pq->device, surf_draw, dirty_area);
255
 
256
   } else {
257
      vlVdpResolveDelayedRendering(pq->device, NULL, NULL);
258
 
259
      src_rect.x0 = 0;
260
      src_rect.y0 = 0;
261
      src_rect.x1 = surf_draw->width;
262
      src_rect.y1 = surf_draw->height;
263
 
264
      vl_compositor_clear_layers(cstate);
265
      vl_compositor_set_rgba_layer(cstate, compositor, 0, surf->sampler_view, &src_rect, NULL, NULL);
266
      vl_compositor_set_dst_clip(cstate, &dst_clip);
267
      vl_compositor_render(cstate, compositor, surf_draw, dirty_area, true);
268
   }
269
 
270
   vl_screen_set_next_timestamp(pq->device->vscreen, earliest_presentation_time);
271
   pipe->screen->flush_frontbuffer
272
   (
273
      pipe->screen, tex, 0, 0,
274
      vl_screen_get_private(pq->device->vscreen), NULL
275
   );
276
 
277
   pipe->screen->fence_reference(pipe->screen, &surf->fence, NULL);
278
   pipe->flush(pipe, &surf->fence, 0);
279
   pq->last_surf = surf;
280
 
281
   if (dump_window == -1) {
282
      dump_window = debug_get_num_option("VDPAU_DUMP", 0);
283
   }
284
 
285
   if (dump_window) {
286
      static unsigned int framenum = 0;
287
      char cmd[256];
288
 
289
      if (framenum) {
290
         sprintf(cmd, "xwd -id %d -silent -out vdpau_frame_%08d.xwd", (int)pq->drawable, framenum);
291
         if (system(cmd) != 0)
292
            VDPAU_MSG(VDPAU_ERR, "[VDPAU] Dumping surface %d failed.\n", surface);
293
      }
294
      framenum++;
295
   }
296
 
297
   pipe_resource_reference(&tex, NULL);
298
   pipe_surface_reference(&surf_draw, NULL);
299
   pipe_mutex_unlock(pq->device->mutex);
300
 
301
   return VDP_STATUS_OK;
302
}
303
 
304
/**
305
 * Wait for a surface to finish being displayed.
306
 */
307
VdpStatus
308
vlVdpPresentationQueueBlockUntilSurfaceIdle(VdpPresentationQueue presentation_queue,
309
                                            VdpOutputSurface surface,
310
                                            VdpTime *first_presentation_time)
311
{
312
   vlVdpPresentationQueue *pq;
313
   vlVdpOutputSurface *surf;
314
   struct pipe_screen *screen;
315
 
316
   if (!first_presentation_time)
317
      return VDP_STATUS_INVALID_POINTER;
318
 
319
   pq = vlGetDataHTAB(presentation_queue);
320
   if (!pq)
321
      return VDP_STATUS_INVALID_HANDLE;
322
 
323
   surf = vlGetDataHTAB(surface);
324
   if (!surf)
325
      return VDP_STATUS_INVALID_HANDLE;
326
 
327
   pipe_mutex_lock(pq->device->mutex);
328
   if (surf->fence) {
329
      screen = pq->device->vscreen->pscreen;
330
      screen->fence_finish(screen, surf->fence, PIPE_TIMEOUT_INFINITE);
331
      screen->fence_reference(screen, &surf->fence, NULL);
332
   }
333
   pipe_mutex_unlock(pq->device->mutex);
334
 
335
   return vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time);
336
}
337
 
338
/**
339
 * Poll the current queue status of a surface.
340
 */
341
VdpStatus
342
vlVdpPresentationQueueQuerySurfaceStatus(VdpPresentationQueue presentation_queue,
343
                                         VdpOutputSurface surface,
344
                                         VdpPresentationQueueStatus *status,
345
                                         VdpTime *first_presentation_time)
346
{
347
   vlVdpPresentationQueue *pq;
348
   vlVdpOutputSurface *surf;
349
   struct pipe_screen *screen;
350
 
351
   if (!(status && first_presentation_time))
352
      return VDP_STATUS_INVALID_POINTER;
353
 
354
   pq = vlGetDataHTAB(presentation_queue);
355
   if (!pq)
356
      return VDP_STATUS_INVALID_HANDLE;
357
 
358
   surf = vlGetDataHTAB(surface);
359
   if (!surf)
360
      return VDP_STATUS_INVALID_HANDLE;
361
 
362
   *first_presentation_time = 0;
363
 
364
   if (!surf->fence) {
365
      if (pq->last_surf == surf)
366
         *status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE;
367
      else
368
         *status = VDP_PRESENTATION_QUEUE_STATUS_IDLE;
369
   } else {
370
      pipe_mutex_lock(pq->device->mutex);
371
      screen = pq->device->vscreen->pscreen;
372
      if (screen->fence_signalled(screen, surf->fence)) {
373
         screen->fence_reference(screen, &surf->fence, NULL);
374
         *status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE;
375
         pipe_mutex_unlock(pq->device->mutex);
376
 
377
         // We actually need to query the timestamp of the last VSYNC event from the hardware
378
         vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time);
379
         *first_presentation_time += 1;
380
      } else {
381
         *status = VDP_PRESENTATION_QUEUE_STATUS_QUEUED;
382
         pipe_mutex_unlock(pq->device->mutex);
383
      }
384
   }
385
 
386
   return VDP_STATUS_OK;
387
}