Path: blob/21.2-virgl/src/gallium/frontends/xa/xa_tracker.c
4561 views
/**********************************************************1* Copyright 2009-2011 VMware, Inc. All rights reserved.2*3* Permission is hereby granted, free of charge, to any person4* obtaining a copy of this software and associated documentation5* files (the "Software"), to deal in the Software without6* restriction, including without limitation the rights to use, copy,7* modify, merge, publish, distribute, sublicense, and/or sell copies8* of the Software, and to permit persons to whom the Software is9* furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23*********************************************************24* Authors:25* Thomas Hellstrom <thellstrom-at-vmware-dot-com>26*/2728#include <unistd.h>29#include "xa_tracker.h"30#include "xa_priv.h"31#include "pipe/p_state.h"32#include "pipe/p_format.h"33#include "pipe-loader/pipe_loader.h"34#include "frontend/drm_driver.h"35#include "util/u_inlines.h"3637/*38* format_map [xa_surface_type][first..last in list].39* Needs to be updated when enum xa_formats is updated.40*/4142static const enum xa_formats preferred_a[] = { xa_format_a8 };4344static const enum xa_formats preferred_argb[] =45{ xa_format_a8r8g8b8, xa_format_x8r8g8b8, xa_format_r5g6b5,46xa_format_x1r5g5b547};48static const enum xa_formats preferred_z[] =49{ xa_format_z32, xa_format_z24, xa_format_z16 };50static const enum xa_formats preferred_sz[] =51{ xa_format_x8z24, xa_format_s8z24 };52static const enum xa_formats preferred_zs[] =53{ xa_format_z24x8, xa_format_z24s8 };54static const enum xa_formats preferred_yuv[] = { xa_format_yuv8 };5556static const enum xa_formats *preferred[] =57{ NULL, preferred_a, preferred_argb, NULL, NULL,58preferred_z, preferred_zs, preferred_sz, preferred_yuv59};6061static const unsigned int num_preferred[] = { 0,62sizeof(preferred_a) / sizeof(enum xa_formats),63sizeof(preferred_argb) / sizeof(enum xa_formats),640,650,66sizeof(preferred_z) / sizeof(enum xa_formats),67sizeof(preferred_zs) / sizeof(enum xa_formats),68sizeof(preferred_sz) / sizeof(enum xa_formats),69sizeof(preferred_yuv) / sizeof(enum xa_formats)70};7172static const unsigned int stype_bind[XA_LAST_SURFACE_TYPE] = { 0,73PIPE_BIND_SAMPLER_VIEW,74PIPE_BIND_SAMPLER_VIEW,75PIPE_BIND_SAMPLER_VIEW,76PIPE_BIND_SAMPLER_VIEW,77PIPE_BIND_DEPTH_STENCIL,78PIPE_BIND_DEPTH_STENCIL,79PIPE_BIND_DEPTH_STENCIL,80PIPE_BIND_SAMPLER_VIEW81};8283static struct xa_format_descriptor84xa_get_pipe_format(struct xa_tracker *xa, enum xa_formats xa_format)85{86struct xa_format_descriptor fdesc;8788fdesc.xa_format = xa_format;8990switch (xa_format) {91case xa_format_a8:92if (xa->screen->is_format_supported(xa->screen, PIPE_FORMAT_R8_UNORM,93PIPE_TEXTURE_2D, 0, 0,94stype_bind[xa_type_a] |95PIPE_BIND_RENDER_TARGET))96fdesc.format = PIPE_FORMAT_R8_UNORM;97else98fdesc.format = PIPE_FORMAT_L8_UNORM;99break;100case xa_format_a8r8g8b8:101fdesc.format = PIPE_FORMAT_B8G8R8A8_UNORM;102break;103case xa_format_x8r8g8b8:104fdesc.format = PIPE_FORMAT_B8G8R8X8_UNORM;105break;106case xa_format_r5g6b5:107fdesc.format = PIPE_FORMAT_B5G6R5_UNORM;108break;109case xa_format_x1r5g5b5:110fdesc.format = PIPE_FORMAT_B5G5R5A1_UNORM;111break;112case xa_format_a4r4g4b4:113fdesc.format = PIPE_FORMAT_B4G4R4A4_UNORM;114break;115case xa_format_a2b10g10r10:116fdesc.format = PIPE_FORMAT_R10G10B10A2_UNORM;117break;118case xa_format_x2b10g10r10:119fdesc.format = PIPE_FORMAT_R10G10B10X2_UNORM;120break;121case xa_format_b8g8r8a8:122fdesc.format = PIPE_FORMAT_A8R8G8B8_UNORM;123break;124case xa_format_b8g8r8x8:125fdesc.format = PIPE_FORMAT_X8R8G8B8_UNORM;126break;127case xa_format_z24:128fdesc.format = PIPE_FORMAT_Z24X8_UNORM;129break;130case xa_format_z16:131fdesc.format = PIPE_FORMAT_Z16_UNORM;132break;133case xa_format_z32:134fdesc.format = PIPE_FORMAT_Z32_UNORM;135break;136case xa_format_x8z24:137fdesc.format = PIPE_FORMAT_Z24X8_UNORM;138break;139case xa_format_z24x8:140fdesc.format = PIPE_FORMAT_X8Z24_UNORM;141break;142case xa_format_s8z24:143fdesc.format = PIPE_FORMAT_Z24_UNORM_S8_UINT;144break;145case xa_format_z24s8:146fdesc.format = PIPE_FORMAT_S8_UINT_Z24_UNORM;147break;148case xa_format_yuv8:149if (xa->screen->is_format_supported(xa->screen, PIPE_FORMAT_R8_UNORM,150PIPE_TEXTURE_2D, 0, 0,151stype_bind[xa_type_yuv_component]))152fdesc.format = PIPE_FORMAT_R8_UNORM;153else154fdesc.format = PIPE_FORMAT_L8_UNORM;155break;156default:157unreachable("Unexpected format");158break;159}160return fdesc;161}162163XA_EXPORT struct xa_tracker *164xa_tracker_create(int drm_fd)165{166struct xa_tracker *xa = calloc(1, sizeof(struct xa_tracker));167enum xa_surface_type stype;168unsigned int num_formats;169170if (!xa)171return NULL;172173if (pipe_loader_drm_probe_fd(&xa->dev, drm_fd))174xa->screen = pipe_loader_create_screen(xa->dev);175176if (!xa->screen)177goto out_no_screen;178179xa->default_ctx = xa_context_create(xa);180if (!xa->default_ctx)181goto out_no_pipe;182183num_formats = 0;184for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype)185num_formats += num_preferred[stype];186187num_formats += 1;188xa->supported_formats = calloc(num_formats, sizeof(*xa->supported_formats));189if (!xa->supported_formats)190goto out_sf_alloc_fail;191192xa->supported_formats[0] = xa_format_unknown;193num_formats = 1;194memset(xa->format_map, 0, sizeof(xa->format_map));195196for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) {197unsigned int bind = stype_bind[stype];198enum xa_formats xa_format;199int i;200201for (i = 0; i < num_preferred[stype]; ++i) {202xa_format = preferred[stype][i];203204struct xa_format_descriptor fdesc =205xa_get_pipe_format(xa, xa_format);206207if (xa->screen->is_format_supported(xa->screen, fdesc.format,208PIPE_TEXTURE_2D, 0, 0, bind)) {209if (xa->format_map[stype][0] == 0)210xa->format_map[stype][0] = num_formats;211xa->format_map[stype][1] = num_formats;212xa->supported_formats[num_formats++] = xa_format;213}214}215}216return xa;217218out_sf_alloc_fail:219xa_context_destroy(xa->default_ctx);220out_no_pipe:221xa->screen->destroy(xa->screen);222out_no_screen:223if (xa->dev)224pipe_loader_release(&xa->dev, 1);225226free(xa);227return NULL;228}229230XA_EXPORT void231xa_tracker_destroy(struct xa_tracker *xa)232{233free(xa->supported_formats);234xa_context_destroy(xa->default_ctx);235xa->screen->destroy(xa->screen);236pipe_loader_release(&xa->dev, 1);237/* CHECK: The XA API user preserves ownership of the original fd */238free(xa);239}240241static int242xa_flags_compat(unsigned int old_flags, unsigned int new_flags)243{244unsigned int flag_diff = (old_flags ^ new_flags);245246if (flag_diff == 0)247return 1;248249if (flag_diff & XA_FLAG_SHARED)250return 0;251/*252* Don't recreate if we're dropping the render target flag.253*/254if (flag_diff & XA_FLAG_RENDER_TARGET)255return ((new_flags & XA_FLAG_RENDER_TARGET) == 0);256257/*258* Don't recreate if we're dropping the scanout flag.259*/260if (flag_diff & XA_FLAG_SCANOUT)261return ((new_flags & XA_FLAG_SCANOUT) == 0);262263/*264* Always recreate for unknown / unimplemented flags.265*/266return 0;267}268269static struct xa_format_descriptor270xa_get_format_stype_depth(struct xa_tracker *xa,271enum xa_surface_type stype, unsigned int depth)272{273unsigned int i;274struct xa_format_descriptor fdesc;275int found = 0;276277for (i = xa->format_map[stype][0]; i <= xa->format_map[stype][1]; ++i) {278fdesc = xa_get_pipe_format(xa, xa->supported_formats[i]);279if (fdesc.xa_format != xa_format_unknown &&280xa_format_depth(fdesc.xa_format) == depth) {281found = 1;282break;283}284}285286if (!found)287fdesc.xa_format = xa_format_unknown;288289return fdesc;290}291292XA_EXPORT int293xa_format_check_supported(struct xa_tracker *xa,294enum xa_formats xa_format, unsigned int flags)295{296struct xa_format_descriptor fdesc = xa_get_pipe_format(xa, xa_format);297unsigned int bind;298299if (fdesc.xa_format == xa_format_unknown)300return -XA_ERR_INVAL;301302bind = stype_bind[xa_format_type(fdesc.xa_format)];303if (flags & XA_FLAG_SHARED)304bind |= PIPE_BIND_SHARED;305if (flags & XA_FLAG_RENDER_TARGET)306bind |= PIPE_BIND_RENDER_TARGET;307if (flags & XA_FLAG_SCANOUT)308bind |= PIPE_BIND_SCANOUT;309310if (!xa->screen->is_format_supported(xa->screen, fdesc.format,311PIPE_TEXTURE_2D, 0, 0, bind))312return -XA_ERR_INVAL;313314return XA_ERR_NONE;315}316317static unsigned318handle_type(enum xa_handle_type type)319{320switch (type) {321case xa_handle_type_kms:322return WINSYS_HANDLE_TYPE_KMS;323case xa_handle_type_fd:324return WINSYS_HANDLE_TYPE_FD;325case xa_handle_type_shared:326default:327return WINSYS_HANDLE_TYPE_SHARED;328}329}330331static struct xa_surface *332surface_create(struct xa_tracker *xa,333int width,334int height,335int depth,336enum xa_surface_type stype,337enum xa_formats xa_format, unsigned int flags,338struct winsys_handle *whandle)339{340struct pipe_resource *template;341struct xa_surface *srf;342struct xa_format_descriptor fdesc;343344if (xa_format == xa_format_unknown)345fdesc = xa_get_format_stype_depth(xa, stype, depth);346else347fdesc = xa_get_pipe_format(xa, xa_format);348349if (fdesc.xa_format == xa_format_unknown)350return NULL;351352srf = calloc(1, sizeof(*srf));353if (!srf)354return NULL;355356template = &srf->template;357template->format = fdesc.format;358template->target = PIPE_TEXTURE_2D;359template->width0 = width;360template->height0 = height;361template->depth0 = 1;362template->array_size = 1;363template->last_level = 0;364template->bind = stype_bind[xa_format_type(fdesc.xa_format)];365366if (flags & XA_FLAG_SHARED)367template->bind |= PIPE_BIND_SHARED;368if (flags & XA_FLAG_RENDER_TARGET)369template->bind |= PIPE_BIND_RENDER_TARGET;370if (flags & XA_FLAG_SCANOUT)371template->bind |= PIPE_BIND_SCANOUT;372373if (whandle)374srf->tex = xa->screen->resource_from_handle(xa->screen, template, whandle,375PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);376else377srf->tex = xa->screen->resource_create(xa->screen, template);378if (!srf->tex)379goto out_no_tex;380381srf->refcount = 1;382srf->xa = xa;383srf->flags = flags;384srf->fdesc = fdesc;385386return srf;387out_no_tex:388free(srf);389return NULL;390}391392393XA_EXPORT struct xa_surface *394xa_surface_create(struct xa_tracker *xa,395int width,396int height,397int depth,398enum xa_surface_type stype,399enum xa_formats xa_format, unsigned int flags)400{401return surface_create(xa, width, height, depth, stype, xa_format, flags, NULL);402}403404405XA_EXPORT struct xa_surface *406xa_surface_from_handle(struct xa_tracker *xa,407int width,408int height,409int depth,410enum xa_surface_type stype,411enum xa_formats xa_format, unsigned int flags,412uint32_t handle, uint32_t stride)413{414return xa_surface_from_handle2(xa, width, height, depth, stype, xa_format,415WINSYS_HANDLE_TYPE_SHARED, flags, handle,416stride);417}418419XA_EXPORT struct xa_surface *420xa_surface_from_handle2(struct xa_tracker *xa,421int width,422int height,423int depth,424enum xa_surface_type stype,425enum xa_formats xa_format, unsigned int flags,426enum xa_handle_type type,427uint32_t handle, uint32_t stride)428{429struct winsys_handle whandle;430memset(&whandle, 0, sizeof(whandle));431whandle.type = handle_type(type);432whandle.handle = handle;433whandle.stride = stride;434return surface_create(xa, width, height, depth, stype, xa_format, flags, &whandle);435}436437XA_EXPORT int438xa_surface_redefine(struct xa_surface *srf,439int width,440int height,441int depth,442enum xa_surface_type stype,443enum xa_formats xa_format,444unsigned int new_flags,445int copy_contents)446{447struct pipe_resource *template = &srf->template;448struct pipe_resource *texture;449struct pipe_box src_box;450struct xa_tracker *xa = srf->xa;451int save_width;452int save_height;453unsigned int save_format;454struct xa_format_descriptor fdesc;455456457if (xa_format == xa_format_unknown)458fdesc = xa_get_format_stype_depth(xa, stype, depth);459else460fdesc = xa_get_pipe_format(xa, xa_format);461462if (width == template->width0 && height == template->height0 &&463template->format == fdesc.format &&464xa_flags_compat(srf->flags, new_flags))465return XA_ERR_NONE;466467template->bind = stype_bind[xa_format_type(fdesc.xa_format)];468if (new_flags & XA_FLAG_SHARED)469template->bind |= PIPE_BIND_SHARED;470if (new_flags & XA_FLAG_RENDER_TARGET)471template->bind |= PIPE_BIND_RENDER_TARGET;472if (new_flags & XA_FLAG_SCANOUT)473template->bind |= PIPE_BIND_SCANOUT;474475if (copy_contents) {476if (!xa_format_type_is_color(fdesc.xa_format) ||477xa_format_type(fdesc.xa_format) == xa_type_a)478return -XA_ERR_INVAL;479480if (!xa->screen->is_format_supported(xa->screen, fdesc.format,481PIPE_TEXTURE_2D, 0, 0,482template->bind |483PIPE_BIND_RENDER_TARGET))484return -XA_ERR_INVAL;485}486487save_width = template->width0;488save_height = template->height0;489save_format = template->format;490491template->width0 = width;492template->height0 = height;493template->format = fdesc.format;494495texture = xa->screen->resource_create(xa->screen, template);496if (!texture) {497template->width0 = save_width;498template->height0 = save_height;499template->format = save_format;500return -XA_ERR_NORES;501}502503if (copy_contents) {504struct pipe_context *pipe = xa->default_ctx->pipe;505506u_box_origin_2d(xa_min(save_width, template->width0),507xa_min(save_height, template->height0), &src_box);508pipe->resource_copy_region(pipe, texture,5090, 0, 0, 0, srf->tex, 0, &src_box);510xa_context_flush(xa->default_ctx);511}512513pipe_resource_reference(&srf->tex, texture);514pipe_resource_reference(&texture, NULL);515srf->fdesc = fdesc;516srf->flags = new_flags;517518return XA_ERR_NONE;519}520521XA_EXPORT struct xa_surface*522xa_surface_ref(struct xa_surface *srf)523{524if (srf == NULL) {525return NULL;526}527srf->refcount++;528return srf;529}530531XA_EXPORT void532xa_surface_unref(struct xa_surface *srf)533{534if (srf == NULL || --srf->refcount) {535return;536}537pipe_resource_reference(&srf->tex, NULL);538free(srf);539}540541XA_EXPORT void542xa_tracker_version(int *major, int *minor, int *patch)543{544*major = XA_TRACKER_VERSION_MAJOR;545*minor = XA_TRACKER_VERSION_MINOR;546*patch = XA_TRACKER_VERSION_PATCH;547}548549XA_EXPORT int550xa_surface_handle(struct xa_surface *srf,551enum xa_handle_type type,552uint32_t * handle, unsigned int *stride)553{554struct winsys_handle whandle;555556struct pipe_screen *screen = srf->xa->screen;557boolean res;558559memset(&whandle, 0, sizeof(whandle));560whandle.type = handle_type(type);561res = screen->resource_get_handle(screen, srf->xa->default_ctx->pipe,562srf->tex, &whandle,563PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);564if (!res)565return -XA_ERR_INVAL;566567*handle = whandle.handle;568*stride = whandle.stride;569570return XA_ERR_NONE;571}572573XA_EXPORT enum xa_formats574xa_surface_format(const struct xa_surface *srf)575{576return srf->fdesc.xa_format;577}578579580