r300_texture.c revision 63c9450ae776ff4207422442dd8c3d9d13a05e7a
10648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson/*
20648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
30648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson *
40648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * Permission is hereby granted, free of charge, to any person obtaining a
50648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * copy of this software and associated documentation files (the "Software"),
60648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * to deal in the Software without restriction, including without limitation
70648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * on the rights to use, copy, modify, merge, publish, distribute, sub
80648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * license, and/or sell copies of the Software, and to permit persons to whom
90648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * the Software is furnished to do so, subject to the following conditions:
100648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson *
110648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * The above copyright notice and this permission notice (including the next
120648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * paragraph) shall be included in all copies or substantial portions of the
130648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * Software.
140648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson *
150648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
160648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
170648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
180648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
190648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
200648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
210648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson * USE OR OTHER DEALINGS IN THE SOFTWARE. */
220648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson
236a448a525baf81173f92ee8c3074b98baa54397bCorbin Simpson#include "pipe/p_screen.h"
246a448a525baf81173f92ee8c3074b98baa54397bCorbin Simpson
256a448a525baf81173f92ee8c3074b98baa54397bCorbin Simpson#include "util/u_math.h"
266a448a525baf81173f92ee8c3074b98baa54397bCorbin Simpson#include "util/u_memory.h"
276a448a525baf81173f92ee8c3074b98baa54397bCorbin Simpson
286a448a525baf81173f92ee8c3074b98baa54397bCorbin Simpson#include "r300_context.h"
290648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson#include "r300_texture.h"
30827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák#include "r300_screen.h"
310648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson
32827002f5ff990f8676385583275d6b8090abfb7aMarek Olšákstatic void r300_setup_texture_state(struct r300_texture* tex, boolean is_r500)
339d9e0815be41fa72ff5df6752b02551b648b33b6Corbin Simpson{
349d9e0815be41fa72ff5df6752b02551b648b33b6Corbin Simpson    struct r300_texture_state* state = &tex->state;
359bf85f6b95cb684d16b6035381b1f8a9c44f473fDave Airlie    struct pipe_texture *pt = &tex->tex;
369d9e0815be41fa72ff5df6752b02551b648b33b6Corbin Simpson
379bf85f6b95cb684d16b6035381b1f8a9c44f473fDave Airlie    state->format0 = R300_TX_WIDTH((pt->width[0] - 1) & 0x7ff) |
38827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák                     R300_TX_HEIGHT((pt->height[0] - 1) & 0x7ff);
39827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák
4063c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák    if (tex->is_npot) {
41827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák        /* rectangles love this */
42827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák        state->format0 |= R300_TX_PITCH_EN;
4363c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák        state->format2 = (tex->pitch[0] - 1) & 0x1fff;
4463c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák    } else {
45827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák        /* power of two textures (3D, mipmaps, and no pitch) */
46827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák        state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth[0]) & 0xf) |
47827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák                          R300_TX_NUM_LEVELS(pt->last_level & 0xf);
48827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák    }
499d9e0815be41fa72ff5df6752b02551b648b33b6Corbin Simpson
509bf85f6b95cb684d16b6035381b1f8a9c44f473fDave Airlie    state->format1 = r300_translate_texformat(pt->format);
51eb5dd947fbed35478784e777fe2e59564fee051bDave Airlie    if (pt->target == PIPE_TEXTURE_CUBE) {
52034db65f08b943ee9940947db69e4e190f751061Corbin Simpson        state->format1 |= R300_TX_FORMAT_CUBIC_MAP;
53eb5dd947fbed35478784e777fe2e59564fee051bDave Airlie    }
54eb5dd947fbed35478784e777fe2e59564fee051bDave Airlie    if (pt->target == PIPE_TEXTURE_3D) {
55034db65f08b943ee9940947db69e4e190f751061Corbin Simpson        state->format1 |= R300_TX_FORMAT_3D;
56eb5dd947fbed35478784e777fe2e59564fee051bDave Airlie    }
579d9e0815be41fa72ff5df6752b02551b648b33b6Corbin Simpson
58827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák    /* large textures on r500 */
59827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák    if (is_r500)
60827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák    {
61827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák        if (pt->width[0] > 2048) {
62827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák            state->format2 |= R500_TXWIDTH_BIT11;
63827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák        }
64827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák        if (pt->height[0] > 2048) {
65827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák            state->format2 |= R500_TXHEIGHT_BIT11;
66827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák        }
671aa38b2c2d80b67fe2eefe468f90aeb44bc20259Corbin Simpson    }
68827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák    assert(is_r500 || (pt->width[0] <= 2048 && pt->height[0] <= 2048));
692cbd5ecfb666a757c4abef85dbe40fb53d647ec9Corbin Simpson
709ca94f91a3b48350b02a8fec5ecf60a819a24de5Nicolai Hähnle    debug_printf("r300: Set texture state (%dx%d, %d levels)\n",
719bf85f6b95cb684d16b6035381b1f8a9c44f473fDave Airlie		 pt->width[0], pt->height[0], pt->last_level);
723cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle}
733cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle
74118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšákunsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
75118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák                                 unsigned zslice, unsigned face)
76118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák{
77118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák    unsigned offset = tex->offset[level];
78118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák
79118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák    switch (tex->tex.target) {
80118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák        case PIPE_TEXTURE_3D:
81118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák            assert(face == 0);
82118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák            return offset + zslice * tex->layer_size[level];
83118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák
84118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák        case PIPE_TEXTURE_CUBE:
85118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák            assert(zslice == 0);
86118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák            return offset + face * tex->layer_size[level];
87118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák
88118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák        default:
89118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák            assert(zslice == 0 && face == 0);
90118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák            return offset;
91118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák    }
92118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák}
93118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák
943cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle/**
953cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle * Return the stride, in bytes, of the texture images of the given texture
963cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle * at the given level.
973cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle */
983cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnleunsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level)
993cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle{
1003cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle    if (tex->stride_override)
1013cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle        return tex->stride_override;
1023cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle
1033cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle    if (level > tex->tex.last_level) {
104034db65f08b943ee9940947db69e4e190f751061Corbin Simpson        debug_printf("%s: level (%u) > last_level (%u)\n", __FUNCTION__,
105034db65f08b943ee9940947db69e4e190f751061Corbin Simpson            level, tex->tex.last_level);
1063cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle        return 0;
1073cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle    }
1083cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle
1093cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle    return align(pf_get_stride(&tex->tex.block, tex->tex.width[level]), 32);
1109d9e0815be41fa72ff5df6752b02551b648b33b6Corbin Simpson}
1119d9e0815be41fa72ff5df6752b02551b648b33b6Corbin Simpson
1128e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpsonstatic void r300_setup_miptree(struct r300_texture* tex)
1138e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson{
1148e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    struct pipe_texture* base = &tex->tex;
115118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák    int stride, size, layer_size;
1162b5770e652f0e6620b52971755bd7eb31c16ad7dCorbin Simpson    int i;
1178e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1182b5770e652f0e6620b52971755bd7eb31c16ad7dCorbin Simpson    for (i = 0; i <= base->last_level; i++) {
1198e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson        if (i > 0) {
1208e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson            base->width[i] = minify(base->width[i-1]);
1218e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson            base->height[i] = minify(base->height[i-1]);
1228e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson            base->depth[i] = minify(base->depth[i-1]);
1238e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson        }
1248e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1258e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson        base->nblocksx[i] = pf_get_nblocksx(&base->block, base->width[i]);
1262cbd5ecfb666a757c4abef85dbe40fb53d647ec9Corbin Simpson        base->nblocksy[i] = pf_get_nblocksy(&base->block, base->height[i]);
1278e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1283cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle        stride = r300_texture_get_stride(tex, i);
129118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák        layer_size = stride * base->nblocksy[i];
130827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák
131827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák        if (base->target == PIPE_TEXTURE_CUBE)
132827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák            size = layer_size * 6;
133827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák        else
134827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák            size = layer_size * base->depth[i];
1358e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1362cbd5ecfb666a757c4abef85dbe40fb53d647ec9Corbin Simpson        tex->offset[i] = align(tex->size, 32);
137048f988aeb06fa360c6c41eaa50cb96b4b86e34eMichel Dänzer        tex->size = tex->offset[i] + size;
138118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák        tex->layer_size[i] = layer_size;
1397c204c975381b0ef4a7693827ffc4ff904de991cCorbin Simpson
14063c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák        if (tex->is_npot) {
14163c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák            tex->pitch[i] = stride / base->block.size;
14263c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák        } else {
14363c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák            tex->pitch[i] = base->width[i];
14463c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák        }
14563c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák
1462cbd5ecfb666a757c4abef85dbe40fb53d647ec9Corbin Simpson        debug_printf("r300: Texture miptree: Level %d "
1472cbd5ecfb666a757c4abef85dbe40fb53d647ec9Corbin Simpson                "(%dx%dx%d px, pitch %d bytes)\n",
1482cbd5ecfb666a757c4abef85dbe40fb53d647ec9Corbin Simpson                i, base->width[i], base->height[i], base->depth[i],
1492cbd5ecfb666a757c4abef85dbe40fb53d647ec9Corbin Simpson                stride);
1508e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    }
1518e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson}
1528e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
15363c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšákstatic void r300_setup_flags(struct r300_texture* tex)
15463c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák{
15563c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák    tex->is_npot = !util_is_power_of_two(tex->tex.width[0]) ||
15663c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák                   !util_is_power_of_two(tex->tex.height[0]);
15763c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák}
15863c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák
1590648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson/* Create a new texture. */
1600648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpsonstatic struct pipe_texture*
1610648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson    r300_texture_create(struct pipe_screen* screen,
1620648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson                        const struct pipe_texture* template)
1630648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson{
1648e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    struct r300_texture* tex = CALLOC_STRUCT(r300_texture);
1658e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1668e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    if (!tex) {
1678e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson        return NULL;
1688e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    }
1698e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1708e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    tex->tex = *template;
1715e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    pipe_reference_init(&tex->tex.reference, 1);
1728e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    tex->tex.screen = screen;
1738e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
17463c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák    r300_setup_flags(tex);
1758e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    r300_setup_miptree(tex);
176827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák    r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500);
1779d9e0815be41fa72ff5df6752b02551b648b33b6Corbin Simpson
1787a10472f095ef0f9f6109ca17d8be16836e56509Corbin Simpson    tex->buffer = screen->buffer_create(screen, 1024,
179ce6710e369d3b5c512ba8b315efc863fd41de734Corbin Simpson                                        PIPE_BUFFER_USAGE_PIXEL,
180ce6710e369d3b5c512ba8b315efc863fd41de734Corbin Simpson                                        tex->size);
1818e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1828e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    if (!tex->buffer) {
1838e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson        FREE(tex);
1848e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson        return NULL;
1858e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    }
1868e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1878e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson    return (struct pipe_texture*)tex;
1888e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson}
1898e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1905e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzerstatic void r300_texture_destroy(struct pipe_texture* texture)
1918e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson{
1925e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    struct r300_texture* tex = (struct r300_texture*)texture;
1938e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1945e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    pipe_buffer_reference(&tex->buffer, NULL);
1958e11e0121466efa34cfc14d299b43455a30b198cCorbin Simpson
1965e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    FREE(tex);
1970648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson}
1980648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson
199471129c7a14fb585ede198970e59270c4afa5310Corbin Simpsonstatic struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
200471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson                                                 struct pipe_texture* texture,
201471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson                                                 unsigned face,
202471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson                                                 unsigned level,
203471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson                                                 unsigned zslice,
204471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson                                                 unsigned flags)
205471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson{
206471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson    struct r300_texture* tex = (struct r300_texture*)texture;
207471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson    struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface);
208471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson    unsigned offset;
209471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson
210118dfe16887d1ec4d3b96d49b76fffa0d2924132Marek Olšák    offset = r300_texture_get_offset(tex, level, zslice, face);
211471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson
212471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson    if (surface) {
2135e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer        pipe_reference_init(&surface->reference, 1);
214471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson        pipe_texture_reference(&surface->texture, texture);
215471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson        surface->format = texture->format;
216471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson        surface->width = texture->width[level];
217471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson        surface->height = texture->height[level];
218471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson        surface->offset = offset;
219471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson        surface->usage = flags;
220c2df759cd73e281c4698c717e0ab89757a7affd5Marek Olšák        surface->zslice = zslice;
221c2df759cd73e281c4698c717e0ab89757a7affd5Marek Olšák        surface->texture = texture;
222c2df759cd73e281c4698c717e0ab89757a7affd5Marek Olšák        surface->face = face;
223c2df759cd73e281c4698c717e0ab89757a7affd5Marek Olšák        surface->level = level;
224471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson    }
225471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson
226471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson    return surface;
227471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson}
228471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson
2295e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzerstatic void r300_tex_surface_destroy(struct pipe_surface* s)
230471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson{
2315e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    pipe_texture_reference(&s->texture, NULL);
2325e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    FREE(s);
233471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson}
234471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson
2351a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpsonstatic struct pipe_texture*
2361a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson    r300_texture_blanket(struct pipe_screen* screen,
2371a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson                         const struct pipe_texture* base,
2381a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson                         const unsigned* stride,
2391a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson                         struct pipe_buffer* buffer)
2401a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson{
2411a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson    struct r300_texture* tex;
2421a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson
24363c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák    /* Support only 2D textures without mipmaps */
24463c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák    if (base->target != PIPE_TEXTURE_2D ||
24563c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák        base->depth[0] != 1 ||
24663c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák        base->last_level != 0) {
24763c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák        return NULL;
24863c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák    }
24963c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák
2501a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson    tex = CALLOC_STRUCT(r300_texture);
2511a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson    if (!tex) {
2521a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson        return NULL;
2531a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson    }
2541a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson
2551a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson    tex->tex = *base;
2565e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    pipe_reference_init(&tex->tex.reference, 1);
2571a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson    tex->tex.screen = screen;
2581a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson
2593cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle    tex->stride_override = *stride;
26063c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák    tex->pitch[0] = *stride / base->block.size;
2611a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson
26263c9450ae776ff4207422442dd8c3d9d13a05e7aMarek Olšák    r300_setup_flags(tex);
263827002f5ff990f8676385583275d6b8090abfb7aMarek Olšák    r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500);
2649d9e0815be41fa72ff5df6752b02551b648b33b6Corbin Simpson
2655e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    pipe_buffer_reference(&tex->buffer, buffer);
2665425c4aa28721072085f128e902f5679ba31a963Corbin Simpson
2671a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson    return (struct pipe_texture*)tex;
2681a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson}
2691a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson
270a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuanstatic struct pipe_video_surface *
271a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuanr300_video_surface_create(struct pipe_screen *screen,
272a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan                          enum pipe_video_chroma_format chroma_format,
273a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan                          unsigned width, unsigned height)
274a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan{
275a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    struct r300_video_surface *r300_vsfc;
276a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    struct pipe_texture template;
277a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan
278a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    assert(screen);
279a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    assert(width && height);
280a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan
281a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    r300_vsfc = CALLOC_STRUCT(r300_video_surface);
282a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    if (!r300_vsfc)
283a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan       return NULL;
284a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan
285a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    pipe_reference_init(&r300_vsfc->base.reference, 1);
286a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    r300_vsfc->base.screen = screen;
287a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    r300_vsfc->base.chroma_format = chroma_format;
288a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    r300_vsfc->base.width = width;
289a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    r300_vsfc->base.height = height;
290a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan
291a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    memset(&template, 0, sizeof(struct pipe_texture));
292a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    template.target = PIPE_TEXTURE_2D;
293a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    template.format = PIPE_FORMAT_X8R8G8B8_UNORM;
294a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    template.last_level = 0;
295a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    template.width[0] = util_next_power_of_two(width);
296a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    template.height[0] = util_next_power_of_two(height);
297a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    template.depth[0] = 1;
298a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    pf_get_block(template.format, &template.block);
299a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER |
300a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan                         PIPE_TEXTURE_USAGE_RENDER_TARGET;
301a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan
302a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    r300_vsfc->tex = screen->texture_create(screen, &template);
303a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    if (!r300_vsfc->tex)
304a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    {
305a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan        FREE(r300_vsfc);
306a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan        return NULL;
307a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    }
308a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan
309a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    return &r300_vsfc->base;
310a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan}
311a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan
312a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuanstatic void r300_video_surface_destroy(struct pipe_video_surface *vsfc)
313a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan{
314a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    struct r300_video_surface *r300_vsfc = r300_video_surface(vsfc);
315a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    pipe_texture_reference(&r300_vsfc->tex, NULL);
316a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    FREE(r300_vsfc);
317a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan}
318a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan
3190648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpsonvoid r300_init_screen_texture_functions(struct pipe_screen* screen)
3200648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson{
3210648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson    screen->texture_create = r300_texture_create;
3225e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    screen->texture_destroy = r300_texture_destroy;
323471129c7a14fb585ede198970e59270c4afa5310Corbin Simpson    screen->get_tex_surface = r300_get_tex_surface;
3245e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    screen->tex_surface_destroy = r300_tex_surface_destroy;
3251a5eea0c1e9ce6162ed6b07c337bffe62cb3c221Corbin Simpson    screen->texture_blanket = r300_texture_blanket;
326a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan
327a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    screen->video_surface_create = r300_video_surface_create;
328a74e53ddba246b1f6604c6120b63a923fd9c60d5Cooper Yuan    screen->video_surface_destroy= r300_video_surface_destroy;
3290648bc9f65f1c6700b442e57ac0e82404fb60c2dCorbin Simpson}
33060041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson
33160041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpsonboolean r300_get_texture_buffer(struct pipe_texture* texture,
33260041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson                                struct pipe_buffer** buffer,
33360041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson                                unsigned* stride)
33460041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson{
33560041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson    struct r300_texture* tex = (struct r300_texture*)texture;
33660041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson    if (!tex) {
33760041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson        return FALSE;
33860041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson    }
33960041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson
3405e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer    pipe_buffer_reference(buffer, tex->buffer);
34160041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson
34260041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson    if (stride) {
3433cb30e55e48d86aa5f660e670e055d6b258ea54aNicolai Hähnle        *stride = r300_texture_get_stride(tex, 0);
34460041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson    }
34560041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson
34660041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson    return TRUE;
34760041203d5847de8ab71842a6ce5d33d96cc4930Corbin Simpson}
348