wrapper_sw_winsys.c revision c9f98673c5b6830cd1f41c0c53a9e5e299d47464
1/********************************************************** 2 * Copyright 2010 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 **********************************************************/ 25 26 27#include "wrapper_sw_winsys.h" 28 29#include "pipe/p_format.h" 30#include "pipe/p_state.h" 31 32#include "state_tracker/sw_winsys.h" 33 34#include "util/u_memory.h" 35#include "util/u_inlines.h" 36 37/* 38 * This code wraps a pipe_screen and exposes a sw_winsys interface for use 39 * with software resterizers. This code is used by the DRM based winsys to 40 * allow access to the drm driver. 41 * 42 * We must borrow the whole stack because only the pipe screen knows how 43 * to decode the content of a buffer. Or how to create a buffer that 44 * can still be used by drivers using real hardware (as the case is 45 * with software st/xorg but hw st/dri). 46 * 47 * We also need a pipe context for the transfers. 48 */ 49 50struct wrapper_sw_winsys 51{ 52 struct sw_winsys base; 53 struct pipe_screen *screen; 54 struct pipe_context *pipe; 55}; 56 57struct wrapper_sw_displaytarget 58{ 59 struct wrapper_sw_winsys *winsys; 60 struct pipe_texture *tex; 61 struct pipe_transfer *transfer; 62 63 unsigned width; 64 unsigned height; 65 unsigned map_count; 66 unsigned stride; /**< because we give stride at create */ 67 void *ptr; 68}; 69 70static INLINE struct wrapper_sw_winsys * 71wrapper_sw_winsys(struct sw_winsys *ws) 72{ 73 return (struct wrapper_sw_winsys *)ws; 74} 75 76static INLINE struct wrapper_sw_displaytarget * 77wrapper_sw_displaytarget(struct sw_displaytarget *dt) 78{ 79 return (struct wrapper_sw_displaytarget *)dt; 80} 81 82 83/* 84 * Functions 85 */ 86 87 88static boolean 89wsw_dt_get_stride(struct wrapper_sw_displaytarget *wdt, unsigned *stride) 90{ 91 struct pipe_context *pipe = wdt->winsys->pipe; 92 struct pipe_texture *tex = wdt->tex; 93 struct pipe_transfer *tr; 94 95 tr = pipe->get_tex_transfer(pipe, tex, 0, 0, 0, 96 PIPE_TRANSFER_READ_WRITE, 97 0, 0, wdt->width, wdt->height); 98 if (!tr) 99 return FALSE; 100 101 *stride = tr->stride; 102 wdt->stride = tr->stride; 103 104 pipe->tex_transfer_destroy(pipe, tr); 105 106 return TRUE; 107} 108 109static struct sw_displaytarget * 110wsw_dt_wrap_texture(struct wrapper_sw_winsys *wsw, 111 struct pipe_texture *tex, unsigned *stride) 112{ 113 struct wrapper_sw_displaytarget *wdt = CALLOC_STRUCT(wrapper_sw_displaytarget); 114 if (!wdt) 115 goto err_unref; 116 117 wdt->tex = tex; 118 wdt->winsys = wsw; 119 120 if (!wsw_dt_get_stride(wdt, stride)) 121 goto err_free; 122 123 return (struct sw_displaytarget *)wdt; 124 125err_free: 126 FREE(wdt); 127err_unref: 128 pipe_texture_reference(&tex, NULL); 129 return NULL; 130} 131 132static struct sw_displaytarget * 133wsw_dt_create(struct sw_winsys *ws, 134 unsigned tex_usage, 135 enum pipe_format format, 136 unsigned width, unsigned height, 137 unsigned alignment, 138 unsigned *stride) 139{ 140 struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); 141 struct pipe_texture templ; 142 struct pipe_texture *tex; 143 144 /* 145 * XXX Why don't we just get the template. 146 */ 147 memset(&templ, 0, sizeof(templ)); 148 templ.width0 = width; 149 templ.height0 = height; 150 templ.format = format; 151 templ.tex_usage = tex_usage; 152 153 /* XXX alignment: we can't do anything about this */ 154 155 tex = wsw->screen->texture_create(wsw->screen, &templ); 156 if (!tex) 157 return NULL; 158 159 return wsw_dt_wrap_texture(wsw, tex, stride); 160} 161 162static struct sw_displaytarget * 163wsw_dt_from_handle(struct sw_winsys *ws, 164 const struct pipe_texture *templ, 165 struct winsys_handle *whandle, 166 unsigned *stride) 167{ 168 struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); 169 struct pipe_texture *tex; 170 171 tex = wsw->screen->texture_from_handle(wsw->screen, templ, whandle); 172 if (!tex) 173 return NULL; 174 175 return wsw_dt_wrap_texture(wsw, tex, stride); 176} 177 178static void * 179wsw_dt_map(struct sw_winsys *ws, 180 struct sw_displaytarget *dt, 181 unsigned flags) 182{ 183 struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); 184 struct pipe_context *pipe = wdt->winsys->pipe; 185 struct pipe_texture *tex = wdt->tex; 186 struct pipe_transfer *tr; 187 void *ptr; 188 189 if (!wdt->map_count) { 190 191 assert(!wdt->transfer); 192 193 tr = pipe->get_tex_transfer(pipe, tex, 0, 0, 0, 194 PIPE_TRANSFER_READ_WRITE, 195 0, 0, wdt->width, wdt->height); 196 if (!tr) 197 return NULL; 198 199 ptr = pipe->transfer_map(pipe, tr); 200 if (!ptr) 201 goto err; 202 203 wdt->transfer = tr; 204 wdt->ptr = ptr; 205 206 /* XXX Handle this case */ 207 assert(tr->stride == wdt->stride); 208 } 209 210 wdt->map_count++; 211 212 return wdt->ptr; 213 214err: 215 pipe->tex_transfer_destroy(pipe, tr); 216 return NULL; 217} 218 219static void 220wsw_dt_unmap(struct sw_winsys *ws, 221 struct sw_displaytarget *dt) 222{ 223 struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); 224 struct pipe_context *pipe = wdt->winsys->pipe; 225 226 assert(wdt->transfer); 227 228 wdt->map_count--; 229 230 if (wdt->map_count) 231 return; 232 233 pipe->transfer_unmap(pipe, wdt->transfer); 234 pipe->tex_transfer_destroy(pipe, wdt->transfer); 235 wdt->transfer = NULL; 236} 237 238static void 239wsw_dt_destroy(struct sw_winsys *ws, 240 struct sw_displaytarget *dt) 241{ 242 struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); 243 244 pipe_texture_reference(&wdt->tex, NULL); 245 246 FREE(wdt); 247} 248 249static void 250wsw_destroy(struct sw_winsys *ws) 251{ 252 struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); 253 254 wsw->pipe->destroy(wsw->pipe); 255 wsw->screen->destroy(wsw->screen); 256 257 FREE(wsw); 258} 259 260struct sw_winsys * 261wrapper_sw_winsys_warp_pipe_screen(struct pipe_screen *screen) 262{ 263 struct wrapper_sw_winsys *wsw = CALLOC_STRUCT(wrapper_sw_winsys); 264 265 wsw->base.displaytarget_create = wsw_dt_create; 266 wsw->base.displaytarget_from_handle = wsw_dt_from_handle; 267 wsw->base.displaytarget_map = wsw_dt_map; 268 wsw->base.displaytarget_unmap = wsw_dt_unmap; 269 wsw->base.displaytarget_destroy = wsw_dt_destroy; 270 wsw->base.destroy = wsw_destroy; 271 272 wsw->screen = screen; 273 wsw->pipe = screen->context_create(screen, NULL); 274 if (!wsw->pipe) 275 goto err; 276 277 return &wsw->base; 278 279err: 280 FREE(wsw); 281 return NULL; 282} 283