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