Path: blob/21.2-virgl/src/gallium/winsys/sw/dri/dri_sw_winsys.c
4573 views
/**************************************************************************1*2* Copyright 2009, VMware, Inc.3* All Rights Reserved.4* Copyright 2010 George Sapountzis <[email protected]>5*6* Permission is hereby granted, free of charge, to any person obtaining a7* copy of this software and associated documentation files (the8* "Software"), to deal in the Software without restriction, including9* without limitation the rights to use, copy, modify, merge, publish,10* distribute, sub license, and/or sell copies of the Software, and to11* permit persons to whom the Software is furnished to do so, subject to12* the following conditions:13*14* The above copyright notice and this permission notice (including the15* next paragraph) shall be included in all copies or substantial portions16* of the Software.17*18* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS19* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF20* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.21* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR22* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,23* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE24* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.25*26**************************************************************************/2728#if ANDROID_API_LEVEL < 2629#undef HAVE_SYS_SHM_H30#endif3132#ifdef HAVE_SYS_SHM_H33#include <sys/ipc.h>34#include <sys/shm.h>35#ifdef __FreeBSD__36/* sys/ipc.h -> sys/_types.h -> machine/param.h37* - defines ALIGN which clashes with our ALIGN38*/39#undef ALIGN40#endif41#endif4243#include "pipe/p_compiler.h"44#include "pipe/p_format.h"45#include "pipe/p_state.h"46#include "util/u_inlines.h"47#include "util/format/u_format.h"48#include "util/u_math.h"49#include "util/u_memory.h"5051#include "frontend/sw_winsys.h"52#include "dri_sw_winsys.h"535455struct dri_sw_displaytarget56{57enum pipe_format format;58unsigned width;59unsigned height;60unsigned stride;6162unsigned map_flags;63int shmid;64void *data;65void *mapped;66const void *front_private;67};6869struct dri_sw_winsys70{71struct sw_winsys base;7273const struct drisw_loader_funcs *lf;74};7576static inline struct dri_sw_displaytarget *77dri_sw_displaytarget( struct sw_displaytarget *dt )78{79return (struct dri_sw_displaytarget *)dt;80}8182static inline struct dri_sw_winsys *83dri_sw_winsys( struct sw_winsys *ws )84{85return (struct dri_sw_winsys *)ws;86}878889static bool90dri_sw_is_displaytarget_format_supported( struct sw_winsys *ws,91unsigned tex_usage,92enum pipe_format format )93{94/* TODO: check visuals or other sensible thing here */95return true;96}9798#ifdef HAVE_SYS_SHM_H99static char *100alloc_shm(struct dri_sw_displaytarget *dri_sw_dt, unsigned size)101{102char *addr;103104/* 0600 = user read+write */105dri_sw_dt->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600);106if (dri_sw_dt->shmid < 0)107return NULL;108109addr = (char *) shmat(dri_sw_dt->shmid, 0, 0);110/* mark the segment immediately for deletion to avoid leaks */111shmctl(dri_sw_dt->shmid, IPC_RMID, 0);112113if (addr == (char *) -1)114return NULL;115116return addr;117}118#endif119120static struct sw_displaytarget *121dri_sw_displaytarget_create(struct sw_winsys *winsys,122unsigned tex_usage,123enum pipe_format format,124unsigned width, unsigned height,125unsigned alignment,126const void *front_private,127unsigned *stride)128{129UNUSED struct dri_sw_winsys *ws = dri_sw_winsys(winsys);130struct dri_sw_displaytarget *dri_sw_dt;131unsigned nblocksy, size, format_stride;132133dri_sw_dt = CALLOC_STRUCT(dri_sw_displaytarget);134if(!dri_sw_dt)135goto no_dt;136137dri_sw_dt->format = format;138dri_sw_dt->width = width;139dri_sw_dt->height = height;140dri_sw_dt->front_private = front_private;141142format_stride = util_format_get_stride(format, width);143dri_sw_dt->stride = align(format_stride, alignment);144145nblocksy = util_format_get_nblocksy(format, height);146size = dri_sw_dt->stride * nblocksy;147148dri_sw_dt->shmid = -1;149150#ifdef HAVE_SYS_SHM_H151if (ws->lf->put_image_shm)152dri_sw_dt->data = alloc_shm(dri_sw_dt, size);153#endif154155if(!dri_sw_dt->data)156dri_sw_dt->data = align_malloc(size, alignment);157158if(!dri_sw_dt->data)159goto no_data;160161*stride = dri_sw_dt->stride;162return (struct sw_displaytarget *)dri_sw_dt;163164no_data:165FREE(dri_sw_dt);166no_dt:167return NULL;168}169170static void171dri_sw_displaytarget_destroy(struct sw_winsys *ws,172struct sw_displaytarget *dt)173{174struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);175176if (dri_sw_dt->shmid >= 0) {177#ifdef HAVE_SYS_SHM_H178shmdt(dri_sw_dt->data);179shmctl(dri_sw_dt->shmid, IPC_RMID, 0);180#endif181} else {182align_free(dri_sw_dt->data);183}184185FREE(dri_sw_dt);186}187188static void *189dri_sw_displaytarget_map(struct sw_winsys *ws,190struct sw_displaytarget *dt,191unsigned flags)192{193struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);194dri_sw_dt->mapped = dri_sw_dt->data;195196if (dri_sw_dt->front_private && (flags & PIPE_MAP_READ)) {197struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);198dri_sw_ws->lf->get_image((void *)dri_sw_dt->front_private, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride, dri_sw_dt->data);199}200dri_sw_dt->map_flags = flags;201return dri_sw_dt->mapped;202}203204static void205dri_sw_displaytarget_unmap(struct sw_winsys *ws,206struct sw_displaytarget *dt)207{208struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);209if (dri_sw_dt->front_private && (dri_sw_dt->map_flags & PIPE_MAP_WRITE)) {210struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);211dri_sw_ws->lf->put_image2((void *)dri_sw_dt->front_private, dri_sw_dt->data, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride);212}213dri_sw_dt->map_flags = 0;214dri_sw_dt->mapped = NULL;215}216217static struct sw_displaytarget *218dri_sw_displaytarget_from_handle(struct sw_winsys *winsys,219const struct pipe_resource *templ,220struct winsys_handle *whandle,221unsigned *stride)222{223assert(0);224return NULL;225}226227static bool228dri_sw_displaytarget_get_handle(struct sw_winsys *winsys,229struct sw_displaytarget *dt,230struct winsys_handle *whandle)231{232struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);233234if (whandle->type == WINSYS_HANDLE_TYPE_SHMID) {235if (dri_sw_dt->shmid < 0)236return false;237whandle->handle = dri_sw_dt->shmid;238return true;239}240241return false;242}243244static void245dri_sw_displaytarget_display(struct sw_winsys *ws,246struct sw_displaytarget *dt,247void *context_private,248struct pipe_box *box)249{250struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);251struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);252struct dri_drawable *dri_drawable = (struct dri_drawable *)context_private;253unsigned width, height, x = 0, y = 0;254unsigned blsize = util_format_get_blocksize(dri_sw_dt->format);255unsigned offset = 0;256unsigned offset_x = 0;257char *data = dri_sw_dt->data;258bool is_shm = dri_sw_dt->shmid != -1;259/* Set the width to 'stride / cpp'.260*261* PutImage correctly clips to the width of the dst drawable.262*/263if (box) {264offset = dri_sw_dt->stride * box->y;265offset_x = box->x * blsize;266data += offset;267/* don't add x offset for shm, the put_image_shm will deal with it */268if (!is_shm)269data += offset_x;270x = box->x;271y = box->y;272width = box->width;273height = box->height;274} else {275width = dri_sw_dt->stride / blsize;276height = dri_sw_dt->height;277}278279if (is_shm) {280dri_sw_ws->lf->put_image_shm(dri_drawable, dri_sw_dt->shmid, dri_sw_dt->data, offset, offset_x,281x, y, width, height, dri_sw_dt->stride);282return;283}284285if (box)286dri_sw_ws->lf->put_image2(dri_drawable, data,287x, y, width, height, dri_sw_dt->stride);288else289dri_sw_ws->lf->put_image(dri_drawable, data, width, height);290}291292static void293dri_destroy_sw_winsys(struct sw_winsys *winsys)294{295FREE(winsys);296}297298struct sw_winsys *299dri_create_sw_winsys(const struct drisw_loader_funcs *lf)300{301struct dri_sw_winsys *ws;302303ws = CALLOC_STRUCT(dri_sw_winsys);304if (!ws)305return NULL;306307ws->lf = lf;308ws->base.destroy = dri_destroy_sw_winsys;309310ws->base.is_displaytarget_format_supported = dri_sw_is_displaytarget_format_supported;311312/* screen texture functions */313ws->base.displaytarget_create = dri_sw_displaytarget_create;314ws->base.displaytarget_destroy = dri_sw_displaytarget_destroy;315ws->base.displaytarget_from_handle = dri_sw_displaytarget_from_handle;316ws->base.displaytarget_get_handle = dri_sw_displaytarget_get_handle;317318/* texture functions */319ws->base.displaytarget_map = dri_sw_displaytarget_map;320ws->base.displaytarget_unmap = dri_sw_displaytarget_unmap;321322ws->base.displaytarget_display = dri_sw_displaytarget_display;323324return &ws->base;325}326327/* vim: set sw=3 ts=8 sts=3 expandtab: */328329330