1af69d88dSmrg/*
2af69d88dSmrg * Copyright (C) 2014 Intel Corporation
3af69d88dSmrg *
4af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5af69d88dSmrg * copy of this software and associated documentation files (the "Software"),
6af69d88dSmrg * to deal in the Software without restriction, including without limitation
7af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9af69d88dSmrg * Software is furnished to do so, subject to the following conditions:
10af69d88dSmrg *
11af69d88dSmrg * The above copyright notice and this permission notice (including the next
12af69d88dSmrg * paragraph) shall be included in all copies or substantial portions of the
13af69d88dSmrg * Software.
14af69d88dSmrg *
15af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19af69d88dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20af69d88dSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21af69d88dSmrg * DEALINGS IN THE SOFTWARE.
22af69d88dSmrg */
23af69d88dSmrg
24af69d88dSmrg/**
25af69d88dSmrg * \file texcompress_bptc.c
26af69d88dSmrg * GL_ARB_texture_compression_bptc support.
27af69d88dSmrg */
28af69d88dSmrg
29af69d88dSmrg#include <stdbool.h>
30af69d88dSmrg#include "texcompress.h"
31af69d88dSmrg#include "texcompress_bptc.h"
3201e04c3fSmrg#include "texcompress_bptc_tmp.h"
33af69d88dSmrg#include "texstore.h"
34af69d88dSmrg#include "image.h"
3501e04c3fSmrg#include "mtypes.h"
36af69d88dSmrg
3701e04c3fSmrgstatic void
3801e04c3fSmrgfetch_bptc_rgb_float(const GLubyte *map,
3901e04c3fSmrg                     GLint rowStride, GLint i, GLint j,
4001e04c3fSmrg                     GLfloat *texel,
4101e04c3fSmrg                     bool is_signed)
42af69d88dSmrg{
4301e04c3fSmrg   const GLubyte *block;
44af69d88dSmrg
4501e04c3fSmrg   block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
46af69d88dSmrg
4701e04c3fSmrg   fetch_rgb_float_from_block(block, texel, (i % 4) + (j % 4) * 4, is_signed);
48af69d88dSmrg}
49af69d88dSmrg
50af69d88dSmrgstatic void
5101e04c3fSmrgfetch_bptc_rgb_signed_float(const GLubyte *map,
5201e04c3fSmrg                            GLint rowStride, GLint i, GLint j,
5301e04c3fSmrg                            GLfloat *texel)
54af69d88dSmrg{
5501e04c3fSmrg   fetch_bptc_rgb_float(map, rowStride, i, j, texel, true);
56af69d88dSmrg}
57af69d88dSmrg
58af69d88dSmrgstatic void
5901e04c3fSmrgfetch_bptc_rgb_unsigned_float(const GLubyte *map,
6001e04c3fSmrg                              GLint rowStride, GLint i, GLint j,
6101e04c3fSmrg                              GLfloat *texel)
62af69d88dSmrg{
6301e04c3fSmrg   fetch_bptc_rgb_float(map, rowStride, i, j, texel, false);
64af69d88dSmrg}
65af69d88dSmrg
66af69d88dSmrgstatic void
67af69d88dSmrgfetch_bptc_rgba_unorm_bytes(const GLubyte *map,
68af69d88dSmrg                            GLint rowStride, GLint i, GLint j,
69af69d88dSmrg                            GLubyte *texel)
70af69d88dSmrg{
71af69d88dSmrg   const GLubyte *block;
72af69d88dSmrg
73af69d88dSmrg   block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
74af69d88dSmrg
75af69d88dSmrg   fetch_rgba_unorm_from_block(block, texel, (i % 4) + (j % 4) * 4);
76af69d88dSmrg}
77af69d88dSmrg
78af69d88dSmrgstatic void
79af69d88dSmrgfetch_bptc_rgba_unorm(const GLubyte *map,
80af69d88dSmrg                      GLint rowStride, GLint i, GLint j,
81af69d88dSmrg                      GLfloat *texel)
82af69d88dSmrg{
83af69d88dSmrg   GLubyte texel_bytes[4];
84af69d88dSmrg
85af69d88dSmrg   fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
86af69d88dSmrg
87af69d88dSmrg   texel[RCOMP] = UBYTE_TO_FLOAT(texel_bytes[0]);
88af69d88dSmrg   texel[GCOMP] = UBYTE_TO_FLOAT(texel_bytes[1]);
89af69d88dSmrg   texel[BCOMP] = UBYTE_TO_FLOAT(texel_bytes[2]);
90af69d88dSmrg   texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
91af69d88dSmrg}
92af69d88dSmrg
93af69d88dSmrgstatic void
94af69d88dSmrgfetch_bptc_srgb_alpha_unorm(const GLubyte *map,
95af69d88dSmrg                            GLint rowStride, GLint i, GLint j,
96af69d88dSmrg                            GLfloat *texel)
97af69d88dSmrg{
98af69d88dSmrg   GLubyte texel_bytes[4];
99af69d88dSmrg
100af69d88dSmrg   fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
101af69d88dSmrg
102af69d88dSmrg   texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[0]);
103af69d88dSmrg   texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[1]);
104af69d88dSmrg   texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[2]);
105af69d88dSmrg   texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
106af69d88dSmrg}
107af69d88dSmrg
108af69d88dSmrgcompressed_fetch_func
109af69d88dSmrg_mesa_get_bptc_fetch_func(mesa_format format)
110af69d88dSmrg{
111af69d88dSmrg   switch (format) {
112af69d88dSmrg   case MESA_FORMAT_BPTC_RGBA_UNORM:
113af69d88dSmrg      return fetch_bptc_rgba_unorm;
114af69d88dSmrg   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
115af69d88dSmrg      return fetch_bptc_srgb_alpha_unorm;
116af69d88dSmrg   case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
117af69d88dSmrg      return fetch_bptc_rgb_signed_float;
118af69d88dSmrg   case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
119af69d88dSmrg      return fetch_bptc_rgb_unsigned_float;
120af69d88dSmrg   default:
121af69d88dSmrg      return NULL;
122af69d88dSmrg   }
123af69d88dSmrg}
124af69d88dSmrg
125af69d88dSmrgGLboolean
126af69d88dSmrg_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS)
127af69d88dSmrg{
128af69d88dSmrg   const GLubyte *pixels;
129af69d88dSmrg   const GLubyte *tempImage = NULL;
130af69d88dSmrg   int rowstride;
131af69d88dSmrg
132af69d88dSmrg   if (srcFormat != GL_RGBA ||
133af69d88dSmrg       srcType != GL_UNSIGNED_BYTE ||
134af69d88dSmrg       ctx->_ImageTransferState ||
135af69d88dSmrg       srcPacking->SwapBytes) {
136af69d88dSmrg      /* convert image to RGBA/ubyte */
13701e04c3fSmrg      GLubyte *tempImageSlices[1];
13801e04c3fSmrg      int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
13901e04c3fSmrg      tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
140af69d88dSmrg      if (!tempImage)
141af69d88dSmrg         return GL_FALSE; /* out of memory */
14201e04c3fSmrg      tempImageSlices[0] = (GLubyte *) tempImage;
14301e04c3fSmrg      _mesa_texstore(ctx, dims,
14401e04c3fSmrg                     baseInternalFormat,
1457ec681f3Smrg#if UTIL_ARCH_LITTLE_ENDIAN
1467ec681f3Smrg                     MESA_FORMAT_R8G8B8A8_UNORM,
1477ec681f3Smrg#else
1487ec681f3Smrg                     MESA_FORMAT_A8B8G8R8_UNORM,
1497ec681f3Smrg#endif
15001e04c3fSmrg                     rgbaRowStride, tempImageSlices,
15101e04c3fSmrg                     srcWidth, srcHeight, srcDepth,
15201e04c3fSmrg                     srcFormat, srcType, srcAddr,
15301e04c3fSmrg                     srcPacking);
154af69d88dSmrg
155af69d88dSmrg      pixels = tempImage;
156af69d88dSmrg      rowstride = srcWidth * 4;
157af69d88dSmrg   } else {
158af69d88dSmrg      pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
159af69d88dSmrg                                     srcFormat, srcType, 0, 0);
160af69d88dSmrg      rowstride = _mesa_image_row_stride(srcPacking, srcWidth,
161af69d88dSmrg                                         srcFormat, srcType);
162af69d88dSmrg   }
163af69d88dSmrg
164af69d88dSmrg   compress_rgba_unorm(srcWidth, srcHeight,
165af69d88dSmrg                       pixels, rowstride,
166af69d88dSmrg                       dstSlices[0], dstRowStride);
167af69d88dSmrg
168af69d88dSmrg   free((void *) tempImage);
169af69d88dSmrg
170af69d88dSmrg   return GL_TRUE;
171af69d88dSmrg}
172af69d88dSmrg
173af69d88dSmrgstatic GLboolean
174af69d88dSmrgtexstore_bptc_rgb_float(TEXSTORE_PARAMS,
175af69d88dSmrg                        bool is_signed)
176af69d88dSmrg{
177af69d88dSmrg   const float *pixels;
178af69d88dSmrg   const float *tempImage = NULL;
179af69d88dSmrg   int rowstride;
180af69d88dSmrg
181af69d88dSmrg   if (srcFormat != GL_RGB ||
182af69d88dSmrg       srcType != GL_FLOAT ||
183af69d88dSmrg       ctx->_ImageTransferState ||
184af69d88dSmrg       srcPacking->SwapBytes) {
185af69d88dSmrg      /* convert image to RGB/float */
18601e04c3fSmrg      GLfloat *tempImageSlices[1];
18701e04c3fSmrg      int rgbRowStride = 3 * srcWidth * sizeof(GLfloat);
18801e04c3fSmrg      tempImage = malloc(srcWidth * srcHeight * 3 * sizeof(GLfloat));
189af69d88dSmrg      if (!tempImage)
190af69d88dSmrg         return GL_FALSE; /* out of memory */
19101e04c3fSmrg      tempImageSlices[0] = (GLfloat *) tempImage;
19201e04c3fSmrg      _mesa_texstore(ctx, dims,
19301e04c3fSmrg                     baseInternalFormat,
19401e04c3fSmrg                     MESA_FORMAT_RGB_FLOAT32,
19501e04c3fSmrg                     rgbRowStride, (GLubyte **)tempImageSlices,
19601e04c3fSmrg                     srcWidth, srcHeight, srcDepth,
19701e04c3fSmrg                     srcFormat, srcType, srcAddr,
19801e04c3fSmrg                     srcPacking);
199af69d88dSmrg
200af69d88dSmrg      pixels = tempImage;
201af69d88dSmrg      rowstride = srcWidth * sizeof(float) * 3;
202af69d88dSmrg   } else {
203af69d88dSmrg      pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
204af69d88dSmrg                                     srcFormat, srcType, 0, 0);
205af69d88dSmrg      rowstride = _mesa_image_row_stride(srcPacking, srcWidth,
206af69d88dSmrg                                         srcFormat, srcType);
207af69d88dSmrg   }
208af69d88dSmrg
209af69d88dSmrg   compress_rgb_float(srcWidth, srcHeight,
210af69d88dSmrg                      pixels, rowstride,
211af69d88dSmrg                      dstSlices[0], dstRowStride,
212af69d88dSmrg                      is_signed);
213af69d88dSmrg
214af69d88dSmrg   free((void *) tempImage);
215af69d88dSmrg
216af69d88dSmrg   return GL_TRUE;
217af69d88dSmrg}
218af69d88dSmrg
219af69d88dSmrgGLboolean
220af69d88dSmrg_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS)
221af69d88dSmrg{
22201e04c3fSmrg   assert(dstFormat == MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT);
223af69d88dSmrg
224af69d88dSmrg   return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat,
225af69d88dSmrg                                  dstFormat, dstRowStride, dstSlices,
226af69d88dSmrg                                  srcWidth, srcHeight, srcDepth,
227af69d88dSmrg                                  srcFormat, srcType,
228af69d88dSmrg                                  srcAddr, srcPacking,
229af69d88dSmrg                                  true /* signed */);
230af69d88dSmrg}
231af69d88dSmrg
232af69d88dSmrgGLboolean
233af69d88dSmrg_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS)
234af69d88dSmrg{
23501e04c3fSmrg   assert(dstFormat == MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT);
236af69d88dSmrg
237af69d88dSmrg   return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat,
238af69d88dSmrg                                  dstFormat, dstRowStride, dstSlices,
239af69d88dSmrg                                  srcWidth, srcHeight, srcDepth,
240af69d88dSmrg                                  srcFormat, srcType,
241af69d88dSmrg                                  srcAddr, srcPacking,
242af69d88dSmrg                                  false /* unsigned */);
243af69d88dSmrg}
244