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