diff --git a/build/wiiu.vcxproj b/build/wiiu.vcxproj
index 5bdf36c2..dcc03887 100644
--- a/build/wiiu.vcxproj
+++ b/build/wiiu.vcxproj
@@ -111,6 +111,7 @@
+
@@ -244,6 +245,7 @@
+
diff --git a/build/wiiu.vcxproj.filters b/build/wiiu.vcxproj.filters
index 11a2334f..975886ba 100644
--- a/build/wiiu.vcxproj.filters
+++ b/build/wiiu.vcxproj.filters
@@ -531,6 +531,9 @@
Source Files\gpu
+
+ Source Files\gpu
+
@@ -962,6 +965,9 @@
Header Files\gpu
+
+ Header Files\gpu
+
diff --git a/src/gpu/latte_tiling.cpp b/src/gpu/latte_tiling.cpp
index 5efc627a..292a8b86 100644
--- a/src/gpu/latte_tiling.cpp
+++ b/src/gpu/latte_tiling.cpp
@@ -1,407 +1,43 @@
#include "latte_tiling.h"
+#include "mesa_r600_tiling.h"
-typedef int GLint;
-typedef unsigned char GLubyte;
-
-struct radeon_renderbuffer {
- struct {
- int Width;
- int Height;
- } base;
- struct data {
- uint8_t *ptr;
- uint32_t flags;
- } *bo;
- bool has_surface;
- int pitch;
- int cpp; // byte per pixel
- int group_bytes;
- int num_channels; // same as pipes in r800 and above
- int num_banks;
- int r7xx_bank_op;
-};
-
-// Following code is derived from the legacy Mesa r600 driver (radeon_span.c).
-
-/**************************************************************************
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
-VA Linux Systems Inc., Fremont, California.
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-All Rights Reserved.
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**************************************************************************/
-
-/*
-* Authors:
-* Kevin E. Martin
-* Gareth Hughes
-* Keith Whitwell
-*
-*/
-
-#define RADEON_BO_FLAGS_MACRO_TILE 1
-#define RADEON_BO_FLAGS_MICRO_TILE 2
-
-static inline GLint r600_coord_within_microtile(GLint x, GLint y, GLint element_bytes)
+void
+untileSurface(GX2Surface *surface, std::vector &data, uint32_t &rowPitch)
{
- GLint pixel_number = 0;
- switch (element_bytes) {
- case 1:
- pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
- pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
- pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
- pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
- pixel_number |= ((y >> 0) & 1) << 4; // pn[4] = y[0]
- pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
- break;
- case 2:
- pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
- pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
- pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
- pixel_number |= ((y >> 0) & 1) << 3; // pn[3] = y[0]
- pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
- pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
- break;
- case 4:
- pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
- pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
- pixel_number |= ((y >> 0) & 1) << 2; // pn[2] = y[0]
- pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
- pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
- pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
- break;
- case 8:
- pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
- pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
- pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
- pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
- pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
- pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
- break;
- case 16:
- pixel_number |= ((y >> 0) & 1) << 0; // pn[0] = y[0]
- pixel_number |= ((x >> 0) & 1) << 1; // pn[1] = x[0]
- pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
- pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
- pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
- pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
- break;
- }
- return pixel_number;
-}
-
-static inline GLint r600_1d_tile_helper(const struct radeon_renderbuffer * rrb,
- GLint x, GLint y, GLint is_depth, GLint is_stencil)
-{
- GLint element_bytes = rrb->cpp;
- GLint num_samples = 1;
- GLint tile_width = 8;
- GLint tile_height = 8;
- GLint tile_thickness = 1;
- GLint pitch_elements = rrb->pitch / element_bytes;
- GLint height = rrb->base.Height;
- GLint z = 0;
- GLint sample_number = 0;
- /* */
- GLint tile_bytes;
- GLint tiles_per_row;
- GLint tiles_per_slice;
- GLint slice_offset;
- GLint tile_row_index;
- GLint tile_column_index;
- GLint tile_offset;
- GLint pixel_number = 0;
- GLint element_offset;
- GLint offset = 0;
-
- tile_bytes = tile_width * tile_height * tile_thickness * element_bytes * num_samples;
- tiles_per_row = pitch_elements / tile_width;
- tiles_per_slice = tiles_per_row * (height / tile_height);
- slice_offset = (z / tile_thickness) * tiles_per_slice * tile_bytes;
- tile_row_index = y / tile_height;
- tile_column_index = x / tile_width;
- tile_offset = ((tile_row_index * tiles_per_row) + tile_column_index) * tile_bytes;
-
- if (is_depth) {
- GLint pixel_offset = 0;
-
- pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
- pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
- pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
- pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
- pixel_number |= ((x >> 2) & 1) << 4; // pn[4] = x[2]
- pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
- switch (element_bytes) {
- case 2:
- pixel_offset = pixel_number * element_bytes * num_samples;
- break;
- case 4:
- /* stencil and depth data are stored separately within a tile.
- * stencil is stored in a contiguous tile before the depth tile.
- * stencil element is 1 byte, depth element is 3 bytes.
- * stencil tile is 64 bytes.
- */
- if (is_stencil)
- pixel_offset = pixel_number * 1 * num_samples;
- else
- pixel_offset = (pixel_number * 3 * num_samples) + 64;
- break;
- }
- element_offset = pixel_offset + (sample_number * element_bytes);
- } else {
- GLint sample_offset;
-
- pixel_number = r600_coord_within_microtile(x, y, element_bytes);
- sample_offset = sample_number * (tile_bytes / num_samples);
- element_offset = sample_offset + (pixel_number * element_bytes);
- }
- offset = slice_offset + tile_offset + element_offset;
- return offset;
-}
-
-static inline GLint r600_log2(GLint n)
-{
- GLint log2 = 0;
-
- while (n >>= 1)
- ++log2;
- return log2;
-}
-
-static inline GLint r600_2d_tile_helper(const struct radeon_renderbuffer * rrb,
- GLint x, GLint y, GLint is_depth, GLint is_stencil)
-{
- GLint group_bytes = rrb->group_bytes;
- GLint num_channels = rrb->num_channels;
- GLint num_banks = rrb->num_banks;
- GLint r7xx_bank_op = rrb->r7xx_bank_op;
- /* */
- GLint group_bits = r600_log2(group_bytes);
- GLint channel_bits = r600_log2(num_channels);
- GLint bank_bits = r600_log2(num_banks);
- GLint element_bytes = rrb->cpp;
- GLint num_samples = 1;
- GLint tile_width = 8;
- GLint tile_height = 8;
- GLint tile_thickness = 1;
- GLint macro_tile_width = num_banks;
- GLint macro_tile_height = num_channels;
- GLint pitch_elements = (rrb->pitch / element_bytes) / tile_width;
- GLint height = rrb->base.Height / tile_height;
- GLint z = 0;
- GLint sample_number = 0;
- /* */
- GLint tile_bytes;
- GLint macro_tile_bytes;
- GLint macro_tiles_per_row;
- GLint macro_tiles_per_slice;
- GLint slice_offset;
- GLint macro_tile_row_index;
- GLint macro_tile_column_index;
- GLint macro_tile_offset;
- GLint pixel_number = 0;
- GLint element_offset;
- GLint bank = 0;
- GLint channel = 0;
- GLint total_offset;
- GLint group_mask = (1 << group_bits) - 1;
- GLint offset_low;
- GLint offset_high;
- GLint offset = 0;
-
- switch (num_channels) {
- case 2:
- default:
- // channel[0] = x[3] ^ y[3]
- channel |= (((x >> 3) ^ (y >> 3)) & 1) << 0;
- break;
- case 4:
- // channel[0] = x[4] ^ y[3]
- channel |= (((x >> 4) ^ (y >> 3)) & 1) << 0;
- // channel[1] = x[3] ^ y[4]
- channel |= (((x >> 3) ^ (y >> 4)) & 1) << 1;
- break;
- case 8:
- // channel[0] = x[5] ^ y[3]
- channel |= (((x >> 5) ^ (y >> 3)) & 1) << 0;
- // channel[0] = x[4] ^ x[5] ^ y[4]
- channel |= (((x >> 4) ^ (x >> 5) ^ (y >> 4)) & 1) << 1;
- // channel[0] = x[3] ^ y[5]
- channel |= (((x >> 3) ^ (y >> 5)) & 1) << 2;
- break;
- }
-
- switch (num_banks) {
- case 4:
- // bank[0] = x[3] ^ y[4 + log2(num_channels)]
- bank |= (((x >> 3) ^ (y >> (4 + channel_bits))) & 1) << 0;
- if (r7xx_bank_op)
- // bank[1] = x[3] ^ y[4 + log2(num_channels)] ^ x[5]
- bank |= (((x >> 4) ^ (y >> (3 + channel_bits)) ^ (x >> 5)) & 1) << 1;
- else
- // bank[1] = x[4] ^ y[3 + log2(num_channels)]
- bank |= (((x >> 4) ^ (y >> (3 + channel_bits))) & 1) << 1;
- break;
- case 8:
- // bank[0] = x[3] ^ y[5 + log2(num_channels)]
- bank |= (((x >> 3) ^ (y >> (5 + channel_bits))) & 1) << 0;
- // bank[1] = x[4] ^ y[4 + log2(num_channels)] ^ y[5 + log2(num_channels)]
- bank |= (((x >> 4) ^ (y >> (4 + channel_bits)) ^ (y >> (5 + channel_bits))) & 1) << 1;
- if (r7xx_bank_op)
- // bank[2] = x[5] ^ y[3 + log2(num_channels)] ^ x[6]
- bank |= (((x >> 5) ^ (y >> (3 + channel_bits)) ^ (x >> 6)) & 1) << 2;
- else
- // bank[2] = x[5] ^ y[3 + log2(num_channels)]
- bank |= (((x >> 5) ^ (y >> (3 + channel_bits))) & 1) << 2;
- break;
- }
-
- tile_bytes = tile_width * tile_height * tile_thickness * element_bytes * num_samples;
- macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
- macro_tiles_per_row = pitch_elements / macro_tile_width;
- macro_tiles_per_slice = macro_tiles_per_row * (height / macro_tile_height);
- slice_offset = (z / tile_thickness) * macro_tiles_per_slice * macro_tile_bytes;
- macro_tile_row_index = (y / tile_height) / macro_tile_height;
- macro_tile_column_index = (x / tile_width) / macro_tile_width;
- macro_tile_offset = ((macro_tile_row_index * macro_tiles_per_row) + macro_tile_column_index) * macro_tile_bytes;
-
- if (is_depth) {
- GLint pixel_offset = 0;
-
- pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
- pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
- pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
- pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
- pixel_number |= ((x >> 2) & 1) << 4; // pn[4] = x[2]
- pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
- switch (element_bytes) {
- case 2:
- pixel_offset = pixel_number * element_bytes * num_samples;
- break;
- case 4:
- /* stencil and depth data are stored separately within a tile.
- * stencil is stored in a contiguous tile before the depth tile.
- * stencil element is 1 byte, depth element is 3 bytes.
- * stencil tile is 64 bytes.
- */
- if (is_stencil)
- pixel_offset = pixel_number * 1 * num_samples;
- else
- pixel_offset = (pixel_number * 3 * num_samples) + 64;
- break;
- }
- element_offset = pixel_offset + (sample_number * element_bytes);
- } else {
- GLint sample_offset;
-
- pixel_number = r600_coord_within_microtile(x, y, element_bytes);
-
- sample_offset = sample_number * (tile_bytes / num_samples);
- element_offset = sample_offset + (pixel_number * element_bytes);
- }
- total_offset = (slice_offset + macro_tile_offset) >> (channel_bits + bank_bits);
- total_offset += element_offset;
-
- offset_low = total_offset & group_mask;
- offset_high = (total_offset & ~group_mask) << (channel_bits + bank_bits);
- offset = (bank << (group_bits + channel_bits)) + (channel << group_bits) + offset_low + offset_high;
-
- return offset;
-}
-/* depth buffers */
-static GLubyte *r600_ptr_depth(const struct radeon_renderbuffer * rrb,
- GLint x, GLint y)
-{
- GLubyte *ptr = rrb->bo->ptr;
- GLint offset;
- if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
- offset = r600_2d_tile_helper(rrb, x, y, 1, 0);
- else
- offset = r600_1d_tile_helper(rrb, x, y, 1, 0);
- return &ptr[offset];
-}
-static GLubyte *r600_ptr_stencil(const struct radeon_renderbuffer * rrb,
- GLint x, GLint y)
-{
- GLubyte *ptr = rrb->bo->ptr;
- GLint offset;
- if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
- offset = r600_2d_tile_helper(rrb, x, y, 1, 1);
- else
- offset = r600_1d_tile_helper(rrb, x, y, 1, 1);
- return &ptr[offset];
-}
-static GLubyte *r600_ptr_color(const struct radeon_renderbuffer * rrb,
- GLint x, GLint y)
-{
- GLubyte *ptr = rrb->bo->ptr;
- uint32_t mask = RADEON_BO_FLAGS_MACRO_TILE | RADEON_BO_FLAGS_MICRO_TILE;
- GLint offset;
- if (rrb->has_surface || !(rrb->bo->flags & mask)) {
- offset = x * rrb->cpp + y * rrb->pitch;
- } else {
- if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
- offset = r600_2d_tile_helper(rrb, x, y, 0, 0);
- else
- offset = r600_1d_tile_helper(rrb, x, y, 0, 0);
- }
- return &ptr[offset];
-}
-
-// end Mesa code
-
-#pragma pack(1)
-
-void untileSurface(GX2Surface *surface, std::vector& data, uint32_t& rowPitch) {
// TODO: This way of untiling (using expandX,expandY) will
// only work with BC compressed textures...
- uint32_t cpp = 1;
+ auto cpp = 1;
+
switch (surface->format) {
case GX2SurfaceFormat::UNORM_BC1:
- cpp = 8; break;
+ cpp = 8;
+ break;
case GX2SurfaceFormat::UNORM_BC3:
- cpp = 16; break;
+ cpp = 16;
+ break;
default:
__debugbreak();
}
- int expandX = 4;
- int expandY = 4;
+ auto expandX = 4;
+ auto expandY = 4;
- int surfaceWidth = (int)surface->width;
- int surfaceHeight = (int)surface->height;
- int surfacePitch = (int)surface->pitch;
- uint8_t *surfaceData = (uint8_t*)(void*)surface->image;
- uint32_t surfaceDataSize = (uint32_t)surface->imageSize;
+ auto surfaceWidth = (int)surface->width;
+ auto surfaceHeight = (int)surface->height;
+ auto surfacePitch = (int)surface->pitch;
+ auto surfaceData = reinterpret_cast(surface->image.get());
+ auto surfaceDataSize = surface->imageSize;
data.resize(surfaceDataSize);
- radeon_renderbuffer texture;
- radeon_renderbuffer::data rbdata;
+ mesa::radeon_renderbuffer texture;
+ mesa::radeon_renderbuffer::data rbdata;
texture.has_surface = false;
texture.cpp = cpp;
texture.base.Width = surfaceWidth / expandX;
texture.base.Height = surfaceHeight / expandY;
texture.pitch = surfacePitch * texture.cpp;
texture.group_bytes = 256;
+
switch (surface->tileMode) {
case GX2TileMode::Tiled2DThin1:
texture.num_channels = 2;
@@ -416,13 +52,14 @@ void untileSurface(GX2Surface *surface, std::vector& data, uint32_t& ro
texture.bo->flags = RADEON_BO_FLAGS_MACRO_TILE;
texture.bo->ptr = surfaceData;
- uint8_t* outBuf = &data[0];
+ auto outBuf = &data[0];
+
for (int y = 0; y < texture.base.Height; y++) {
for (int x = 0; x < texture.base.Width; x++) {
- GLubyte *blockData = r600_ptr_color(&texture, x, y);
+ auto blockData = r600_ptr_color(&texture, x, y);
memcpy(outBuf + (y*texture.pitch + x*texture.cpp), blockData, texture.cpp);
}
}
rowPitch = texture.pitch;
-}
\ No newline at end of file
+}
diff --git a/src/gpu/latte_tiling.h b/src/gpu/latte_tiling.h
index 2daf9153..baeef1e4 100644
--- a/src/gpu/latte_tiling.h
+++ b/src/gpu/latte_tiling.h
@@ -3,4 +3,4 @@
#include "systemtypes.h"
#include "modules/gx2/gx2_surface.h"
-void untileSurface(GX2Surface *surface, std::vector& data, uint32_t& rowPitch);
\ No newline at end of file
+void untileSurface(GX2Surface *surface, std::vector &data, uint32_t &rowPitch);
diff --git a/src/gpu/mesa_r600_tiling.cpp b/src/gpu/mesa_r600_tiling.cpp
new file mode 100755
index 00000000..1e8ae082
--- /dev/null
+++ b/src/gpu/mesa_r600_tiling.cpp
@@ -0,0 +1,367 @@
+#include "mesa_r600_tiling.h"
+
+typedef int GLint;
+typedef unsigned char GLubyte;
+
+// Following code is derived from the legacy Mesa r600 driver (radeon_span.c).
+namespace mesa
+{
+
+/**************************************************************************
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+VA Linux Systems Inc., Fremont, California.
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+All Rights Reserved.
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************/
+
+/*
+* Authors:
+* Kevin E. Martin
+* Gareth Hughes
+* Keith Whitwell
+*
+*/
+
+static inline GLint
+r600_coord_within_microtile(GLint x, GLint y, GLint element_bytes)
+{
+ GLint pixel_number = 0;
+ switch (element_bytes) {
+ case 1:
+ pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
+ pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
+ pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
+ pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
+ pixel_number |= ((y >> 0) & 1) << 4; // pn[4] = y[0]
+ pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+ break;
+ case 2:
+ pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
+ pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
+ pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
+ pixel_number |= ((y >> 0) & 1) << 3; // pn[3] = y[0]
+ pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
+ pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+ break;
+ case 4:
+ pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
+ pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
+ pixel_number |= ((y >> 0) & 1) << 2; // pn[2] = y[0]
+ pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
+ pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
+ pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+ break;
+ case 8:
+ pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
+ pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
+ pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
+ pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
+ pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
+ pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+ break;
+ case 16:
+ pixel_number |= ((y >> 0) & 1) << 0; // pn[0] = y[0]
+ pixel_number |= ((x >> 0) & 1) << 1; // pn[1] = x[0]
+ pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
+ pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
+ pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
+ pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+ break;
+ }
+ return pixel_number;
+}
+
+
+static inline GLint
+r600_1d_tile_helper(const struct radeon_renderbuffer * rrb,
+ GLint x, GLint y,
+ GLint is_depth,
+ GLint is_stencil)
+{
+ GLint element_bytes = rrb->cpp;
+ GLint num_samples = 1;
+ GLint tile_width = 8;
+ GLint tile_height = 8;
+ GLint tile_thickness = 1;
+ GLint pitch_elements = rrb->pitch / element_bytes;
+ GLint height = rrb->base.Height;
+ GLint z = 0;
+ GLint sample_number = 0;
+ /* */
+ GLint tile_bytes;
+ GLint tiles_per_row;
+ GLint tiles_per_slice;
+ GLint slice_offset;
+ GLint tile_row_index;
+ GLint tile_column_index;
+ GLint tile_offset;
+ GLint pixel_number = 0;
+ GLint element_offset;
+ GLint offset = 0;
+
+ tile_bytes = tile_width * tile_height * tile_thickness * element_bytes * num_samples;
+ tiles_per_row = pitch_elements / tile_width;
+ tiles_per_slice = tiles_per_row * (height / tile_height);
+ slice_offset = (z / tile_thickness) * tiles_per_slice * tile_bytes;
+ tile_row_index = y / tile_height;
+ tile_column_index = x / tile_width;
+ tile_offset = ((tile_row_index * tiles_per_row) + tile_column_index) * tile_bytes;
+
+ if (is_depth) {
+ GLint pixel_offset = 0;
+
+ pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
+ pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
+ pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
+ pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
+ pixel_number |= ((x >> 2) & 1) << 4; // pn[4] = x[2]
+ pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+ switch (element_bytes) {
+ case 2:
+ pixel_offset = pixel_number * element_bytes * num_samples;
+ break;
+ case 4:
+ /* stencil and depth data are stored separately within a tile.
+ * stencil is stored in a contiguous tile before the depth tile.
+ * stencil element is 1 byte, depth element is 3 bytes.
+ * stencil tile is 64 bytes.
+ */
+ if (is_stencil)
+ pixel_offset = pixel_number * 1 * num_samples;
+ else
+ pixel_offset = (pixel_number * 3 * num_samples) + 64;
+ break;
+ }
+ element_offset = pixel_offset + (sample_number * element_bytes);
+ } else {
+ GLint sample_offset;
+
+ pixel_number = r600_coord_within_microtile(x, y, element_bytes);
+ sample_offset = sample_number * (tile_bytes / num_samples);
+ element_offset = sample_offset + (pixel_number * element_bytes);
+ }
+ offset = slice_offset + tile_offset + element_offset;
+ return offset;
+}
+
+
+static inline GLint
+r600_log2(GLint n)
+{
+ GLint log2 = 0;
+
+ while (n >>= 1)
+ ++log2;
+ return log2;
+}
+
+
+static inline GLint
+r600_2d_tile_helper(const struct radeon_renderbuffer * rrb,
+ GLint x, GLint y,
+ GLint is_depth,
+ GLint is_stencil)
+{
+ GLint group_bytes = rrb->group_bytes;
+ GLint num_channels = rrb->num_channels;
+ GLint num_banks = rrb->num_banks;
+ GLint r7xx_bank_op = rrb->r7xx_bank_op;
+ /* */
+ GLint group_bits = r600_log2(group_bytes);
+ GLint channel_bits = r600_log2(num_channels);
+ GLint bank_bits = r600_log2(num_banks);
+ GLint element_bytes = rrb->cpp;
+ GLint num_samples = 1;
+ GLint tile_width = 8;
+ GLint tile_height = 8;
+ GLint tile_thickness = 1;
+ GLint macro_tile_width = num_banks;
+ GLint macro_tile_height = num_channels;
+ GLint pitch_elements = (rrb->pitch / element_bytes) / tile_width;
+ GLint height = rrb->base.Height / tile_height;
+ GLint z = 0;
+ GLint sample_number = 0;
+ /* */
+ GLint tile_bytes;
+ GLint macro_tile_bytes;
+ GLint macro_tiles_per_row;
+ GLint macro_tiles_per_slice;
+ GLint slice_offset;
+ GLint macro_tile_row_index;
+ GLint macro_tile_column_index;
+ GLint macro_tile_offset;
+ GLint pixel_number = 0;
+ GLint element_offset;
+ GLint bank = 0;
+ GLint channel = 0;
+ GLint total_offset;
+ GLint group_mask = (1 << group_bits) - 1;
+ GLint offset_low;
+ GLint offset_high;
+ GLint offset = 0;
+
+ switch (num_channels) {
+ case 2:
+ default:
+ // channel[0] = x[3] ^ y[3]
+ channel |= (((x >> 3) ^ (y >> 3)) & 1) << 0;
+ break;
+ case 4:
+ // channel[0] = x[4] ^ y[3]
+ channel |= (((x >> 4) ^ (y >> 3)) & 1) << 0;
+ // channel[1] = x[3] ^ y[4]
+ channel |= (((x >> 3) ^ (y >> 4)) & 1) << 1;
+ break;
+ case 8:
+ // channel[0] = x[5] ^ y[3]
+ channel |= (((x >> 5) ^ (y >> 3)) & 1) << 0;
+ // channel[0] = x[4] ^ x[5] ^ y[4]
+ channel |= (((x >> 4) ^ (x >> 5) ^ (y >> 4)) & 1) << 1;
+ // channel[0] = x[3] ^ y[5]
+ channel |= (((x >> 3) ^ (y >> 5)) & 1) << 2;
+ break;
+ }
+
+ switch (num_banks) {
+ case 4:
+ // bank[0] = x[3] ^ y[4 + log2(num_channels)]
+ bank |= (((x >> 3) ^ (y >> (4 + channel_bits))) & 1) << 0;
+ if (r7xx_bank_op)
+ // bank[1] = x[3] ^ y[4 + log2(num_channels)] ^ x[5]
+ bank |= (((x >> 4) ^ (y >> (3 + channel_bits)) ^ (x >> 5)) & 1) << 1;
+ else
+ // bank[1] = x[4] ^ y[3 + log2(num_channels)]
+ bank |= (((x >> 4) ^ (y >> (3 + channel_bits))) & 1) << 1;
+ break;
+ case 8:
+ // bank[0] = x[3] ^ y[5 + log2(num_channels)]
+ bank |= (((x >> 3) ^ (y >> (5 + channel_bits))) & 1) << 0;
+ // bank[1] = x[4] ^ y[4 + log2(num_channels)] ^ y[5 + log2(num_channels)]
+ bank |= (((x >> 4) ^ (y >> (4 + channel_bits)) ^ (y >> (5 + channel_bits))) & 1) << 1;
+ if (r7xx_bank_op)
+ // bank[2] = x[5] ^ y[3 + log2(num_channels)] ^ x[6]
+ bank |= (((x >> 5) ^ (y >> (3 + channel_bits)) ^ (x >> 6)) & 1) << 2;
+ else
+ // bank[2] = x[5] ^ y[3 + log2(num_channels)]
+ bank |= (((x >> 5) ^ (y >> (3 + channel_bits))) & 1) << 2;
+ break;
+ }
+
+ tile_bytes = tile_width * tile_height * tile_thickness * element_bytes * num_samples;
+ macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
+ macro_tiles_per_row = pitch_elements / macro_tile_width;
+ macro_tiles_per_slice = macro_tiles_per_row * (height / macro_tile_height);
+ slice_offset = (z / tile_thickness) * macro_tiles_per_slice * macro_tile_bytes;
+ macro_tile_row_index = (y / tile_height) / macro_tile_height;
+ macro_tile_column_index = (x / tile_width) / macro_tile_width;
+ macro_tile_offset = ((macro_tile_row_index * macro_tiles_per_row) + macro_tile_column_index) * macro_tile_bytes;
+
+ if (is_depth) {
+ GLint pixel_offset = 0;
+
+ pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
+ pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
+ pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
+ pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
+ pixel_number |= ((x >> 2) & 1) << 4; // pn[4] = x[2]
+ pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+ switch (element_bytes) {
+ case 2:
+ pixel_offset = pixel_number * element_bytes * num_samples;
+ break;
+ case 4:
+ /* stencil and depth data are stored separately within a tile.
+ * stencil is stored in a contiguous tile before the depth tile.
+ * stencil element is 1 byte, depth element is 3 bytes.
+ * stencil tile is 64 bytes.
+ */
+ if (is_stencil)
+ pixel_offset = pixel_number * 1 * num_samples;
+ else
+ pixel_offset = (pixel_number * 3 * num_samples) + 64;
+ break;
+ }
+ element_offset = pixel_offset + (sample_number * element_bytes);
+ } else {
+ GLint sample_offset;
+
+ pixel_number = r600_coord_within_microtile(x, y, element_bytes);
+
+ sample_offset = sample_number * (tile_bytes / num_samples);
+ element_offset = sample_offset + (pixel_number * element_bytes);
+ }
+ total_offset = (slice_offset + macro_tile_offset) >> (channel_bits + bank_bits);
+ total_offset += element_offset;
+
+ offset_low = total_offset & group_mask;
+ offset_high = (total_offset & ~group_mask) << (channel_bits + bank_bits);
+ offset = (bank << (group_bits + channel_bits)) + (channel << group_bits) + offset_low + offset_high;
+
+ return offset;
+}
+
+
+uint8_t *
+r600_ptr_depth(const struct radeon_renderbuffer * rrb, int x, int y)
+{
+ GLubyte *ptr = rrb->bo->ptr;
+ GLint offset;
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+ offset = r600_2d_tile_helper(rrb, x, y, 1, 0);
+ else
+ offset = r600_1d_tile_helper(rrb, x, y, 1, 0);
+ return &ptr[offset];
+}
+
+
+uint8_t *
+r600_ptr_stencil(const struct radeon_renderbuffer * rrb, int x, int y)
+{
+ GLubyte *ptr = rrb->bo->ptr;
+ GLint offset;
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+ offset = r600_2d_tile_helper(rrb, x, y, 1, 1);
+ else
+ offset = r600_1d_tile_helper(rrb, x, y, 1, 1);
+ return &ptr[offset];
+}
+
+
+uint8_t *
+r600_ptr_color(const struct radeon_renderbuffer * rrb, int x, int y)
+{
+ GLubyte *ptr = rrb->bo->ptr;
+ uint32_t mask = RADEON_BO_FLAGS_MACRO_TILE | RADEON_BO_FLAGS_MICRO_TILE;
+ GLint offset;
+ if (rrb->has_surface || !(rrb->bo->flags & mask)) {
+ offset = x * rrb->cpp + y * rrb->pitch;
+ } else {
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+ offset = r600_2d_tile_helper(rrb, x, y, 0, 0);
+ else
+ offset = r600_1d_tile_helper(rrb, x, y, 0, 0);
+ }
+ return &ptr[offset];
+}
+
+} // namespace mesa
diff --git a/src/gpu/mesa_r600_tiling.h b/src/gpu/mesa_r600_tiling.h
new file mode 100755
index 00000000..9a462170
--- /dev/null
+++ b/src/gpu/mesa_r600_tiling.h
@@ -0,0 +1,42 @@
+#pragma once
+#include
+
+#define RADEON_BO_FLAGS_MACRO_TILE 1
+#define RADEON_BO_FLAGS_MICRO_TILE 2
+
+namespace mesa
+{
+
+struct radeon_renderbuffer
+{
+ struct
+ {
+ int Width;
+ int Height;
+ } base;
+
+ struct data
+ {
+ uint8_t *ptr;
+ uint32_t flags;
+ } *bo;
+
+ bool has_surface;
+ int pitch;
+ int cpp; // byte per pixel
+ int group_bytes;
+ int num_channels; // same as pipes in r800 and above
+ int num_banks;
+ int r7xx_bank_op;
+};
+
+uint8_t *
+r600_ptr_depth(const struct radeon_renderbuffer * rrb, int x, int y);
+
+uint8_t *
+r600_ptr_stencil(const struct radeon_renderbuffer * rrb, int x, int y);
+
+uint8_t *
+r600_ptr_color(const struct radeon_renderbuffer * rrb, int x, int y);
+
+} // namespace mesa