1 /************************************************************************** 2 * 3 * Copyright 2009, VMware, Inc. 4 * All Rights Reserved. 5 * Copyright 2010 George Sapountzis <gsapountzis (at) gmail.com> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29 #include "pipe/p_compiler.h" 30 #include "pipe/p_format.h" 31 #include "util/u_inlines.h" 32 #include "util/u_format.h" 33 #include "util/u_math.h" 34 #include "util/u_memory.h" 35 36 #include "state_tracker/sw_winsys.h" 37 #include "dri_sw_winsys.h" 38 39 40 struct dri_sw_displaytarget 41 { 42 enum pipe_format format; 43 unsigned width; 44 unsigned height; 45 unsigned stride; 46 47 unsigned map_flags; 48 void *data; 49 void *mapped; 50 const void *front_private; 51 }; 52 53 struct dri_sw_winsys 54 { 55 struct sw_winsys base; 56 57 struct drisw_loader_funcs *lf; 58 }; 59 60 static inline struct dri_sw_displaytarget * 61 dri_sw_displaytarget( struct sw_displaytarget *dt ) 62 { 63 return (struct dri_sw_displaytarget *)dt; 64 } 65 66 static inline struct dri_sw_winsys * 67 dri_sw_winsys( struct sw_winsys *ws ) 68 { 69 return (struct dri_sw_winsys *)ws; 70 } 71 72 73 static boolean 74 dri_sw_is_displaytarget_format_supported( struct sw_winsys *ws, 75 unsigned tex_usage, 76 enum pipe_format format ) 77 { 78 /* TODO: check visuals or other sensible thing here */ 79 return TRUE; 80 } 81 82 static struct sw_displaytarget * 83 dri_sw_displaytarget_create(struct sw_winsys *winsys, 84 unsigned tex_usage, 85 enum pipe_format format, 86 unsigned width, unsigned height, 87 unsigned alignment, 88 const void *front_private, 89 unsigned *stride) 90 { 91 struct dri_sw_displaytarget *dri_sw_dt; 92 unsigned nblocksy, size, format_stride; 93 94 dri_sw_dt = CALLOC_STRUCT(dri_sw_displaytarget); 95 if(!dri_sw_dt) 96 goto no_dt; 97 98 dri_sw_dt->format = format; 99 dri_sw_dt->width = width; 100 dri_sw_dt->height = height; 101 dri_sw_dt->front_private = front_private; 102 103 format_stride = util_format_get_stride(format, width); 104 dri_sw_dt->stride = align(format_stride, alignment); 105 106 nblocksy = util_format_get_nblocksy(format, height); 107 size = dri_sw_dt->stride * nblocksy; 108 109 dri_sw_dt->data = align_malloc(size, alignment); 110 if(!dri_sw_dt->data) 111 goto no_data; 112 113 *stride = dri_sw_dt->stride; 114 return (struct sw_displaytarget *)dri_sw_dt; 115 116 no_data: 117 FREE(dri_sw_dt); 118 no_dt: 119 return NULL; 120 } 121 122 static void 123 dri_sw_displaytarget_destroy(struct sw_winsys *ws, 124 struct sw_displaytarget *dt) 125 { 126 struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); 127 128 align_free(dri_sw_dt->data); 129 130 FREE(dri_sw_dt); 131 } 132 133 static void * 134 dri_sw_displaytarget_map(struct sw_winsys *ws, 135 struct sw_displaytarget *dt, 136 unsigned flags) 137 { 138 struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); 139 dri_sw_dt->mapped = dri_sw_dt->data; 140 141 if (dri_sw_dt->front_private && (flags & PIPE_TRANSFER_READ)) { 142 struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws); 143 dri_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); 144 } 145 dri_sw_dt->map_flags = flags; 146 return dri_sw_dt->mapped; 147 } 148 149 static void 150 dri_sw_displaytarget_unmap(struct sw_winsys *ws, 151 struct sw_displaytarget *dt) 152 { 153 struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); 154 if (dri_sw_dt->front_private && (dri_sw_dt->map_flags & PIPE_TRANSFER_WRITE)) { 155 struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws); 156 dri_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); 157 } 158 dri_sw_dt->map_flags = 0; 159 dri_sw_dt->mapped = NULL; 160 } 161 162 static struct sw_displaytarget * 163 dri_sw_displaytarget_from_handle(struct sw_winsys *winsys, 164 const struct pipe_resource *templ, 165 struct winsys_handle *whandle, 166 unsigned *stride) 167 { 168 assert(0); 169 return NULL; 170 } 171 172 static boolean 173 dri_sw_displaytarget_get_handle(struct sw_winsys *winsys, 174 struct sw_displaytarget *dt, 175 struct winsys_handle *whandle) 176 { 177 assert(0); 178 return FALSE; 179 } 180 181 static void 182 dri_sw_displaytarget_display(struct sw_winsys *ws, 183 struct sw_displaytarget *dt, 184 void *context_private, 185 struct pipe_box *box) 186 { 187 struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws); 188 struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt); 189 struct dri_drawable *dri_drawable = (struct dri_drawable *)context_private; 190 unsigned width, height; 191 unsigned blsize = util_format_get_blocksize(dri_sw_dt->format); 192 193 /* Set the width to 'stride / cpp'. 194 * 195 * PutImage correctly clips to the width of the dst drawable. 196 */ 197 width = dri_sw_dt->stride / blsize; 198 199 height = dri_sw_dt->height; 200 201 if (box) { 202 void *data; 203 data = (char *)dri_sw_dt->data + (dri_sw_dt->stride * box->y) + box->x * blsize; 204 dri_sw_ws->lf->put_image2(dri_drawable, data, 205 box->x, box->y, box->width, box->height, dri_sw_dt->stride); 206 } else { 207 dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height); 208 } 209 } 210 211 static void 212 dri_destroy_sw_winsys(struct sw_winsys *winsys) 213 { 214 FREE(winsys); 215 } 216 217 struct sw_winsys * 218 dri_create_sw_winsys(struct drisw_loader_funcs *lf) 219 { 220 struct dri_sw_winsys *ws; 221 222 ws = CALLOC_STRUCT(dri_sw_winsys); 223 if (!ws) 224 return NULL; 225 226 ws->lf = lf; 227 ws->base.destroy = dri_destroy_sw_winsys; 228 229 ws->base.is_displaytarget_format_supported = dri_sw_is_displaytarget_format_supported; 230 231 /* screen texture functions */ 232 ws->base.displaytarget_create = dri_sw_displaytarget_create; 233 ws->base.displaytarget_destroy = dri_sw_displaytarget_destroy; 234 ws->base.displaytarget_from_handle = dri_sw_displaytarget_from_handle; 235 ws->base.displaytarget_get_handle = dri_sw_displaytarget_get_handle; 236 237 /* texture functions */ 238 ws->base.displaytarget_map = dri_sw_displaytarget_map; 239 ws->base.displaytarget_unmap = dri_sw_displaytarget_unmap; 240 241 ws->base.displaytarget_display = dri_sw_displaytarget_display; 242 243 return &ws->base; 244 } 245 246 /* vim: set sw=3 ts=8 sts=3 expandtab: */ 247