1848b8605Smrg/*
2848b8605Smrg * Copyright (C) 2014 Intel Corporation
3848b8605Smrg *
4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5848b8605Smrg * copy of this software and associated documentation files (the "Software"),
6848b8605Smrg * to deal in the Software without restriction, including without limitation
7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
9848b8605Smrg * Software is furnished to do so, subject to the following conditions:
10848b8605Smrg *
11848b8605Smrg * The above copyright notice and this permission notice (including the next
12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the
13848b8605Smrg * Software.
14848b8605Smrg *
15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21848b8605Smrg * DEALINGS IN THE SOFTWARE.
22848b8605Smrg */
23848b8605Smrg
24848b8605Smrg/**
25848b8605Smrg * \file texcompress_bptc.c
26848b8605Smrg * GL_ARB_texture_compression_bptc support.
27848b8605Smrg */
28848b8605Smrg
29848b8605Smrg#include <stdbool.h>
30848b8605Smrg#include "texcompress.h"
31848b8605Smrg#include "texcompress_bptc.h"
32b8e80941Smrg#include "texcompress_bptc_tmp.h"
33848b8605Smrg#include "texstore.h"
34848b8605Smrg#include "image.h"
35b8e80941Smrg#include "mtypes.h"
36848b8605Smrg
37b8e80941Smrgstatic void
38b8e80941Smrgfetch_bptc_rgb_float(const GLubyte *map,
39b8e80941Smrg                     GLint rowStride, GLint i, GLint j,
40b8e80941Smrg                     GLfloat *texel,
41b8e80941Smrg                     bool is_signed)
42848b8605Smrg{
43b8e80941Smrg   const GLubyte *block;
44848b8605Smrg
45b8e80941Smrg   block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
46848b8605Smrg
47b8e80941Smrg   fetch_rgb_float_from_block(block, texel, (i % 4) + (j % 4) * 4, is_signed);
48848b8605Smrg}
49848b8605Smrg
50848b8605Smrgstatic void
51b8e80941Smrgfetch_bptc_rgb_signed_float(const GLubyte *map,
52b8e80941Smrg                            GLint rowStride, GLint i, GLint j,
53b8e80941Smrg                            GLfloat *texel)
54848b8605Smrg{
55b8e80941Smrg   fetch_bptc_rgb_float(map, rowStride, i, j, texel, true);
56848b8605Smrg}
57848b8605Smrg
58848b8605Smrgstatic void
59b8e80941Smrgfetch_bptc_rgb_unsigned_float(const GLubyte *map,
60b8e80941Smrg                              GLint rowStride, GLint i, GLint j,
61b8e80941Smrg                              GLfloat *texel)
62848b8605Smrg{
63b8e80941Smrg   fetch_bptc_rgb_float(map, rowStride, i, j, texel, false);
64848b8605Smrg}
65848b8605Smrg
66848b8605Smrgstatic void
67848b8605Smrgfetch_bptc_rgba_unorm_bytes(const GLubyte *map,
68848b8605Smrg                            GLint rowStride, GLint i, GLint j,
69848b8605Smrg                            GLubyte *texel)
70848b8605Smrg{
71848b8605Smrg   const GLubyte *block;
72848b8605Smrg
73848b8605Smrg   block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
74848b8605Smrg
75848b8605Smrg   fetch_rgba_unorm_from_block(block, texel, (i % 4) + (j % 4) * 4);
76848b8605Smrg}
77848b8605Smrg
78848b8605Smrgstatic void
79848b8605Smrgfetch_bptc_rgba_unorm(const GLubyte *map,
80848b8605Smrg                      GLint rowStride, GLint i, GLint j,
81848b8605Smrg                      GLfloat *texel)
82848b8605Smrg{
83848b8605Smrg   GLubyte texel_bytes[4];
84848b8605Smrg
85848b8605Smrg   fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
86848b8605Smrg
87848b8605Smrg   texel[RCOMP] = UBYTE_TO_FLOAT(texel_bytes[0]);
88848b8605Smrg   texel[GCOMP] = UBYTE_TO_FLOAT(texel_bytes[1]);
89848b8605Smrg   texel[BCOMP] = UBYTE_TO_FLOAT(texel_bytes[2]);
90848b8605Smrg   texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
91848b8605Smrg}
92848b8605Smrg
93848b8605Smrgstatic void
94848b8605Smrgfetch_bptc_srgb_alpha_unorm(const GLubyte *map,
95848b8605Smrg                            GLint rowStride, GLint i, GLint j,
96848b8605Smrg                            GLfloat *texel)
97848b8605Smrg{
98848b8605Smrg   GLubyte texel_bytes[4];
99848b8605Smrg
100848b8605Smrg   fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
101848b8605Smrg
102848b8605Smrg   texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[0]);
103848b8605Smrg   texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[1]);
104848b8605Smrg   texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[2]);
105848b8605Smrg   texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
106848b8605Smrg}
107848b8605Smrg
108848b8605Smrgcompressed_fetch_func
109848b8605Smrg_mesa_get_bptc_fetch_func(mesa_format format)
110848b8605Smrg{
111848b8605Smrg   switch (format) {
112848b8605Smrg   case MESA_FORMAT_BPTC_RGBA_UNORM:
113848b8605Smrg      return fetch_bptc_rgba_unorm;
114848b8605Smrg   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
115848b8605Smrg      return fetch_bptc_srgb_alpha_unorm;
116848b8605Smrg   case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
117848b8605Smrg      return fetch_bptc_rgb_signed_float;
118848b8605Smrg   case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
119848b8605Smrg      return fetch_bptc_rgb_unsigned_float;
120848b8605Smrg   default:
121848b8605Smrg      return NULL;
122848b8605Smrg   }
123848b8605Smrg}
124848b8605Smrg
125848b8605SmrgGLboolean
126848b8605Smrg_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS)
127848b8605Smrg{
128848b8605Smrg   const GLubyte *pixels;
129848b8605Smrg   const GLubyte *tempImage = NULL;
130848b8605Smrg   int rowstride;
131848b8605Smrg
132848b8605Smrg   if (srcFormat != GL_RGBA ||
133848b8605Smrg       srcType != GL_UNSIGNED_BYTE ||
134848b8605Smrg       ctx->_ImageTransferState ||
135848b8605Smrg       srcPacking->SwapBytes) {
136848b8605Smrg      /* convert image to RGBA/ubyte */
137b8e80941Smrg      GLubyte *tempImageSlices[1];
138b8e80941Smrg      int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
139b8e80941Smrg      tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
140848b8605Smrg      if (!tempImage)
141848b8605Smrg         return GL_FALSE; /* out of memory */
142b8e80941Smrg      tempImageSlices[0] = (GLubyte *) tempImage;
143b8e80941Smrg      _mesa_texstore(ctx, dims,
144b8e80941Smrg                     baseInternalFormat,
145b8e80941Smrg                     _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM
146b8e80941Smrg                                           : MESA_FORMAT_A8B8G8R8_UNORM,
147b8e80941Smrg                     rgbaRowStride, tempImageSlices,
148b8e80941Smrg                     srcWidth, srcHeight, srcDepth,
149b8e80941Smrg                     srcFormat, srcType, srcAddr,
150b8e80941Smrg                     srcPacking);
151848b8605Smrg
152848b8605Smrg      pixels = tempImage;
153848b8605Smrg      rowstride = srcWidth * 4;
154848b8605Smrg   } else {
155848b8605Smrg      pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
156848b8605Smrg                                     srcFormat, srcType, 0, 0);
157848b8605Smrg      rowstride = _mesa_image_row_stride(srcPacking, srcWidth,
158848b8605Smrg                                         srcFormat, srcType);
159848b8605Smrg   }
160848b8605Smrg
161848b8605Smrg   compress_rgba_unorm(srcWidth, srcHeight,
162848b8605Smrg                       pixels, rowstride,
163848b8605Smrg                       dstSlices[0], dstRowStride);
164848b8605Smrg
165848b8605Smrg   free((void *) tempImage);
166848b8605Smrg
167848b8605Smrg   return GL_TRUE;
168848b8605Smrg}
169848b8605Smrg
170848b8605Smrgstatic GLboolean
171848b8605Smrgtexstore_bptc_rgb_float(TEXSTORE_PARAMS,
172848b8605Smrg                        bool is_signed)
173848b8605Smrg{
174848b8605Smrg   const float *pixels;
175848b8605Smrg   const float *tempImage = NULL;
176848b8605Smrg   int rowstride;
177848b8605Smrg
178848b8605Smrg   if (srcFormat != GL_RGB ||
179848b8605Smrg       srcType != GL_FLOAT ||
180848b8605Smrg       ctx->_ImageTransferState ||
181848b8605Smrg       srcPacking->SwapBytes) {
182848b8605Smrg      /* convert image to RGB/float */
183b8e80941Smrg      GLfloat *tempImageSlices[1];
184b8e80941Smrg      int rgbRowStride = 3 * srcWidth * sizeof(GLfloat);
185b8e80941Smrg      tempImage = malloc(srcWidth * srcHeight * 3 * sizeof(GLfloat));
186848b8605Smrg      if (!tempImage)
187848b8605Smrg         return GL_FALSE; /* out of memory */
188b8e80941Smrg      tempImageSlices[0] = (GLfloat *) tempImage;
189b8e80941Smrg      _mesa_texstore(ctx, dims,
190b8e80941Smrg                     baseInternalFormat,
191b8e80941Smrg                     MESA_FORMAT_RGB_FLOAT32,
192b8e80941Smrg                     rgbRowStride, (GLubyte **)tempImageSlices,
193b8e80941Smrg                     srcWidth, srcHeight, srcDepth,
194b8e80941Smrg                     srcFormat, srcType, srcAddr,
195b8e80941Smrg                     srcPacking);
196848b8605Smrg
197848b8605Smrg      pixels = tempImage;
198848b8605Smrg      rowstride = srcWidth * sizeof(float) * 3;
199848b8605Smrg   } else {
200848b8605Smrg      pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
201848b8605Smrg                                     srcFormat, srcType, 0, 0);
202848b8605Smrg      rowstride = _mesa_image_row_stride(srcPacking, srcWidth,
203848b8605Smrg                                         srcFormat, srcType);
204848b8605Smrg   }
205848b8605Smrg
206848b8605Smrg   compress_rgb_float(srcWidth, srcHeight,
207848b8605Smrg                      pixels, rowstride,
208848b8605Smrg                      dstSlices[0], dstRowStride,
209848b8605Smrg                      is_signed);
210848b8605Smrg
211848b8605Smrg   free((void *) tempImage);
212848b8605Smrg
213848b8605Smrg   return GL_TRUE;
214848b8605Smrg}
215848b8605Smrg
216848b8605SmrgGLboolean
217848b8605Smrg_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS)
218848b8605Smrg{
219b8e80941Smrg   assert(dstFormat == MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT);
220848b8605Smrg
221848b8605Smrg   return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat,
222848b8605Smrg                                  dstFormat, dstRowStride, dstSlices,
223848b8605Smrg                                  srcWidth, srcHeight, srcDepth,
224848b8605Smrg                                  srcFormat, srcType,
225848b8605Smrg                                  srcAddr, srcPacking,
226848b8605Smrg                                  true /* signed */);
227848b8605Smrg}
228848b8605Smrg
229848b8605SmrgGLboolean
230848b8605Smrg_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS)
231848b8605Smrg{
232b8e80941Smrg   assert(dstFormat == MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT);
233848b8605Smrg
234848b8605Smrg   return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat,
235848b8605Smrg                                  dstFormat, dstRowStride, dstSlices,
236848b8605Smrg                                  srcWidth, srcHeight, srcDepth,
237848b8605Smrg                                  srcFormat, srcType,
238848b8605Smrg                                  srcAddr, srcPacking,
239848b8605Smrg                                  false /* unsigned */);
240848b8605Smrg}
241