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