Path: blob/21.2-virgl/src/gallium/frontends/vdpau/presentation.c
4565 views
/**************************************************************************1*2* Copyright 2010 Thomas Balling Sørensen.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include <stdio.h>28#include <vdpau/vdpau.h>2930#include "util/u_debug.h"31#include "util/u_memory.h"3233#include "vdpau_private.h"3435/**36* Create a VdpPresentationQueue.37*/38VdpStatus39vlVdpPresentationQueueCreate(VdpDevice device,40VdpPresentationQueueTarget presentation_queue_target,41VdpPresentationQueue *presentation_queue)42{43vlVdpPresentationQueue *pq = NULL;44VdpStatus ret;4546if (!presentation_queue)47return VDP_STATUS_INVALID_POINTER;4849vlVdpDevice *dev = vlGetDataHTAB(device);50if (!dev)51return VDP_STATUS_INVALID_HANDLE;5253vlVdpPresentationQueueTarget *pqt = vlGetDataHTAB(presentation_queue_target);54if (!pqt)55return VDP_STATUS_INVALID_HANDLE;5657if (dev != pqt->device)58return VDP_STATUS_HANDLE_DEVICE_MISMATCH;5960pq = CALLOC(1, sizeof(vlVdpPresentationQueue));61if (!pq)62return VDP_STATUS_RESOURCES;6364DeviceReference(&pq->device, dev);65pq->drawable = pqt->drawable;6667mtx_lock(&dev->mutex);68if (!vl_compositor_init_state(&pq->cstate, dev->context)) {69mtx_unlock(&dev->mutex);70ret = VDP_STATUS_ERROR;71goto no_compositor;72}73mtx_unlock(&dev->mutex);7475*presentation_queue = vlAddDataHTAB(pq);76if (*presentation_queue == 0) {77ret = VDP_STATUS_ERROR;78goto no_handle;79}8081return VDP_STATUS_OK;8283no_handle:84no_compositor:85DeviceReference(&pq->device, NULL);86FREE(pq);87return ret;88}8990/**91* Destroy a VdpPresentationQueue.92*/93VdpStatus94vlVdpPresentationQueueDestroy(VdpPresentationQueue presentation_queue)95{96vlVdpPresentationQueue *pq;9798pq = vlGetDataHTAB(presentation_queue);99if (!pq)100return VDP_STATUS_INVALID_HANDLE;101102mtx_lock(&pq->device->mutex);103vl_compositor_cleanup_state(&pq->cstate);104mtx_unlock(&pq->device->mutex);105106vlRemoveDataHTAB(presentation_queue);107DeviceReference(&pq->device, NULL);108FREE(pq);109110return VDP_STATUS_OK;111}112113/**114* Configure the background color setting.115*/116VdpStatus117vlVdpPresentationQueueSetBackgroundColor(VdpPresentationQueue presentation_queue,118VdpColor *const background_color)119{120vlVdpPresentationQueue *pq;121union pipe_color_union color;122123if (!background_color)124return VDP_STATUS_INVALID_POINTER;125126pq = vlGetDataHTAB(presentation_queue);127if (!pq)128return VDP_STATUS_INVALID_HANDLE;129130color.f[0] = background_color->red;131color.f[1] = background_color->green;132color.f[2] = background_color->blue;133color.f[3] = background_color->alpha;134135mtx_lock(&pq->device->mutex);136vl_compositor_set_clear_color(&pq->cstate, &color);137mtx_unlock(&pq->device->mutex);138139return VDP_STATUS_OK;140}141142/**143* Retrieve the current background color setting.144*/145VdpStatus146vlVdpPresentationQueueGetBackgroundColor(VdpPresentationQueue presentation_queue,147VdpColor *const background_color)148{149vlVdpPresentationQueue *pq;150union pipe_color_union color;151152if (!background_color)153return VDP_STATUS_INVALID_POINTER;154155pq = vlGetDataHTAB(presentation_queue);156if (!pq)157return VDP_STATUS_INVALID_HANDLE;158159mtx_lock(&pq->device->mutex);160vl_compositor_get_clear_color(&pq->cstate, &color);161mtx_unlock(&pq->device->mutex);162163background_color->red = color.f[0];164background_color->green = color.f[1];165background_color->blue = color.f[2];166background_color->alpha = color.f[3];167168return VDP_STATUS_OK;169}170171/**172* Retrieve the presentation queue's "current" time.173*/174VdpStatus175vlVdpPresentationQueueGetTime(VdpPresentationQueue presentation_queue,176VdpTime *current_time)177{178vlVdpPresentationQueue *pq;179180if (!current_time)181return VDP_STATUS_INVALID_POINTER;182183pq = vlGetDataHTAB(presentation_queue);184if (!pq)185return VDP_STATUS_INVALID_HANDLE;186187mtx_lock(&pq->device->mutex);188*current_time = pq->device->vscreen->get_timestamp(pq->device->vscreen,189(void *)pq->drawable);190mtx_unlock(&pq->device->mutex);191192return VDP_STATUS_OK;193}194195/**196* Enter a surface into the presentation queue.197*/198VdpStatus199vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue,200VdpOutputSurface surface,201uint32_t clip_width,202uint32_t clip_height,203VdpTime earliest_presentation_time)204{205static int dump_window = -1;206207vlVdpPresentationQueue *pq;208vlVdpOutputSurface *surf;209210struct pipe_context *pipe;211struct pipe_resource *tex;212struct pipe_surface surf_templ, *surf_draw = NULL;213struct u_rect src_rect, dst_clip, *dirty_area;214215struct vl_compositor *compositor;216struct vl_compositor_state *cstate;217struct vl_screen *vscreen;218219pq = vlGetDataHTAB(presentation_queue);220if (!pq)221return VDP_STATUS_INVALID_HANDLE;222223surf = vlGetDataHTAB(surface);224if (!surf)225return VDP_STATUS_INVALID_HANDLE;226227pipe = pq->device->context;228compositor = &pq->device->compositor;229cstate = &pq->cstate;230vscreen = pq->device->vscreen;231232mtx_lock(&pq->device->mutex);233if (vscreen->set_back_texture_from_output && surf->send_to_X)234vscreen->set_back_texture_from_output(vscreen, surf->surface->texture, clip_width, clip_height);235tex = vscreen->texture_from_drawable(vscreen, (void *)pq->drawable);236if (!tex) {237mtx_unlock(&pq->device->mutex);238return VDP_STATUS_INVALID_HANDLE;239}240241if (!vscreen->set_back_texture_from_output || !surf->send_to_X) {242dirty_area = vscreen->get_dirty_area(vscreen);243244memset(&surf_templ, 0, sizeof(surf_templ));245surf_templ.format = tex->format;246surf_draw = pipe->create_surface(pipe, tex, &surf_templ);247248dst_clip.x0 = 0;249dst_clip.y0 = 0;250dst_clip.x1 = clip_width ? clip_width : surf_draw->width;251dst_clip.y1 = clip_height ? clip_height : surf_draw->height;252253src_rect.x0 = 0;254src_rect.y0 = 0;255src_rect.x1 = surf_draw->width;256src_rect.y1 = surf_draw->height;257258vl_compositor_clear_layers(cstate);259vl_compositor_set_rgba_layer(cstate, compositor, 0, surf->sampler_view, &src_rect, NULL, NULL);260vl_compositor_set_dst_clip(cstate, &dst_clip);261vl_compositor_render(cstate, compositor, surf_draw, dirty_area, true);262}263264vscreen->set_next_timestamp(vscreen, earliest_presentation_time);265266// flush before calling flush_frontbuffer so that rendering is flushed267// to back buffer so the texture can be copied in flush_frontbuffer268pipe->screen->fence_reference(pipe->screen, &surf->fence, NULL);269pipe->flush(pipe, &surf->fence, 0);270pipe->screen->flush_frontbuffer(pipe->screen, pipe, tex, 0, 0,271vscreen->get_private(vscreen), NULL);272273pq->last_surf = surf;274275if (dump_window == -1) {276dump_window = debug_get_num_option("VDPAU_DUMP", 0);277}278279if (dump_window) {280static unsigned int framenum = 0;281char cmd[256];282283if (framenum) {284sprintf(cmd, "xwd -id %d -silent -out vdpau_frame_%08d.xwd", (int)pq->drawable, framenum);285if (system(cmd) != 0)286VDPAU_MSG(VDPAU_ERR, "[VDPAU] Dumping surface %d failed.\n", surface);287}288framenum++;289}290291if (!vscreen->set_back_texture_from_output || !surf->send_to_X) {292pipe_resource_reference(&tex, NULL);293pipe_surface_reference(&surf_draw, NULL);294}295mtx_unlock(&pq->device->mutex);296297return VDP_STATUS_OK;298}299300/**301* Wait for a surface to finish being displayed.302*/303VdpStatus304vlVdpPresentationQueueBlockUntilSurfaceIdle(VdpPresentationQueue presentation_queue,305VdpOutputSurface surface,306VdpTime *first_presentation_time)307{308vlVdpPresentationQueue *pq;309vlVdpOutputSurface *surf;310struct pipe_screen *screen;311312if (!first_presentation_time)313return VDP_STATUS_INVALID_POINTER;314315pq = vlGetDataHTAB(presentation_queue);316if (!pq)317return VDP_STATUS_INVALID_HANDLE;318319surf = vlGetDataHTAB(surface);320if (!surf)321return VDP_STATUS_INVALID_HANDLE;322323mtx_lock(&pq->device->mutex);324if (surf->fence) {325screen = pq->device->vscreen->pscreen;326screen->fence_finish(screen, NULL, surf->fence, PIPE_TIMEOUT_INFINITE);327screen->fence_reference(screen, &surf->fence, NULL);328}329mtx_unlock(&pq->device->mutex);330331return vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time);332}333334/**335* Poll the current queue status of a surface.336*/337VdpStatus338vlVdpPresentationQueueQuerySurfaceStatus(VdpPresentationQueue presentation_queue,339VdpOutputSurface surface,340VdpPresentationQueueStatus *status,341VdpTime *first_presentation_time)342{343vlVdpPresentationQueue *pq;344vlVdpOutputSurface *surf;345struct pipe_screen *screen;346347if (!(status && first_presentation_time))348return VDP_STATUS_INVALID_POINTER;349350pq = vlGetDataHTAB(presentation_queue);351if (!pq)352return VDP_STATUS_INVALID_HANDLE;353354surf = vlGetDataHTAB(surface);355if (!surf)356return VDP_STATUS_INVALID_HANDLE;357358*first_presentation_time = 0;359360if (!surf->fence) {361if (pq->last_surf == surf)362*status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE;363else364*status = VDP_PRESENTATION_QUEUE_STATUS_IDLE;365} else {366mtx_lock(&pq->device->mutex);367screen = pq->device->vscreen->pscreen;368if (screen->fence_finish(screen, NULL, surf->fence, 0)) {369screen->fence_reference(screen, &surf->fence, NULL);370*status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE;371mtx_unlock(&pq->device->mutex);372373// We actually need to query the timestamp of the last VSYNC event from the hardware374vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time);375*first_presentation_time += 1;376} else {377*status = VDP_PRESENTATION_QUEUE_STATUS_QUEUED;378mtx_unlock(&pq->device->mutex);379}380}381382return VDP_STATUS_OK;383}384385386