1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (C) 2009 Maciej Cencora <m.cencora@gmail.com>
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * All Rights Reserved.
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * a copy of this software and associated documentation files (the
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "Software"), to deal in the Software without restriction, including
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * without limitation the rights to use, copy, modify, merge, publish,
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * distribute, sublicense, and/or sell copies of the Software, and to
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * permit persons to whom the Software is furnished to do so, subject to
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the following conditions:
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * next paragraph) shall be included in all copies or substantial
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * portions of the Software.
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_common.h"
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_texture.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/enums.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/image.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/teximage.h"
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/texstate.h"
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "drivers/common/meta.h"
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_mipmap_tree.h"
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic GLboolean
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdo_copy_texsubimage(struct gl_context *ctx,
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    struct radeon_tex_obj *tobj,
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    radeon_texture_image *timg,
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    GLint dstx, GLint dsty,
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    struct radeon_renderbuffer *rrb,
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    GLint x, GLint y,
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    GLsizei width, GLsizei height)
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    radeonContextPtr radeon = RADEON_CONTEXT(ctx);
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const GLuint face = timg->base.Base.Face;
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const GLuint level = timg->base.Base.Level;
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned src_bpp;
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned dst_bpp;
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    gl_format src_mesaformat;
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    gl_format dst_mesaformat;
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned flip_y;
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (!radeon->vtbl.blit) {
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return GL_FALSE;
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    // This is software renderbuffer, fallback to swrast
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (!rrb) {
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return GL_FALSE;
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (_mesa_get_format_bits(timg->base.Base.TexFormat, GL_DEPTH_BITS) > 0) {
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* copying depth values */
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        flip_y = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Type == GL_NONE;
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else {
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* copying color */
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        flip_y = ctx->ReadBuffer->Attachment[BUFFER_COLOR0].Type == GL_NONE;
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (!timg->mt) {
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        radeon_validate_texture_miptree(ctx, &tobj->base.Sampler, &tobj->base);
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    assert(rrb->bo);
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    assert(timg->mt);
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    assert(timg->mt->bo);
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    assert(timg->base.Base.Width >= dstx + width);
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    assert(timg->base.Base.Height >= dsty + height);
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    intptr_t src_offset = rrb->draw_offset;
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    intptr_t dst_offset = radeon_miptree_image_offset(timg->mt, face, level);
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (0) {
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        fprintf(stderr, "%s: copying to face %d, level %d\n",
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                __FUNCTION__, face, level);
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        fprintf(stderr, "to: x %d, y %d, offset %d\n", dstx, dsty, (uint32_t) dst_offset);
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        fprintf(stderr, "from (%dx%d) width %d, height %d, offset %d, pitch %d\n",
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                x, y, rrb->base.Base.Width, rrb->base.Base.Height, (uint32_t) src_offset, rrb->pitch/rrb->cpp);
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        fprintf(stderr, "src size %d, dst size %d\n", rrb->bo->size, timg->mt->bo->size);
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    src_mesaformat = rrb->base.Base.Format;
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    dst_mesaformat = timg->base.Base.TexFormat;
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    src_bpp = _mesa_get_format_bytes(src_mesaformat);
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    dst_bpp = _mesa_get_format_bytes(dst_mesaformat);
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (!radeon->vtbl.check_blit(dst_mesaformat, rrb->pitch / rrb->cpp)) {
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* depth formats tend to be special */
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (_mesa_get_format_bits(dst_mesaformat, GL_DEPTH_BITS) > 0)
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    return GL_FALSE;
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (src_bpp != dst_bpp)
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    return GL_FALSE;
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    switch (dst_bpp) {
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    case 2:
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    src_mesaformat = MESA_FORMAT_RGB565;
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    dst_mesaformat = MESA_FORMAT_RGB565;
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    break;
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    case 4:
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    src_mesaformat = MESA_FORMAT_ARGB8888;
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    dst_mesaformat = MESA_FORMAT_ARGB8888;
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    break;
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    case 1:
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    src_mesaformat = MESA_FORMAT_A8;
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    dst_mesaformat = MESA_FORMAT_A8;
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    break;
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    default:
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    return GL_FALSE;
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* blit from src buffer to texture */
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return radeon->vtbl.blit(ctx, rrb->bo, src_offset, src_mesaformat, rrb->pitch/rrb->cpp,
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             rrb->base.Base.Width, rrb->base.Base.Height, x, y,
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             timg->mt->bo, dst_offset, dst_mesaformat,
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             timg->mt->levels[level].rowstride / dst_bpp,
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             timg->base.Base.Width, timg->base.Base.Height,
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             dstx, dsty, width, height, flip_y);
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgradeonCopyTexSubImage(struct gl_context *ctx, GLuint dims,
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      struct gl_texture_image *texImage,
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      GLint xoffset, GLint yoffset, GLint zoffset,
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      struct gl_renderbuffer *rb,
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      GLint x, GLint y,
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      GLsizei width, GLsizei height)
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    radeonContextPtr radeon = RADEON_CONTEXT(ctx);
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    radeon_prepare_render(radeon);
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (dims != 2 || !do_copy_texsubimage(ctx,
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             radeon_tex_obj(texImage->TexObject),
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             (radeon_texture_image *)texImage,
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             xoffset, yoffset,
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             radeon_renderbuffer(rb),                                                        x, y, width, height)) {
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        radeon_print(RADEON_FALLBACKS, RADEON_NORMAL,
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     "Falling back to sw for glCopyTexSubImage2D\n");
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        _mesa_meta_CopyTexSubImage(ctx, dims, texImage,
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   xoffset, yoffset, zoffset,
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     rb, x, y, width, height);
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
161