1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 2006 VMware, Inc.
4848b8605Smrg * All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the
8848b8605Smrg * "Software"), to deal in the Software without restriction, including
9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
12848b8605Smrg * the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice (including the
15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
16848b8605Smrg * of the Software.
17848b8605Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25848b8605Smrg *
26848b8605Smrg **************************************************************************/
27848b8605Smrg /*
28848b8605Smrg  * Authors:
29848b8605Smrg  *   Keith Whitwell <keithw@vmware.com>
30848b8605Smrg  *   Michel Dänzer <daenzer@vmware.com>
31848b8605Smrg  */
32848b8605Smrg
33848b8605Smrg#include "pipe/p_defines.h"
34848b8605Smrg#include "util/u_inlines.h"
35848b8605Smrg
36848b8605Smrg#include "util/u_format.h"
37848b8605Smrg#include "util/u_math.h"
38848b8605Smrg#include "util/u_memory.h"
39848b8605Smrg#include "util/u_transfer.h"
40b8e80941Smrg#include "util/u_surface.h"
41848b8605Smrg
42848b8605Smrg#include "sp_context.h"
43848b8605Smrg#include "sp_flush.h"
44848b8605Smrg#include "sp_texture.h"
45848b8605Smrg#include "sp_screen.h"
46848b8605Smrg
47848b8605Smrg#include "state_tracker/sw_winsys.h"
48848b8605Smrg
49848b8605Smrg
50848b8605Smrg/**
51848b8605Smrg * Conventional allocation path for non-display textures:
52848b8605Smrg * Use a simple, maximally packed layout.
53848b8605Smrg */
54848b8605Smrgstatic boolean
55848b8605Smrgsoftpipe_resource_layout(struct pipe_screen *screen,
56848b8605Smrg                         struct softpipe_resource *spr,
57848b8605Smrg                         boolean allocate)
58848b8605Smrg{
59848b8605Smrg   struct pipe_resource *pt = &spr->base;
60848b8605Smrg   unsigned level;
61848b8605Smrg   unsigned width = pt->width0;
62848b8605Smrg   unsigned height = pt->height0;
63848b8605Smrg   unsigned depth = pt->depth0;
64848b8605Smrg   uint64_t buffer_size = 0;
65848b8605Smrg
66848b8605Smrg   for (level = 0; level <= pt->last_level; level++) {
67b8e80941Smrg      unsigned slices, nblocksy;
68b8e80941Smrg
69b8e80941Smrg      nblocksy = util_format_get_nblocksy(pt->format, height);
70848b8605Smrg
71848b8605Smrg      if (pt->target == PIPE_TEXTURE_CUBE)
72b8e80941Smrg         assert(pt->array_size == 6);
73b8e80941Smrg
74b8e80941Smrg      if (pt->target == PIPE_TEXTURE_3D)
75848b8605Smrg         slices = depth;
76848b8605Smrg      else
77848b8605Smrg         slices = pt->array_size;
78848b8605Smrg
79848b8605Smrg      spr->stride[level] = util_format_get_stride(pt->format, width);
80848b8605Smrg
81848b8605Smrg      spr->level_offset[level] = buffer_size;
82848b8605Smrg
83b8e80941Smrg      /* if row_stride * height > SP_MAX_TEXTURE_SIZE */
84b8e80941Smrg      if ((uint64_t)spr->stride[level] * nblocksy > SP_MAX_TEXTURE_SIZE) {
85b8e80941Smrg         /* image too large */
86b8e80941Smrg         return FALSE;
87b8e80941Smrg      }
88b8e80941Smrg
89b8e80941Smrg      spr->img_stride[level] = spr->stride[level] * nblocksy;
90b8e80941Smrg
91b8e80941Smrg      buffer_size += (uint64_t) spr->img_stride[level] * slices;
92848b8605Smrg
93848b8605Smrg      width  = u_minify(width, 1);
94848b8605Smrg      height = u_minify(height, 1);
95848b8605Smrg      depth = u_minify(depth, 1);
96848b8605Smrg   }
97848b8605Smrg
98848b8605Smrg   if (buffer_size > SP_MAX_TEXTURE_SIZE)
99848b8605Smrg      return FALSE;
100848b8605Smrg
101848b8605Smrg   if (allocate) {
102848b8605Smrg      spr->data = align_malloc(buffer_size, 64);
103848b8605Smrg      return spr->data != NULL;
104848b8605Smrg   }
105848b8605Smrg   else {
106848b8605Smrg      return TRUE;
107848b8605Smrg   }
108848b8605Smrg}
109848b8605Smrg
110848b8605Smrg
111848b8605Smrg/**
112848b8605Smrg * Check the size of the texture specified by 'res'.
113848b8605Smrg * \return TRUE if OK, FALSE if too large.
114848b8605Smrg */
115848b8605Smrgstatic boolean
116848b8605Smrgsoftpipe_can_create_resource(struct pipe_screen *screen,
117848b8605Smrg                             const struct pipe_resource *res)
118848b8605Smrg{
119848b8605Smrg   struct softpipe_resource spr;
120848b8605Smrg   memset(&spr, 0, sizeof(spr));
121848b8605Smrg   spr.base = *res;
122848b8605Smrg   return softpipe_resource_layout(screen, &spr, FALSE);
123848b8605Smrg}
124848b8605Smrg
125848b8605Smrg
126848b8605Smrg/**
127848b8605Smrg * Texture layout for simple color buffers.
128848b8605Smrg */
129848b8605Smrgstatic boolean
130848b8605Smrgsoftpipe_displaytarget_layout(struct pipe_screen *screen,
131b8e80941Smrg                              struct softpipe_resource *spr,
132b8e80941Smrg                              const void *map_front_private)
133848b8605Smrg{
134848b8605Smrg   struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
135848b8605Smrg
136848b8605Smrg   /* Round up the surface size to a multiple of the tile size?
137848b8605Smrg    */
138848b8605Smrg   spr->dt = winsys->displaytarget_create(winsys,
139848b8605Smrg                                          spr->base.bind,
140848b8605Smrg                                          spr->base.format,
141848b8605Smrg                                          spr->base.width0,
142848b8605Smrg                                          spr->base.height0,
143848b8605Smrg                                          64,
144b8e80941Smrg                                          map_front_private,
145848b8605Smrg                                          &spr->stride[0] );
146848b8605Smrg
147848b8605Smrg   return spr->dt != NULL;
148848b8605Smrg}
149848b8605Smrg
150848b8605Smrg
151848b8605Smrg/**
152848b8605Smrg * Create new pipe_resource given the template information.
153848b8605Smrg */
154848b8605Smrgstatic struct pipe_resource *
155b8e80941Smrgsoftpipe_resource_create_front(struct pipe_screen *screen,
156b8e80941Smrg                               const struct pipe_resource *templat,
157b8e80941Smrg                               const void *map_front_private)
158848b8605Smrg{
159848b8605Smrg   struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource);
160848b8605Smrg   if (!spr)
161848b8605Smrg      return NULL;
162848b8605Smrg
163848b8605Smrg   assert(templat->format != PIPE_FORMAT_NONE);
164848b8605Smrg
165848b8605Smrg   spr->base = *templat;
166848b8605Smrg   pipe_reference_init(&spr->base.reference, 1);
167848b8605Smrg   spr->base.screen = screen;
168848b8605Smrg
169b8e80941Smrg   spr->pot = (util_is_power_of_two_or_zero(templat->width0) &&
170b8e80941Smrg               util_is_power_of_two_or_zero(templat->height0) &&
171b8e80941Smrg               util_is_power_of_two_or_zero(templat->depth0));
172848b8605Smrg
173848b8605Smrg   if (spr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
174848b8605Smrg			 PIPE_BIND_SCANOUT |
175848b8605Smrg			 PIPE_BIND_SHARED)) {
176b8e80941Smrg      if (!softpipe_displaytarget_layout(screen, spr, map_front_private))
177848b8605Smrg         goto fail;
178848b8605Smrg   }
179848b8605Smrg   else {
180848b8605Smrg      if (!softpipe_resource_layout(screen, spr, TRUE))
181848b8605Smrg         goto fail;
182848b8605Smrg   }
183848b8605Smrg
184848b8605Smrg   return &spr->base;
185848b8605Smrg
186848b8605Smrg fail:
187848b8605Smrg   FREE(spr);
188848b8605Smrg   return NULL;
189848b8605Smrg}
190848b8605Smrg
191b8e80941Smrgstatic struct pipe_resource *
192b8e80941Smrgsoftpipe_resource_create(struct pipe_screen *screen,
193b8e80941Smrg                         const struct pipe_resource *templat)
194b8e80941Smrg{
195b8e80941Smrg   return softpipe_resource_create_front(screen, templat, NULL);
196b8e80941Smrg}
197848b8605Smrg
198848b8605Smrgstatic void
199848b8605Smrgsoftpipe_resource_destroy(struct pipe_screen *pscreen,
200848b8605Smrg			  struct pipe_resource *pt)
201848b8605Smrg{
202848b8605Smrg   struct softpipe_screen *screen = softpipe_screen(pscreen);
203848b8605Smrg   struct softpipe_resource *spr = softpipe_resource(pt);
204848b8605Smrg
205848b8605Smrg   if (spr->dt) {
206848b8605Smrg      /* display target */
207848b8605Smrg      struct sw_winsys *winsys = screen->winsys;
208848b8605Smrg      winsys->displaytarget_destroy(winsys, spr->dt);
209848b8605Smrg   }
210848b8605Smrg   else if (!spr->userBuffer) {
211848b8605Smrg      /* regular texture */
212848b8605Smrg      align_free(spr->data);
213848b8605Smrg   }
214848b8605Smrg
215848b8605Smrg   FREE(spr);
216848b8605Smrg}
217848b8605Smrg
218848b8605Smrg
219848b8605Smrgstatic struct pipe_resource *
220848b8605Smrgsoftpipe_resource_from_handle(struct pipe_screen *screen,
221848b8605Smrg                              const struct pipe_resource *templat,
222b8e80941Smrg                              struct winsys_handle *whandle,
223b8e80941Smrg                              unsigned usage)
224848b8605Smrg{
225848b8605Smrg   struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
226848b8605Smrg   struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource);
227848b8605Smrg   if (!spr)
228848b8605Smrg      return NULL;
229848b8605Smrg
230848b8605Smrg   spr->base = *templat;
231848b8605Smrg   pipe_reference_init(&spr->base.reference, 1);
232848b8605Smrg   spr->base.screen = screen;
233848b8605Smrg
234b8e80941Smrg   spr->pot = (util_is_power_of_two_or_zero(templat->width0) &&
235b8e80941Smrg               util_is_power_of_two_or_zero(templat->height0) &&
236b8e80941Smrg               util_is_power_of_two_or_zero(templat->depth0));
237848b8605Smrg
238848b8605Smrg   spr->dt = winsys->displaytarget_from_handle(winsys,
239848b8605Smrg                                               templat,
240848b8605Smrg                                               whandle,
241848b8605Smrg                                               &spr->stride[0]);
242848b8605Smrg   if (!spr->dt)
243848b8605Smrg      goto fail;
244848b8605Smrg
245848b8605Smrg   return &spr->base;
246848b8605Smrg
247848b8605Smrg fail:
248848b8605Smrg   FREE(spr);
249848b8605Smrg   return NULL;
250848b8605Smrg}
251848b8605Smrg
252848b8605Smrg
253848b8605Smrgstatic boolean
254848b8605Smrgsoftpipe_resource_get_handle(struct pipe_screen *screen,
255b8e80941Smrg                             struct pipe_context *ctx,
256848b8605Smrg                             struct pipe_resource *pt,
257b8e80941Smrg                             struct winsys_handle *whandle,
258b8e80941Smrg                             unsigned usage)
259848b8605Smrg{
260848b8605Smrg   struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
261848b8605Smrg   struct softpipe_resource *spr = softpipe_resource(pt);
262848b8605Smrg
263848b8605Smrg   assert(spr->dt);
264848b8605Smrg   if (!spr->dt)
265848b8605Smrg      return FALSE;
266848b8605Smrg
267848b8605Smrg   return winsys->displaytarget_get_handle(winsys, spr->dt, whandle);
268848b8605Smrg}
269848b8605Smrg
270848b8605Smrg
271848b8605Smrg/**
272848b8605Smrg * Helper function to compute offset (in bytes) for a particular
273848b8605Smrg * texture level/face/slice from the start of the buffer.
274848b8605Smrg */
275b8e80941Smrgunsigned
276b8e80941Smrgsoftpipe_get_tex_image_offset(const struct softpipe_resource *spr,
277b8e80941Smrg                              unsigned level, unsigned layer)
278848b8605Smrg{
279848b8605Smrg   unsigned offset = spr->level_offset[level];
280848b8605Smrg
281b8e80941Smrg   offset += layer * spr->img_stride[level];
282848b8605Smrg
283848b8605Smrg   return offset;
284848b8605Smrg}
285848b8605Smrg
286848b8605Smrg
287848b8605Smrg/**
288848b8605Smrg * Get a pipe_surface "view" into a texture resource.
289848b8605Smrg */
290848b8605Smrgstatic struct pipe_surface *
291848b8605Smrgsoftpipe_create_surface(struct pipe_context *pipe,
292848b8605Smrg                        struct pipe_resource *pt,
293848b8605Smrg                        const struct pipe_surface *surf_tmpl)
294848b8605Smrg{
295848b8605Smrg   struct pipe_surface *ps;
296848b8605Smrg
297848b8605Smrg   ps = CALLOC_STRUCT(pipe_surface);
298848b8605Smrg   if (ps) {
299848b8605Smrg      pipe_reference_init(&ps->reference, 1);
300848b8605Smrg      pipe_resource_reference(&ps->texture, pt);
301848b8605Smrg      ps->context = pipe;
302848b8605Smrg      ps->format = surf_tmpl->format;
303848b8605Smrg      if (pt->target != PIPE_BUFFER) {
304848b8605Smrg         assert(surf_tmpl->u.tex.level <= pt->last_level);
305848b8605Smrg         ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
306848b8605Smrg         ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
307848b8605Smrg         ps->u.tex.level = surf_tmpl->u.tex.level;
308848b8605Smrg         ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
309848b8605Smrg         ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
310848b8605Smrg         if (ps->u.tex.first_layer != ps->u.tex.last_layer) {
311848b8605Smrg            debug_printf("creating surface with multiple layers, rendering to first layer only\n");
312848b8605Smrg         }
313848b8605Smrg      }
314848b8605Smrg      else {
315848b8605Smrg         /* setting width as number of elements should get us correct renderbuffer width */
316848b8605Smrg         ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1;
317848b8605Smrg         ps->height = pt->height0;
318848b8605Smrg         ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
319848b8605Smrg         ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
320848b8605Smrg         assert(ps->u.buf.first_element <= ps->u.buf.last_element);
321848b8605Smrg         assert(ps->u.buf.last_element < ps->width);
322848b8605Smrg      }
323848b8605Smrg   }
324848b8605Smrg   return ps;
325848b8605Smrg}
326848b8605Smrg
327848b8605Smrg
328848b8605Smrg/**
329848b8605Smrg * Free a pipe_surface which was created with softpipe_create_surface().
330848b8605Smrg */
331848b8605Smrgstatic void
332848b8605Smrgsoftpipe_surface_destroy(struct pipe_context *pipe,
333848b8605Smrg                         struct pipe_surface *surf)
334848b8605Smrg{
335848b8605Smrg   /* Effectively do the texture_update work here - if texture images
336848b8605Smrg    * needed post-processing to put them into hardware layout, this is
337848b8605Smrg    * where it would happen.  For softpipe, nothing to do.
338848b8605Smrg    */
339848b8605Smrg   assert(surf->texture);
340848b8605Smrg   pipe_resource_reference(&surf->texture, NULL);
341848b8605Smrg   FREE(surf);
342848b8605Smrg}
343848b8605Smrg
344848b8605Smrg
345848b8605Smrg/**
346848b8605Smrg * Geta pipe_transfer object which is used for moving data in/out of
347848b8605Smrg * a resource object.
348848b8605Smrg * \param pipe  rendering context
349848b8605Smrg * \param resource  the resource to transfer in/out of
350848b8605Smrg * \param level  which mipmap level
351848b8605Smrg * \param usage  bitmask of PIPE_TRANSFER_x flags
352848b8605Smrg * \param box  the 1D/2D/3D region of interest
353848b8605Smrg */
354848b8605Smrgstatic void *
355848b8605Smrgsoftpipe_transfer_map(struct pipe_context *pipe,
356848b8605Smrg                      struct pipe_resource *resource,
357848b8605Smrg                      unsigned level,
358848b8605Smrg                      unsigned usage,
359848b8605Smrg                      const struct pipe_box *box,
360848b8605Smrg                      struct pipe_transfer **transfer)
361848b8605Smrg{
362848b8605Smrg   struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
363848b8605Smrg   struct softpipe_resource *spr = softpipe_resource(resource);
364848b8605Smrg   struct softpipe_transfer *spt;
365848b8605Smrg   struct pipe_transfer *pt;
366848b8605Smrg   enum pipe_format format = resource->format;
367848b8605Smrg   uint8_t *map;
368848b8605Smrg
369848b8605Smrg   assert(resource);
370848b8605Smrg   assert(level <= resource->last_level);
371848b8605Smrg
372848b8605Smrg   /* make sure the requested region is in the image bounds */
373848b8605Smrg   assert(box->x + box->width <= (int) u_minify(resource->width0, level));
374848b8605Smrg   if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
375848b8605Smrg      assert(box->y + box->height <= (int) resource->array_size);
376848b8605Smrg   }
377848b8605Smrg   else {
378848b8605Smrg      assert(box->y + box->height <= (int) u_minify(resource->height0, level));
379848b8605Smrg      if (resource->target == PIPE_TEXTURE_2D_ARRAY) {
380848b8605Smrg         assert(box->z + box->depth <= (int) resource->array_size);
381848b8605Smrg      }
382848b8605Smrg      else if (resource->target == PIPE_TEXTURE_CUBE) {
383848b8605Smrg         assert(box->z < 6);
384848b8605Smrg      }
385848b8605Smrg      else if (resource->target == PIPE_TEXTURE_CUBE_ARRAY) {
386848b8605Smrg         assert(box->z <= (int) resource->array_size);
387848b8605Smrg      }
388848b8605Smrg      else {
389848b8605Smrg         assert(box->z + box->depth <= (int) u_minify(resource->depth0, level));
390848b8605Smrg      }
391848b8605Smrg   }
392848b8605Smrg
393848b8605Smrg   /*
394848b8605Smrg    * Transfers, like other pipe operations, must happen in order, so flush the
395848b8605Smrg    * context if necessary.
396848b8605Smrg    */
397848b8605Smrg   if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
398848b8605Smrg      boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
399848b8605Smrg      boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
400848b8605Smrg      if (!softpipe_flush_resource(pipe, resource,
401848b8605Smrg                                   level, box->depth > 1 ? -1 : box->z,
402848b8605Smrg                                   0, /* flush_flags */
403848b8605Smrg                                   read_only,
404848b8605Smrg                                   TRUE, /* cpu_access */
405848b8605Smrg                                   do_not_block)) {
406848b8605Smrg         /*
407848b8605Smrg          * It would have blocked, but state tracker requested no to.
408848b8605Smrg          */
409848b8605Smrg         assert(do_not_block);
410848b8605Smrg         return NULL;
411848b8605Smrg      }
412848b8605Smrg   }
413848b8605Smrg
414848b8605Smrg   spt = CALLOC_STRUCT(softpipe_transfer);
415848b8605Smrg   if (!spt)
416848b8605Smrg      return NULL;
417848b8605Smrg
418848b8605Smrg   pt = &spt->base;
419848b8605Smrg
420848b8605Smrg   pipe_resource_reference(&pt->resource, resource);
421848b8605Smrg   pt->level = level;
422848b8605Smrg   pt->usage = usage;
423848b8605Smrg   pt->box = *box;
424848b8605Smrg   pt->stride = spr->stride[level];
425b8e80941Smrg   pt->layer_stride = spr->img_stride[level];
426848b8605Smrg
427b8e80941Smrg   spt->offset = softpipe_get_tex_image_offset(spr, level, box->z);
428848b8605Smrg
429848b8605Smrg   spt->offset +=
430848b8605Smrg         box->y / util_format_get_blockheight(format) * spt->base.stride +
431848b8605Smrg         box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
432848b8605Smrg
433848b8605Smrg   /* resources backed by display target treated specially:
434848b8605Smrg    */
435848b8605Smrg   if (spr->dt) {
436848b8605Smrg      map = winsys->displaytarget_map(winsys, spr->dt, usage);
437848b8605Smrg   }
438848b8605Smrg   else {
439848b8605Smrg      map = spr->data;
440848b8605Smrg   }
441848b8605Smrg
442b8e80941Smrg   if (!map) {
443848b8605Smrg      pipe_resource_reference(&pt->resource, NULL);
444848b8605Smrg      FREE(spt);
445848b8605Smrg      return NULL;
446848b8605Smrg   }
447848b8605Smrg
448848b8605Smrg   *transfer = pt;
449848b8605Smrg   return map + spt->offset;
450848b8605Smrg}
451848b8605Smrg
452848b8605Smrg
453848b8605Smrg/**
454848b8605Smrg * Unmap memory mapping for given pipe_transfer object.
455848b8605Smrg */
456848b8605Smrgstatic void
457848b8605Smrgsoftpipe_transfer_unmap(struct pipe_context *pipe,
458848b8605Smrg                        struct pipe_transfer *transfer)
459848b8605Smrg{
460848b8605Smrg   struct softpipe_resource *spr;
461848b8605Smrg
462848b8605Smrg   assert(transfer->resource);
463848b8605Smrg   spr = softpipe_resource(transfer->resource);
464848b8605Smrg
465848b8605Smrg   if (spr->dt) {
466848b8605Smrg      /* display target */
467848b8605Smrg      struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
468848b8605Smrg      winsys->displaytarget_unmap(winsys, spr->dt);
469848b8605Smrg   }
470848b8605Smrg
471848b8605Smrg   if (transfer->usage & PIPE_TRANSFER_WRITE) {
472848b8605Smrg      /* Mark the texture as dirty to expire the tile caches. */
473848b8605Smrg      spr->timestamp++;
474848b8605Smrg   }
475848b8605Smrg
476848b8605Smrg   pipe_resource_reference(&transfer->resource, NULL);
477848b8605Smrg   FREE(transfer);
478848b8605Smrg}
479848b8605Smrg
480848b8605Smrg/**
481848b8605Smrg * Create buffer which wraps user-space data.
482848b8605Smrg */
483848b8605Smrgstruct pipe_resource *
484848b8605Smrgsoftpipe_user_buffer_create(struct pipe_screen *screen,
485848b8605Smrg                            void *ptr,
486848b8605Smrg                            unsigned bytes,
487848b8605Smrg			    unsigned bind_flags)
488848b8605Smrg{
489848b8605Smrg   struct softpipe_resource *spr;
490848b8605Smrg
491848b8605Smrg   spr = CALLOC_STRUCT(softpipe_resource);
492848b8605Smrg   if (!spr)
493848b8605Smrg      return NULL;
494848b8605Smrg
495848b8605Smrg   pipe_reference_init(&spr->base.reference, 1);
496848b8605Smrg   spr->base.screen = screen;
497848b8605Smrg   spr->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
498848b8605Smrg   spr->base.bind = bind_flags;
499848b8605Smrg   spr->base.usage = PIPE_USAGE_IMMUTABLE;
500848b8605Smrg   spr->base.flags = 0;
501848b8605Smrg   spr->base.width0 = bytes;
502848b8605Smrg   spr->base.height0 = 1;
503848b8605Smrg   spr->base.depth0 = 1;
504848b8605Smrg   spr->base.array_size = 1;
505848b8605Smrg   spr->userBuffer = TRUE;
506848b8605Smrg   spr->data = ptr;
507848b8605Smrg
508848b8605Smrg   return &spr->base;
509848b8605Smrg}
510848b8605Smrg
511848b8605Smrg
512848b8605Smrgvoid
513848b8605Smrgsoftpipe_init_texture_funcs(struct pipe_context *pipe)
514848b8605Smrg{
515848b8605Smrg   pipe->transfer_map = softpipe_transfer_map;
516848b8605Smrg   pipe->transfer_unmap = softpipe_transfer_unmap;
517848b8605Smrg
518848b8605Smrg   pipe->transfer_flush_region = u_default_transfer_flush_region;
519b8e80941Smrg   pipe->buffer_subdata = u_default_buffer_subdata;
520b8e80941Smrg   pipe->texture_subdata = u_default_texture_subdata;
521848b8605Smrg
522848b8605Smrg   pipe->create_surface = softpipe_create_surface;
523848b8605Smrg   pipe->surface_destroy = softpipe_surface_destroy;
524b8e80941Smrg   pipe->clear_texture = util_clear_texture;
525848b8605Smrg}
526848b8605Smrg
527848b8605Smrg
528848b8605Smrgvoid
529848b8605Smrgsoftpipe_init_screen_texture_funcs(struct pipe_screen *screen)
530848b8605Smrg{
531848b8605Smrg   screen->resource_create = softpipe_resource_create;
532b8e80941Smrg   screen->resource_create_front = softpipe_resource_create_front;
533848b8605Smrg   screen->resource_destroy = softpipe_resource_destroy;
534848b8605Smrg   screen->resource_from_handle = softpipe_resource_from_handle;
535848b8605Smrg   screen->resource_get_handle = softpipe_resource_get_handle;
536848b8605Smrg   screen->can_create_resource = softpipe_can_create_resource;
537848b8605Smrg}
538