14a49301eSmrg/**************************************************************************
24a49301eSmrg *
3af69d88dSmrg * Copyright 2007 VMware, Inc.
44a49301eSmrg * All Rights Reserved.
54a49301eSmrg *
64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a
74a49301eSmrg * copy of this software and associated documentation files (the
84a49301eSmrg * "Software"), to deal in the Software without restriction, including
94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish,
104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to
114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to
124a49301eSmrg * the following conditions:
134a49301eSmrg *
144a49301eSmrg * The above copyright notice and this permission notice (including the
154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions
164a49301eSmrg * of the Software.
174a49301eSmrg *
184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
254a49301eSmrg *
264a49301eSmrg **************************************************************************/
274a49301eSmrg
284a49301eSmrg/**
294a49301eSmrg * RGBA/float tile get/put functions.
307ec681f3Smrg * Usable both by drivers and gallium frontends.
314a49301eSmrg */
324a49301eSmrg
334a49301eSmrg
344a49301eSmrg#include "pipe/p_defines.h"
35cdc920a0Smrg#include "util/u_inlines.h"
364a49301eSmrg
377ec681f3Smrg#include "util/format/u_format.h"
387ec681f3Smrg#include "util/format/u_format_bptc.h"
394a49301eSmrg#include "util/u_math.h"
404a49301eSmrg#include "util/u_memory.h"
41af69d88dSmrg#include "util/u_surface.h"
424a49301eSmrg#include "util/u_tile.h"
434a49301eSmrg
444a49301eSmrg
454a49301eSmrg/**
464a49301eSmrg * Move raw block of pixels from transfer object to user memory.
474a49301eSmrg */
484a49301eSmrgvoid
49af69d88dSmrgpipe_get_tile_raw(struct pipe_transfer *pt,
50af69d88dSmrg                  const void *src,
514a49301eSmrg                  uint x, uint y, uint w, uint h,
524a49301eSmrg                  void *dst, int dst_stride)
534a49301eSmrg{
544a49301eSmrg   if (dst_stride == 0)
553464ebd5Sriastradh      dst_stride = util_format_get_stride(pt->resource->format, w);
564a49301eSmrg
573464ebd5Sriastradh   if (u_clip_tile(x, y, &w, &h, &pt->box))
584a49301eSmrg      return;
594a49301eSmrg
603464ebd5Sriastradh   util_copy_rect(dst, pt->resource->format, dst_stride, 0, 0, w, h, src, pt->stride, x, y);
614a49301eSmrg}
624a49301eSmrg
634a49301eSmrg
644a49301eSmrg/**
654a49301eSmrg * Move raw block of pixels from user memory to transfer object.
664a49301eSmrg */
674a49301eSmrgvoid
68af69d88dSmrgpipe_put_tile_raw(struct pipe_transfer *pt,
69af69d88dSmrg                  void *dst,
704a49301eSmrg                  uint x, uint y, uint w, uint h,
714a49301eSmrg                  const void *src, int src_stride)
724a49301eSmrg{
733464ebd5Sriastradh   enum pipe_format format = pt->resource->format;
744a49301eSmrg
754a49301eSmrg   if (src_stride == 0)
76cdc920a0Smrg      src_stride = util_format_get_stride(format, w);
774a49301eSmrg
783464ebd5Sriastradh   if (u_clip_tile(x, y, &w, &h, &pt->box))
794a49301eSmrg      return;
804a49301eSmrg
81cdc920a0Smrg   util_copy_rect(dst, format, pt->stride, x, y, w, h, src, src_stride, 0, 0);
824a49301eSmrg}
834a49301eSmrg
844a49301eSmrg
854a49301eSmrg
864a49301eSmrg
874a49301eSmrg/** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */
884a49301eSmrg#define SHORT_TO_FLOAT(S)   ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
894a49301eSmrg
904a49301eSmrg#define UNCLAMPED_FLOAT_TO_SHORT(us, f)  \
914a49301eSmrg   us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
924a49301eSmrg
934a49301eSmrg
944a49301eSmrg
953464ebd5Sriastradh/*** PIPE_FORMAT_Z16_UNORM ***/
964a49301eSmrg
974a49301eSmrg/**
983464ebd5Sriastradh * Return each Z value as four floats in [0,1].
994a49301eSmrg */
1004a49301eSmrgstatic void
1013464ebd5Sriastradhz16_get_tile_rgba(const ushort *src,
1023464ebd5Sriastradh                  unsigned w, unsigned h,
1033464ebd5Sriastradh                  float *p,
1043464ebd5Sriastradh                  unsigned dst_stride)
1054a49301eSmrg{
1063464ebd5Sriastradh   const float scale = 1.0f / 65535.0f;
1074a49301eSmrg   unsigned i, j;
1084a49301eSmrg
1094a49301eSmrg   for (i = 0; i < h; i++) {
1104a49301eSmrg      float *pRow = p;
1114a49301eSmrg      for (j = 0; j < w; j++, pRow += 4) {
1124a49301eSmrg         pRow[0] =
1134a49301eSmrg         pRow[1] =
1143464ebd5Sriastradh         pRow[2] =
1153464ebd5Sriastradh         pRow[3] = *src++ * scale;
1164a49301eSmrg      }
1174a49301eSmrg      p += dst_stride;
1184a49301eSmrg   }
1194a49301eSmrg}
1204a49301eSmrg
1214a49301eSmrg
1224a49301eSmrg
1234a49301eSmrg
1243464ebd5Sriastradh/*** PIPE_FORMAT_Z32_UNORM ***/
1254a49301eSmrg
1263464ebd5Sriastradh/**
1273464ebd5Sriastradh * Return each Z value as four floats in [0,1].
1283464ebd5Sriastradh */
1294a49301eSmrgstatic void
1303464ebd5Sriastradhz32_get_tile_rgba(const unsigned *src,
1313464ebd5Sriastradh                  unsigned w, unsigned h,
1323464ebd5Sriastradh                  float *p,
1333464ebd5Sriastradh                  unsigned dst_stride)
1344a49301eSmrg{
1353464ebd5Sriastradh   const double scale = 1.0 / (double) 0xffffffff;
1364a49301eSmrg   unsigned i, j;
1374a49301eSmrg
1384a49301eSmrg   for (i = 0; i < h; i++) {
1394a49301eSmrg      float *pRow = p;
1403464ebd5Sriastradh      for (j = 0; j < w; j++, pRow += 4) {
1414a49301eSmrg         pRow[0] =
1424a49301eSmrg         pRow[1] =
1433464ebd5Sriastradh         pRow[2] =
1443464ebd5Sriastradh         pRow[3] = (float) (*src++ * scale);
1454a49301eSmrg      }
1464a49301eSmrg      p += dst_stride;
1474a49301eSmrg   }
1484a49301eSmrg}
1494a49301eSmrg
1504a49301eSmrg
151af69d88dSmrg/*** PIPE_FORMAT_Z24_UNORM_S8_UINT ***/
1524a49301eSmrg
1533464ebd5Sriastradh/**
1543464ebd5Sriastradh * Return Z component as four float in [0,1].  Stencil part ignored.
1553464ebd5Sriastradh */
1564a49301eSmrgstatic void
1573464ebd5Sriastradhs8z24_get_tile_rgba(const unsigned *src,
1583464ebd5Sriastradh                    unsigned w, unsigned h,
1593464ebd5Sriastradh                    float *p,
1603464ebd5Sriastradh                    unsigned dst_stride)
1614a49301eSmrg{
1623464ebd5Sriastradh   const double scale = 1.0 / ((1 << 24) - 1);
1634a49301eSmrg   unsigned i, j;
1644a49301eSmrg
1654a49301eSmrg   for (i = 0; i < h; i++) {
1664a49301eSmrg      float *pRow = p;
1673464ebd5Sriastradh      for (j = 0; j < w; j++, pRow += 4) {
1684a49301eSmrg         pRow[0] =
1694a49301eSmrg         pRow[1] =
1704a49301eSmrg         pRow[2] =
1713464ebd5Sriastradh         pRow[3] = (float) (scale * (*src++ & 0xffffff));
1724a49301eSmrg      }
1734a49301eSmrg      p += dst_stride;
1744a49301eSmrg   }
1754a49301eSmrg}
1764a49301eSmrg
1774a49301eSmrg
178af69d88dSmrg/*** PIPE_FORMAT_S8_UINT_Z24_UNORM ***/
1794a49301eSmrg
1803464ebd5Sriastradh/**
1813464ebd5Sriastradh * Return Z component as four float in [0,1].  Stencil part ignored.
1823464ebd5Sriastradh */
1834a49301eSmrgstatic void
1843464ebd5Sriastradhz24s8_get_tile_rgba(const unsigned *src,
1853464ebd5Sriastradh                    unsigned w, unsigned h,
1863464ebd5Sriastradh                    float *p,
1873464ebd5Sriastradh                    unsigned dst_stride)
1884a49301eSmrg{
1893464ebd5Sriastradh   const double scale = 1.0 / ((1 << 24) - 1);
1904a49301eSmrg   unsigned i, j;
1914a49301eSmrg
1924a49301eSmrg   for (i = 0; i < h; i++) {
1934a49301eSmrg      float *pRow = p;
1944a49301eSmrg      for (j = 0; j < w; j++, pRow += 4) {
1954a49301eSmrg         pRow[0] =
1964a49301eSmrg         pRow[1] =
1973464ebd5Sriastradh         pRow[2] =
1983464ebd5Sriastradh         pRow[3] = (float) (scale * (*src++ >> 8));
1994a49301eSmrg      }
2004a49301eSmrg      p += dst_stride;
2014a49301eSmrg   }
2024a49301eSmrg}
2034a49301eSmrg
204af69d88dSmrg/*** PIPE_FORMAT_S8X24_UINT ***/
2054a49301eSmrg
2064a49301eSmrg/**
2073464ebd5Sriastradh * Return S component as four uint32_t in [0..255].  Z part ignored.
2084a49301eSmrg */
2094a49301eSmrgstatic void
2103464ebd5Sriastradhs8x24_get_tile_rgba(const unsigned *src,
2113464ebd5Sriastradh                    unsigned w, unsigned h,
2123464ebd5Sriastradh                    float *p,
2133464ebd5Sriastradh                    unsigned dst_stride)
2144a49301eSmrg{
2154a49301eSmrg   unsigned i, j;
2164a49301eSmrg
2174a49301eSmrg   for (i = 0; i < h; i++) {
21801e04c3fSmrg      uint32_t *pRow = (uint32_t *)p;
2193464ebd5Sriastradh
2204a49301eSmrg      for (j = 0; j < w; j++, pRow += 4) {
2214a49301eSmrg         pRow[0] =
2224a49301eSmrg         pRow[1] =
2234a49301eSmrg         pRow[2] =
22401e04c3fSmrg         pRow[3] = ((*src++ >> 24) & 0xff);
2254a49301eSmrg      }
2263464ebd5Sriastradh
2274a49301eSmrg      p += dst_stride;
2284a49301eSmrg   }
2294a49301eSmrg}
2304a49301eSmrg
231af69d88dSmrg/*** PIPE_FORMAT_X24S8_UINT ***/
2324a49301eSmrg
2334a49301eSmrg/**
2343464ebd5Sriastradh * Return S component as four uint32_t in [0..255].  Z part ignored.
2354a49301eSmrg */
2364a49301eSmrgstatic void
2373464ebd5Sriastradhx24s8_get_tile_rgba(const unsigned *src,
2384a49301eSmrg                    unsigned w, unsigned h,
2394a49301eSmrg                    float *p,
2404a49301eSmrg                    unsigned dst_stride)
2414a49301eSmrg{
2424a49301eSmrg   unsigned i, j;
2434a49301eSmrg
2444a49301eSmrg   for (i = 0; i < h; i++) {
24501e04c3fSmrg      uint32_t *pRow = (uint32_t *)p;
2464a49301eSmrg      for (j = 0; j < w; j++, pRow += 4) {
2474a49301eSmrg         pRow[0] =
2484a49301eSmrg         pRow[1] =
2494a49301eSmrg         pRow[2] =
25001e04c3fSmrg         pRow[3] = (*src++ & 0xff);
2514a49301eSmrg      }
2524a49301eSmrg      p += dst_stride;
2534a49301eSmrg   }
2544a49301eSmrg}
2554a49301eSmrg
2564a49301eSmrg
2574a49301eSmrg/**
2583464ebd5Sriastradh * Return S component as four uint32_t in [0..255].  Z part ignored.
2594a49301eSmrg */
2604a49301eSmrgstatic void
2613464ebd5Sriastradhs8_get_tile_rgba(const unsigned char *src,
2623464ebd5Sriastradh		 unsigned w, unsigned h,
2633464ebd5Sriastradh		 float *p,
2643464ebd5Sriastradh		 unsigned dst_stride)
2654a49301eSmrg{
2664a49301eSmrg   unsigned i, j;
2674a49301eSmrg
2684a49301eSmrg   for (i = 0; i < h; i++) {
26901e04c3fSmrg      uint32_t *pRow = (uint32_t *)p;
2704a49301eSmrg      for (j = 0; j < w; j++, pRow += 4) {
2714a49301eSmrg         pRow[0] =
2724a49301eSmrg         pRow[1] =
2734a49301eSmrg         pRow[2] =
27401e04c3fSmrg         pRow[3] = (*src++ & 0xff);
2754a49301eSmrg      }
2764a49301eSmrg      p += dst_stride;
2774a49301eSmrg   }
2784a49301eSmrg}
2794a49301eSmrg
2804a49301eSmrg/*** PIPE_FORMAT_Z32_FLOAT ***/
2814a49301eSmrg
2824a49301eSmrg/**
2834a49301eSmrg * Return each Z value as four floats in [0,1].
2844a49301eSmrg */
2854a49301eSmrgstatic void
2864a49301eSmrgz32f_get_tile_rgba(const float *src,
2874a49301eSmrg                   unsigned w, unsigned h,
2884a49301eSmrg                   float *p,
2894a49301eSmrg                   unsigned dst_stride)
2904a49301eSmrg{
2914a49301eSmrg   unsigned i, j;
2924a49301eSmrg
2934a49301eSmrg   for (i = 0; i < h; i++) {
2944a49301eSmrg      float *pRow = p;
2954a49301eSmrg      for (j = 0; j < w; j++, pRow += 4) {
2964a49301eSmrg         pRow[0] =
2974a49301eSmrg         pRow[1] =
2984a49301eSmrg         pRow[2] =
2994a49301eSmrg         pRow[3] = *src++;
3004a49301eSmrg      }
3014a49301eSmrg      p += dst_stride;
3024a49301eSmrg   }
3034a49301eSmrg}
3044a49301eSmrg
305af69d88dSmrg/*** PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ***/
306af69d88dSmrg
307af69d88dSmrg/**
308af69d88dSmrg * Return each Z value as four floats in [0,1].
309af69d88dSmrg */
310af69d88dSmrgstatic void
311af69d88dSmrgz32f_x24s8_get_tile_rgba(const float *src,
312af69d88dSmrg                         unsigned w, unsigned h,
313af69d88dSmrg                         float *p,
314af69d88dSmrg                         unsigned dst_stride)
315af69d88dSmrg{
316af69d88dSmrg   unsigned i, j;
317af69d88dSmrg
318af69d88dSmrg   for (i = 0; i < h; i++) {
319af69d88dSmrg      float *pRow = p;
320af69d88dSmrg      for (j = 0; j < w; j++, pRow += 4) {
321af69d88dSmrg         pRow[0] =
322af69d88dSmrg         pRow[1] =
323af69d88dSmrg         pRow[2] =
324af69d88dSmrg         pRow[3] = *src;
325af69d88dSmrg         src += 2;
326af69d88dSmrg      }
327af69d88dSmrg      p += dst_stride;
328af69d88dSmrg   }
329af69d88dSmrg}
330af69d88dSmrg
331af69d88dSmrg/*** PIPE_FORMAT_X32_S8X24_UINT ***/
332af69d88dSmrg
333af69d88dSmrg/**
334af69d88dSmrg * Return S component as four uint32_t in [0..255].  Z part ignored.
335af69d88dSmrg */
336af69d88dSmrgstatic void
337af69d88dSmrgx32_s8_get_tile_rgba(const unsigned *src,
338af69d88dSmrg                     unsigned w, unsigned h,
339af69d88dSmrg                     float *p,
340af69d88dSmrg                     unsigned dst_stride)
341af69d88dSmrg{
342af69d88dSmrg   unsigned i, j;
343af69d88dSmrg
344af69d88dSmrg   for (i = 0; i < h; i++) {
34501e04c3fSmrg      uint32_t *pRow = (uint32_t *)p;
346af69d88dSmrg      for (j = 0; j < w; j++, pRow += 4) {
347af69d88dSmrg         src++;
348af69d88dSmrg         pRow[0] =
349af69d88dSmrg         pRow[1] =
350af69d88dSmrg         pRow[2] =
35101e04c3fSmrg         pRow[3] = (*src++ & 0xff);
352af69d88dSmrg      }
353af69d88dSmrg      p += dst_stride;
354af69d88dSmrg   }
355af69d88dSmrg}
3564a49301eSmrg
3574a49301eSmrgvoid
3587ec681f3Smrgpipe_put_tile_rgba(struct pipe_transfer *pt,
3597ec681f3Smrg                   void *dst,
3607ec681f3Smrg                   uint x, uint y, uint w, uint h,
3617ec681f3Smrg                   enum pipe_format format, const void *p)
3624a49301eSmrg{
3637ec681f3Smrg   unsigned src_stride = w * 4;
3644a49301eSmrg
3657ec681f3Smrg   if (u_clip_tile(x, y, &w, &h, &pt->box))
3667ec681f3Smrg      return;
367af69d88dSmrg
3687ec681f3Smrg   /* While we do generate RGBA tiles for z/s for softpipe's texture fetch
3697ec681f3Smrg    * path, we never have to store from "RGBA" to Z/S.
3707ec681f3Smrg    */
3717ec681f3Smrg   if (util_format_is_depth_or_stencil(format))
3727ec681f3Smrg      return;
3737ec681f3Smrg
3747ec681f3Smrg   util_format_write_4(format,
3757ec681f3Smrg                       p, src_stride * sizeof(float),
3767ec681f3Smrg                       dst, pt->stride,
3777ec681f3Smrg                       x, y, w, h);
378af69d88dSmrg}
3794a49301eSmrg
3804a49301eSmrgvoid
381af69d88dSmrgpipe_get_tile_rgba(struct pipe_transfer *pt,
382af69d88dSmrg                   const void *src,
3834a49301eSmrg                   uint x, uint y, uint w, uint h,
3847ec681f3Smrg                   enum pipe_format format,
3857ec681f3Smrg                   void *dst)
3864a49301eSmrg{
3874a49301eSmrg   unsigned dst_stride = w * 4;
3884a49301eSmrg   void *packed;
3894a49301eSmrg
3903464ebd5Sriastradh   if (u_clip_tile(x, y, &w, &h, &pt->box)) {
3914a49301eSmrg      return;
3923464ebd5Sriastradh   }
3934a49301eSmrg
394cdc920a0Smrg   packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
3953464ebd5Sriastradh   if (!packed) {
3964a49301eSmrg      return;
3973464ebd5Sriastradh   }
3984a49301eSmrg
3993464ebd5Sriastradh   if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) {
4004a49301eSmrg      assert((x & 1) == 0);
4013464ebd5Sriastradh   }
4024a49301eSmrg
403af69d88dSmrg   pipe_get_tile_raw(pt, src, x, y, w, h, packed, 0);
4044a49301eSmrg
405cdc920a0Smrg   switch (format) {
4064a49301eSmrg   case PIPE_FORMAT_Z16_UNORM:
4077ec681f3Smrg      z16_get_tile_rgba((ushort *) packed, w, h, dst, dst_stride);
4084a49301eSmrg      break;
4094a49301eSmrg   case PIPE_FORMAT_Z32_UNORM:
4107ec681f3Smrg      z32_get_tile_rgba((unsigned *) packed, w, h, dst, dst_stride);
4114a49301eSmrg      break;
412af69d88dSmrg   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
4134a49301eSmrg   case PIPE_FORMAT_Z24X8_UNORM:
4147ec681f3Smrg      s8z24_get_tile_rgba((unsigned *) packed, w, h, dst, dst_stride);
415cdc920a0Smrg      break;
4167ec681f3Smrg   case PIPE_FORMAT_S8_UINT:
4177ec681f3Smrg      s8_get_tile_rgba((unsigned char *) packed, w, h, dst, dst_stride);
4184a49301eSmrg      break;
4197ec681f3Smrg   case PIPE_FORMAT_X24S8_UINT:
4207ec681f3Smrg      s8x24_get_tile_rgba((unsigned *) packed, w, h, dst, dst_stride);
4214a49301eSmrg      break;
422af69d88dSmrg   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
423cdc920a0Smrg   case PIPE_FORMAT_X8Z24_UNORM:
4247ec681f3Smrg      z24s8_get_tile_rgba((unsigned *) packed, w, h, dst, dst_stride);
4254a49301eSmrg      break;
4267ec681f3Smrg   case PIPE_FORMAT_S8X24_UINT:
4277ec681f3Smrg      x24s8_get_tile_rgba((unsigned *) packed, w, h, dst, dst_stride);
4284a49301eSmrg      break;
429af69d88dSmrg   case PIPE_FORMAT_Z32_FLOAT:
4307ec681f3Smrg      z32f_get_tile_rgba((float *) packed, w, h, dst, dst_stride);
431af69d88dSmrg      break;
432af69d88dSmrg   case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
4337ec681f3Smrg      z32f_x24s8_get_tile_rgba((float *) packed, w, h, dst, dst_stride);
434af69d88dSmrg      break;
4357ec681f3Smrg   case PIPE_FORMAT_X32_S8X24_UINT:
4367ec681f3Smrg      x32_s8_get_tile_rgba((unsigned *) packed, w, h, dst, dst_stride);
437af69d88dSmrg      break;
4384a49301eSmrg   default:
4397ec681f3Smrg      util_format_read_4(format,
4407ec681f3Smrg                         dst, dst_stride * sizeof(float),
4417ec681f3Smrg                         packed, util_format_get_stride(format, w),
4427ec681f3Smrg                         0, 0, w, h);
443af69d88dSmrg   }
444af69d88dSmrg
445af69d88dSmrg   FREE(packed);
446af69d88dSmrg}
447