xref: /aosp_15_r20/external/mesa3d/src/mesa/main/glthread_pixels.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2024 Advanced Micro Devices, Inc.
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "main/glthread_marshal.h"
8 #include "main/dispatch.h"
9 #include "main/image.h"
10 
11 #define MAX_BITMAP_BYTE_SIZE     4096
12 #define MAX_DRAWPIX_BYTE_SIZE    4096
13 
14 struct marshal_cmd_Bitmap
15 {
16    struct marshal_cmd_base cmd_base;
17    uint16_t num_slots;
18    GLsizei width;
19    GLsizei height;
20    GLfloat xorig;
21    GLfloat yorig;
22    GLfloat xmove;
23    GLfloat ymove;
24    GLubyte *bitmap;
25 };
26 
27 uint32_t
_mesa_unmarshal_Bitmap(struct gl_context * ctx,const struct marshal_cmd_Bitmap * restrict cmd)28 _mesa_unmarshal_Bitmap(struct gl_context *ctx,
29                        const struct marshal_cmd_Bitmap *restrict cmd)
30 {
31    CALL_Bitmap(ctx->Dispatch.Current,
32                (cmd->width, cmd->height, cmd->xorig, cmd->yorig, cmd->xmove,
33                 cmd->ymove, cmd->bitmap));
34    return cmd->num_slots;
35 }
36 
37 void GLAPIENTRY
_mesa_marshal_Bitmap(GLsizei width,GLsizei height,GLfloat xorig,GLfloat yorig,GLfloat xmove,GLfloat ymove,const GLubyte * bitmap)38 _mesa_marshal_Bitmap(GLsizei width, GLsizei height, GLfloat xorig,
39                      GLfloat yorig, GLfloat xmove, GLfloat ymove,
40                      const GLubyte *bitmap)
41 {
42    GET_CURRENT_CONTEXT(ctx);
43    int cmd_size = sizeof(struct marshal_cmd_Bitmap);
44 
45    /* If not building a display list... */
46    if (!ctx->GLThread.ListMode) {
47       /* PBO path or bitmap == NULL (which means xmove/ymove only move the raster
48        * pos.
49        */
50       if (!bitmap || _mesa_glthread_has_unpack_buffer(ctx)) {
51          struct marshal_cmd_Bitmap *cmd =
52             _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_Bitmap,
53                                             cmd_size);
54          cmd->num_slots = align(cmd_size, 8) / 8;
55          cmd->width = width;
56          cmd->height = height;
57          cmd->xorig = xorig;
58          cmd->yorig = yorig;
59          cmd->xmove = xmove;
60          cmd->ymove = ymove;
61          cmd->bitmap = (GLubyte *)bitmap;
62          return;
63       }
64 
65       size_t bitmap_size =
66          (size_t)_mesa_image_row_stride(&ctx->GLThread.Unpack, width,
67                                         GL_COLOR_INDEX, GL_BITMAP) * height;
68 
69       /* If the bitmap is small enough, copy it into the batch. */
70       if (bitmap_size <= MAX_BITMAP_BYTE_SIZE) {
71          struct marshal_cmd_Bitmap *cmd =
72             _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_Bitmap,
73                                             cmd_size + bitmap_size);
74          cmd->num_slots = align(cmd_size + bitmap_size, 8) / 8;
75          cmd->width = width;
76          cmd->height = height;
77          cmd->xorig = xorig;
78          cmd->yorig = yorig;
79          cmd->xmove = xmove;
80          cmd->ymove = ymove;
81          cmd->bitmap = (GLubyte *)(cmd + 1);
82          memcpy(cmd->bitmap, bitmap, bitmap_size);
83          return;
84       }
85    }
86 
87    _mesa_glthread_finish_before(ctx, "Bitmap");
88    CALL_Bitmap(ctx->Dispatch.Current,
89                (width, height, xorig, yorig, xmove, ymove, bitmap));
90 }
91 
92 struct marshal_cmd_DrawPixels
93 {
94    struct marshal_cmd_base cmd_base;
95    uint16_t num_slots;
96    GLenum16 format;
97    GLenum16 type;
98    GLsizei width;
99    GLsizei height;
100    GLvoid *pixels;
101 };
102 
103 uint32_t
_mesa_unmarshal_DrawPixels(struct gl_context * ctx,const struct marshal_cmd_DrawPixels * restrict cmd)104 _mesa_unmarshal_DrawPixels(struct gl_context *ctx,
105                            const struct marshal_cmd_DrawPixels *restrict cmd)
106 {
107    CALL_DrawPixels(ctx->Dispatch.Current,
108                    (cmd->width, cmd->height, cmd->format, cmd->type,
109                     cmd->pixels));
110    return cmd->num_slots;
111 }
112 
113 void GLAPIENTRY
_mesa_marshal_DrawPixels(GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)114 _mesa_marshal_DrawPixels(GLsizei width, GLsizei height, GLenum format,
115                          GLenum type, const GLvoid *pixels)
116 {
117    GET_CURRENT_CONTEXT(ctx);
118    int cmd_size = sizeof(struct marshal_cmd_DrawPixels);
119 
120    /* If not building a display list... */
121    if (!ctx->GLThread.ListMode) {
122       /* PBO */
123       if (_mesa_glthread_has_unpack_buffer(ctx)) {
124          struct marshal_cmd_DrawPixels *cmd =
125             _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawPixels,
126                                             cmd_size);
127          cmd->num_slots = align(cmd_size, 8) / 8;
128          cmd->format = MIN2(format, 0xffff); /* clamped to 0xffff (invalid enum) */
129          cmd->type = MIN2(type, 0xffff); /* clamped to 0xffff (invalid enum) */
130          cmd->width = width;
131          cmd->height = height;
132          cmd->pixels = (void *)pixels;
133          return;
134       }
135 
136       /* A negative stride is unimplemented (it inverts the offset). */
137       if (!ctx->Unpack.Invert) {
138          size_t image_size =
139             (size_t)_mesa_image_row_stride(&ctx->GLThread.Unpack,
140                                            width, format, type) * height;
141 
142          /* If the image is small enough, copy it into the batch. */
143          if (image_size <= MAX_DRAWPIX_BYTE_SIZE) {
144             struct marshal_cmd_DrawPixels *cmd =
145                _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawPixels,
146                                                cmd_size + image_size);
147             cmd->num_slots = align(cmd_size + image_size, 8) / 8;
148             cmd->format = MIN2(format, 0xffff); /* clamped to 0xffff (invalid enum) */
149             cmd->type = MIN2(type, 0xffff); /* clamped to 0xffff (invalid enum) */
150             cmd->width = width;
151             cmd->height = height;
152             cmd->pixels = cmd + 1;
153             memcpy(cmd->pixels, pixels, image_size);
154             return;
155          }
156       }
157    }
158 
159    _mesa_glthread_finish_before(ctx, "DrawPixels");
160    CALL_DrawPixels(ctx->Dispatch.Current,
161                    (width, height, format, type, pixels));
162 }
163