wrapper_sw_winsys.c revision 4c7001462607e6e99e474d6271dd481d3f8f201c
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 enum pipe_texture_target target; 56}; 57 58struct wrapper_sw_displaytarget 59{ 60 struct wrapper_sw_winsys *winsys; 61 struct pipe_resource *tex; 62 struct pipe_transfer *transfer; 63 64 unsigned width; 65 unsigned height; 66 unsigned map_count; 67 unsigned stride; /**< because we give stride at create */ 68 void *ptr; 69}; 70 71static INLINE struct wrapper_sw_winsys * 72wrapper_sw_winsys(struct sw_winsys *ws) 73{ 74 return (struct wrapper_sw_winsys *)ws; 75} 76 77static INLINE struct wrapper_sw_displaytarget * 78wrapper_sw_displaytarget(struct sw_displaytarget *dt) 79{ 80 return (struct wrapper_sw_displaytarget *)dt; 81} 82 83 84/* 85 * Functions 86 */ 87 88 89static boolean 90wsw_dt_get_stride(struct wrapper_sw_displaytarget *wdt, unsigned *stride) 91{ 92 struct pipe_context *pipe = wdt->winsys->pipe; 93 struct pipe_resource *tex = wdt->tex; 94 struct pipe_transfer *tr; 95 96 tr = pipe_get_transfer(pipe, tex, 0, 0, 97 PIPE_TRANSFER_READ_WRITE, 98 0, 0, wdt->width, wdt->height); 99 if (!tr) 100 return FALSE; 101 102 *stride = tr->stride; 103 wdt->stride = tr->stride; 104 105 pipe->transfer_destroy(pipe, tr); 106 107 return TRUE; 108} 109 110static struct sw_displaytarget * 111wsw_dt_wrap_texture(struct wrapper_sw_winsys *wsw, 112 struct pipe_resource *tex, unsigned *stride) 113{ 114 struct wrapper_sw_displaytarget *wdt = CALLOC_STRUCT(wrapper_sw_displaytarget); 115 if (!wdt) 116 goto err_unref; 117 118 wdt->tex = tex; 119 wdt->winsys = wsw; 120 121 if (!wsw_dt_get_stride(wdt, stride)) 122 goto err_free; 123 124 return (struct sw_displaytarget *)wdt; 125 126err_free: 127 FREE(wdt); 128err_unref: 129 pipe_resource_reference(&tex, NULL); 130 return NULL; 131} 132 133static struct sw_displaytarget * 134wsw_dt_create(struct sw_winsys *ws, 135 unsigned bind, 136 enum pipe_format format, 137 unsigned width, unsigned height, 138 unsigned alignment, 139 unsigned *stride) 140{ 141 struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); 142 struct pipe_resource templ; 143 struct pipe_resource *tex; 144 145 /* 146 * XXX Why don't we just get the template. 147 */ 148 memset(&templ, 0, sizeof(templ)); 149 templ.target = wsw->target; 150 templ.width0 = width; 151 templ.height0 = height; 152 templ.depth0 = 1; 153 templ.array_size = 1; 154 templ.format = format; 155 templ.bind = bind; 156 157 /* XXX alignment: we can't do anything about this */ 158 159 tex = wsw->screen->resource_create(wsw->screen, &templ); 160 if (!tex) 161 return NULL; 162 163 return wsw_dt_wrap_texture(wsw, tex, stride); 164} 165 166static struct sw_displaytarget * 167wsw_dt_from_handle(struct sw_winsys *ws, 168 const struct pipe_resource *templ, 169 struct winsys_handle *whandle, 170 unsigned *stride) 171{ 172 struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); 173 struct pipe_resource *tex; 174 175 tex = wsw->screen->resource_from_handle(wsw->screen, templ, whandle); 176 if (!tex) 177 return NULL; 178 179 return wsw_dt_wrap_texture(wsw, tex, stride); 180} 181 182static boolean 183wsw_dt_get_handle(struct sw_winsys *ws, 184 struct sw_displaytarget *dt, 185 struct winsys_handle *whandle) 186{ 187 struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); 188 struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); 189 struct pipe_resource *tex = wdt->tex; 190 191 return wsw->screen->resource_get_handle(wsw->screen, tex, whandle); 192} 193 194static void * 195wsw_dt_map(struct sw_winsys *ws, 196 struct sw_displaytarget *dt, 197 unsigned flags) 198{ 199 struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); 200 struct pipe_context *pipe = wdt->winsys->pipe; 201 struct pipe_resource *tex = wdt->tex; 202 struct pipe_transfer *tr; 203 void *ptr; 204 205 if (!wdt->map_count) { 206 207 assert(!wdt->transfer); 208 209 tr = pipe_get_transfer(pipe, tex, 0, 0, 210 PIPE_TRANSFER_READ_WRITE, 211 0, 0, wdt->width, wdt->height); 212 if (!tr) 213 return NULL; 214 215 ptr = pipe->transfer_map(pipe, tr); 216 if (!ptr) 217 goto err; 218 219 wdt->transfer = tr; 220 wdt->ptr = ptr; 221 222 /* XXX Handle this case */ 223 assert(tr->stride == wdt->stride); 224 } 225 226 wdt->map_count++; 227 228 return wdt->ptr; 229 230err: 231 pipe->transfer_destroy(pipe, tr); 232 return NULL; 233} 234 235static void 236wsw_dt_unmap(struct sw_winsys *ws, 237 struct sw_displaytarget *dt) 238{ 239 struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); 240 struct pipe_context *pipe = wdt->winsys->pipe; 241 242 assert(wdt->transfer); 243 244 wdt->map_count--; 245 246 if (wdt->map_count) 247 return; 248 249 pipe->transfer_unmap(pipe, wdt->transfer); 250 pipe->transfer_destroy(pipe, wdt->transfer); 251 wdt->transfer = NULL; 252} 253 254static void 255wsw_dt_destroy(struct sw_winsys *ws, 256 struct sw_displaytarget *dt) 257{ 258 struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); 259 260 pipe_resource_reference(&wdt->tex, NULL); 261 262 FREE(wdt); 263} 264 265static void 266wsw_destroy(struct sw_winsys *ws) 267{ 268 struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); 269 270 wsw->pipe->destroy(wsw->pipe); 271 wsw->screen->destroy(wsw->screen); 272 273 FREE(wsw); 274} 275 276struct sw_winsys * 277wrapper_sw_winsys_wrap_pipe_screen(struct pipe_screen *screen) 278{ 279 struct wrapper_sw_winsys *wsw = CALLOC_STRUCT(wrapper_sw_winsys); 280 281 if (!wsw) 282 goto err; 283 284 wsw->base.displaytarget_create = wsw_dt_create; 285 wsw->base.displaytarget_from_handle = wsw_dt_from_handle; 286 wsw->base.displaytarget_get_handle = wsw_dt_get_handle; 287 wsw->base.displaytarget_map = wsw_dt_map; 288 wsw->base.displaytarget_unmap = wsw_dt_unmap; 289 wsw->base.displaytarget_destroy = wsw_dt_destroy; 290 wsw->base.destroy = wsw_destroy; 291 292 wsw->screen = screen; 293 wsw->pipe = screen->context_create(screen, NULL); 294 if (!wsw->pipe) 295 goto err_free; 296 297 if(screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) 298 wsw->target = PIPE_TEXTURE_2D; 299 else 300 wsw->target = PIPE_TEXTURE_RECT; 301 302 return &wsw->base; 303 304err_free: 305 FREE(wsw); 306err: 307 return NULL; 308} 309 310struct pipe_screen * 311wrapper_sw_winsys_dewrap_pipe_screen(struct sw_winsys *ws) 312{ 313 struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); 314 struct pipe_screen *screen = wsw->screen; 315 316 wsw->pipe->destroy(wsw->pipe); 317 /* don't destroy the screen its needed later on */ 318 319 FREE(wsw); 320 return screen; 321} 322