xref: /aosp_15_r20/external/mesa3d/src/glx/pixel.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3*61046927SAndroid Build Coastguard Worker  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4*61046927SAndroid Build Coastguard Worker  *
5*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: SGI-B-2.0
6*61046927SAndroid Build Coastguard Worker  */
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker #include "packrender.h"
9*61046927SAndroid Build Coastguard Worker 
10*61046927SAndroid Build Coastguard Worker static const GLubyte MsbToLsbTable[256] = {
11*61046927SAndroid Build Coastguard Worker    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
12*61046927SAndroid Build Coastguard Worker    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
13*61046927SAndroid Build Coastguard Worker    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
14*61046927SAndroid Build Coastguard Worker    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
15*61046927SAndroid Build Coastguard Worker    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
16*61046927SAndroid Build Coastguard Worker    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
17*61046927SAndroid Build Coastguard Worker    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
18*61046927SAndroid Build Coastguard Worker    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
19*61046927SAndroid Build Coastguard Worker    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
20*61046927SAndroid Build Coastguard Worker    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
21*61046927SAndroid Build Coastguard Worker    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
22*61046927SAndroid Build Coastguard Worker    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
23*61046927SAndroid Build Coastguard Worker    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
24*61046927SAndroid Build Coastguard Worker    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
25*61046927SAndroid Build Coastguard Worker    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
26*61046927SAndroid Build Coastguard Worker    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
27*61046927SAndroid Build Coastguard Worker    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
28*61046927SAndroid Build Coastguard Worker    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
29*61046927SAndroid Build Coastguard Worker    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
30*61046927SAndroid Build Coastguard Worker    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
31*61046927SAndroid Build Coastguard Worker    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
32*61046927SAndroid Build Coastguard Worker    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
33*61046927SAndroid Build Coastguard Worker    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
34*61046927SAndroid Build Coastguard Worker    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
35*61046927SAndroid Build Coastguard Worker    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
36*61046927SAndroid Build Coastguard Worker    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
37*61046927SAndroid Build Coastguard Worker    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
38*61046927SAndroid Build Coastguard Worker    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
39*61046927SAndroid Build Coastguard Worker    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
40*61046927SAndroid Build Coastguard Worker    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
41*61046927SAndroid Build Coastguard Worker    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
42*61046927SAndroid Build Coastguard Worker    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
43*61046927SAndroid Build Coastguard Worker };
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker static const GLubyte LowBitsMask[9] = {
46*61046927SAndroid Build Coastguard Worker    0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
47*61046927SAndroid Build Coastguard Worker };
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker static const GLubyte HighBitsMask[9] = {
50*61046927SAndroid Build Coastguard Worker    0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
51*61046927SAndroid Build Coastguard Worker };
52*61046927SAndroid Build Coastguard Worker 
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker /*
55*61046927SAndroid Build Coastguard Worker ** Copy bitmap data from clients packed memory applying unpacking modes as the
56*61046927SAndroid Build Coastguard Worker ** data is transferred into the destImage buffer.  Return in modes the
57*61046927SAndroid Build Coastguard Worker ** set of pixel modes that are to be done by the server.
58*61046927SAndroid Build Coastguard Worker */
59*61046927SAndroid Build Coastguard Worker static void
FillBitmap(struct glx_context * gc,GLint width,GLint height,GLenum format,const GLvoid * userdata,GLubyte * destImage)60*61046927SAndroid Build Coastguard Worker FillBitmap(struct glx_context * gc, GLint width, GLint height,
61*61046927SAndroid Build Coastguard Worker            GLenum format, const GLvoid * userdata, GLubyte * destImage)
62*61046927SAndroid Build Coastguard Worker {
63*61046927SAndroid Build Coastguard Worker    const __GLXattribute *state = gc->client_state_private;
64*61046927SAndroid Build Coastguard Worker    GLint rowLength = state->storeUnpack.rowLength;
65*61046927SAndroid Build Coastguard Worker    GLint alignment = state->storeUnpack.alignment;
66*61046927SAndroid Build Coastguard Worker    GLint skipPixels = state->storeUnpack.skipPixels;
67*61046927SAndroid Build Coastguard Worker    GLint skipRows = state->storeUnpack.skipRows;
68*61046927SAndroid Build Coastguard Worker    GLint lsbFirst = state->storeUnpack.lsbFirst;
69*61046927SAndroid Build Coastguard Worker    GLint elementsLeft, bitOffset, currentByte, nextByte, highBitMask;
70*61046927SAndroid Build Coastguard Worker    GLint lowBitMask, i;
71*61046927SAndroid Build Coastguard Worker    GLint components, groupsPerRow, rowSize, padding, elementsPerRow;
72*61046927SAndroid Build Coastguard Worker    const GLubyte *start, *iter;
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker    if (rowLength > 0) {
75*61046927SAndroid Build Coastguard Worker       groupsPerRow = rowLength;
76*61046927SAndroid Build Coastguard Worker    }
77*61046927SAndroid Build Coastguard Worker    else {
78*61046927SAndroid Build Coastguard Worker       groupsPerRow = width;
79*61046927SAndroid Build Coastguard Worker    }
80*61046927SAndroid Build Coastguard Worker    components = __glElementsPerGroup(format, GL_BITMAP);
81*61046927SAndroid Build Coastguard Worker    rowSize = (groupsPerRow * components + 7) >> 3;
82*61046927SAndroid Build Coastguard Worker    padding = (rowSize % alignment);
83*61046927SAndroid Build Coastguard Worker    if (padding) {
84*61046927SAndroid Build Coastguard Worker       rowSize += alignment - padding;
85*61046927SAndroid Build Coastguard Worker    }
86*61046927SAndroid Build Coastguard Worker    start = ((const GLubyte *) userdata) + skipRows * rowSize +
87*61046927SAndroid Build Coastguard Worker       ((skipPixels * components) >> 3);
88*61046927SAndroid Build Coastguard Worker    bitOffset = (skipPixels * components) & 7;
89*61046927SAndroid Build Coastguard Worker    highBitMask = LowBitsMask[8 - bitOffset];
90*61046927SAndroid Build Coastguard Worker    lowBitMask = HighBitsMask[bitOffset];
91*61046927SAndroid Build Coastguard Worker    elementsPerRow = width * components;
92*61046927SAndroid Build Coastguard Worker    for (i = 0; i < height; i++) {
93*61046927SAndroid Build Coastguard Worker       elementsLeft = elementsPerRow;
94*61046927SAndroid Build Coastguard Worker       iter = start;
95*61046927SAndroid Build Coastguard Worker       while (elementsLeft) {
96*61046927SAndroid Build Coastguard Worker          /* First retrieve low bits from current byte */
97*61046927SAndroid Build Coastguard Worker          if (lsbFirst) {
98*61046927SAndroid Build Coastguard Worker             currentByte = MsbToLsbTable[iter[0]];
99*61046927SAndroid Build Coastguard Worker          }
100*61046927SAndroid Build Coastguard Worker          else {
101*61046927SAndroid Build Coastguard Worker             currentByte = iter[0];
102*61046927SAndroid Build Coastguard Worker          }
103*61046927SAndroid Build Coastguard Worker          if (bitOffset) {
104*61046927SAndroid Build Coastguard Worker             /* Need to read next byte to finish current byte */
105*61046927SAndroid Build Coastguard Worker             if (elementsLeft > (8 - bitOffset)) {
106*61046927SAndroid Build Coastguard Worker                if (lsbFirst) {
107*61046927SAndroid Build Coastguard Worker                   nextByte = MsbToLsbTable[iter[1]];
108*61046927SAndroid Build Coastguard Worker                }
109*61046927SAndroid Build Coastguard Worker                else {
110*61046927SAndroid Build Coastguard Worker                   nextByte = iter[1];
111*61046927SAndroid Build Coastguard Worker                }
112*61046927SAndroid Build Coastguard Worker                currentByte =
113*61046927SAndroid Build Coastguard Worker                   ((currentByte & highBitMask) << bitOffset) |
114*61046927SAndroid Build Coastguard Worker                   ((nextByte & lowBitMask) >> (8 - bitOffset));
115*61046927SAndroid Build Coastguard Worker             }
116*61046927SAndroid Build Coastguard Worker             else {
117*61046927SAndroid Build Coastguard Worker                currentByte = ((currentByte & highBitMask) << bitOffset);
118*61046927SAndroid Build Coastguard Worker             }
119*61046927SAndroid Build Coastguard Worker          }
120*61046927SAndroid Build Coastguard Worker          if (elementsLeft >= 8) {
121*61046927SAndroid Build Coastguard Worker             *destImage = currentByte;
122*61046927SAndroid Build Coastguard Worker             elementsLeft -= 8;
123*61046927SAndroid Build Coastguard Worker          }
124*61046927SAndroid Build Coastguard Worker          else {
125*61046927SAndroid Build Coastguard Worker             *destImage = currentByte & HighBitsMask[elementsLeft];
126*61046927SAndroid Build Coastguard Worker             elementsLeft = 0;
127*61046927SAndroid Build Coastguard Worker          }
128*61046927SAndroid Build Coastguard Worker          destImage++;
129*61046927SAndroid Build Coastguard Worker          iter++;
130*61046927SAndroid Build Coastguard Worker       }
131*61046927SAndroid Build Coastguard Worker       start += rowSize;
132*61046927SAndroid Build Coastguard Worker    }
133*61046927SAndroid Build Coastguard Worker }
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker /*
136*61046927SAndroid Build Coastguard Worker ** Extract array from user's data applying all pixel store modes.
137*61046927SAndroid Build Coastguard Worker ** The internal packed array format used has LSB_FIRST = FALSE and
138*61046927SAndroid Build Coastguard Worker ** ALIGNMENT = 1.
139*61046927SAndroid Build Coastguard Worker */
140*61046927SAndroid Build Coastguard Worker void
__glFillImage(struct glx_context * gc,GLint dim,GLint width,GLint height,GLint depth,GLenum format,GLenum type,const GLvoid * userdata,GLubyte * newimage,GLubyte * modes)141*61046927SAndroid Build Coastguard Worker __glFillImage(struct glx_context * gc, GLint dim, GLint width, GLint height,
142*61046927SAndroid Build Coastguard Worker               GLint depth, GLenum format, GLenum type,
143*61046927SAndroid Build Coastguard Worker               const GLvoid * userdata, GLubyte * newimage, GLubyte * modes)
144*61046927SAndroid Build Coastguard Worker {
145*61046927SAndroid Build Coastguard Worker    const __GLXattribute *state = gc->client_state_private;
146*61046927SAndroid Build Coastguard Worker    GLint rowLength = state->storeUnpack.rowLength;
147*61046927SAndroid Build Coastguard Worker    GLint imageHeight = state->storeUnpack.imageHeight;
148*61046927SAndroid Build Coastguard Worker    GLint alignment = state->storeUnpack.alignment;
149*61046927SAndroid Build Coastguard Worker    GLint skipPixels = state->storeUnpack.skipPixels;
150*61046927SAndroid Build Coastguard Worker    GLint skipRows = state->storeUnpack.skipRows;
151*61046927SAndroid Build Coastguard Worker    GLint skipImages = state->storeUnpack.skipImages;
152*61046927SAndroid Build Coastguard Worker    GLint swapBytes = state->storeUnpack.swapEndian;
153*61046927SAndroid Build Coastguard Worker    GLint components, elementSize, rowSize, padding, groupsPerRow, groupSize;
154*61046927SAndroid Build Coastguard Worker    GLint elementsPerRow, imageSize, rowsPerImage, h, i, j, k;
155*61046927SAndroid Build Coastguard Worker    const GLubyte *start, *iter, *itera, *iterb, *iterc;
156*61046927SAndroid Build Coastguard Worker    GLubyte *iter2;
157*61046927SAndroid Build Coastguard Worker 
158*61046927SAndroid Build Coastguard Worker    if (type == GL_BITMAP) {
159*61046927SAndroid Build Coastguard Worker       FillBitmap(gc, width, height, format, userdata, newimage);
160*61046927SAndroid Build Coastguard Worker    }
161*61046927SAndroid Build Coastguard Worker    else {
162*61046927SAndroid Build Coastguard Worker       components = __glElementsPerGroup(format, type);
163*61046927SAndroid Build Coastguard Worker       if (rowLength > 0) {
164*61046927SAndroid Build Coastguard Worker          groupsPerRow = rowLength;
165*61046927SAndroid Build Coastguard Worker       }
166*61046927SAndroid Build Coastguard Worker       else {
167*61046927SAndroid Build Coastguard Worker          groupsPerRow = width;
168*61046927SAndroid Build Coastguard Worker       }
169*61046927SAndroid Build Coastguard Worker       if (imageHeight > 0) {
170*61046927SAndroid Build Coastguard Worker          rowsPerImage = imageHeight;
171*61046927SAndroid Build Coastguard Worker       }
172*61046927SAndroid Build Coastguard Worker       else {
173*61046927SAndroid Build Coastguard Worker          rowsPerImage = height;
174*61046927SAndroid Build Coastguard Worker       }
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker       elementSize = __glBytesPerElement(type);
177*61046927SAndroid Build Coastguard Worker       groupSize = elementSize * components;
178*61046927SAndroid Build Coastguard Worker       if (elementSize == 1)
179*61046927SAndroid Build Coastguard Worker          swapBytes = 0;
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker       rowSize = groupsPerRow * groupSize;
182*61046927SAndroid Build Coastguard Worker       padding = (rowSize % alignment);
183*61046927SAndroid Build Coastguard Worker       if (padding) {
184*61046927SAndroid Build Coastguard Worker          rowSize += alignment - padding;
185*61046927SAndroid Build Coastguard Worker       }
186*61046927SAndroid Build Coastguard Worker       imageSize = rowSize * rowsPerImage;
187*61046927SAndroid Build Coastguard Worker       start = ((const GLubyte *) userdata) + skipImages * imageSize +
188*61046927SAndroid Build Coastguard Worker          skipRows * rowSize + skipPixels * groupSize;
189*61046927SAndroid Build Coastguard Worker       iter2 = newimage;
190*61046927SAndroid Build Coastguard Worker       elementsPerRow = width * components;
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker       if (swapBytes) {
193*61046927SAndroid Build Coastguard Worker          itera = start;
194*61046927SAndroid Build Coastguard Worker          for (h = 0; h < depth; h++) {
195*61046927SAndroid Build Coastguard Worker             iterb = itera;
196*61046927SAndroid Build Coastguard Worker             for (i = 0; i < height; i++) {
197*61046927SAndroid Build Coastguard Worker                iterc = iterb;
198*61046927SAndroid Build Coastguard Worker                for (j = 0; j < elementsPerRow; j++) {
199*61046927SAndroid Build Coastguard Worker                   for (k = 1; k <= elementSize; k++) {
200*61046927SAndroid Build Coastguard Worker                      iter2[k - 1] = iterc[elementSize - k];
201*61046927SAndroid Build Coastguard Worker                   }
202*61046927SAndroid Build Coastguard Worker                   iter2 += elementSize;
203*61046927SAndroid Build Coastguard Worker                   iterc += elementSize;
204*61046927SAndroid Build Coastguard Worker                }
205*61046927SAndroid Build Coastguard Worker                iterb += rowSize;
206*61046927SAndroid Build Coastguard Worker             }
207*61046927SAndroid Build Coastguard Worker             itera += imageSize;
208*61046927SAndroid Build Coastguard Worker          }
209*61046927SAndroid Build Coastguard Worker       }
210*61046927SAndroid Build Coastguard Worker       else {
211*61046927SAndroid Build Coastguard Worker          itera = start;
212*61046927SAndroid Build Coastguard Worker          for (h = 0; h < depth; h++) {
213*61046927SAndroid Build Coastguard Worker             if (rowSize == elementsPerRow * elementSize) {
214*61046927SAndroid Build Coastguard Worker                /* Ha!  This is mondo easy! */
215*61046927SAndroid Build Coastguard Worker                __GLX_MEM_COPY(iter2, itera,
216*61046927SAndroid Build Coastguard Worker                               elementsPerRow * elementSize * height);
217*61046927SAndroid Build Coastguard Worker                iter2 += elementsPerRow * elementSize * height;
218*61046927SAndroid Build Coastguard Worker             }
219*61046927SAndroid Build Coastguard Worker             else {
220*61046927SAndroid Build Coastguard Worker                iter = itera;
221*61046927SAndroid Build Coastguard Worker                for (i = 0; i < height; i++) {
222*61046927SAndroid Build Coastguard Worker                   __GLX_MEM_COPY(iter2, iter, elementsPerRow * elementSize);
223*61046927SAndroid Build Coastguard Worker                   iter2 += elementsPerRow * elementSize;
224*61046927SAndroid Build Coastguard Worker                   iter += rowSize;
225*61046927SAndroid Build Coastguard Worker                }
226*61046927SAndroid Build Coastguard Worker             }
227*61046927SAndroid Build Coastguard Worker             itera += imageSize;
228*61046927SAndroid Build Coastguard Worker          }
229*61046927SAndroid Build Coastguard Worker       }
230*61046927SAndroid Build Coastguard Worker    }
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker    /* Setup store modes that describe what we just did */
233*61046927SAndroid Build Coastguard Worker    if (modes) {
234*61046927SAndroid Build Coastguard Worker       if (dim < 3) {
235*61046927SAndroid Build Coastguard Worker          (void) memcpy(modes, __glXDefaultPixelStore + 4, 20);
236*61046927SAndroid Build Coastguard Worker       }
237*61046927SAndroid Build Coastguard Worker       else {
238*61046927SAndroid Build Coastguard Worker          (void) memcpy(modes, __glXDefaultPixelStore + 0, 36);
239*61046927SAndroid Build Coastguard Worker       }
240*61046927SAndroid Build Coastguard Worker    }
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker /*
244*61046927SAndroid Build Coastguard Worker ** Empty a bitmap in LSB_FIRST=GL_FALSE and ALIGNMENT=4 format packing it
245*61046927SAndroid Build Coastguard Worker ** into the clients memory using the pixel store PACK modes.
246*61046927SAndroid Build Coastguard Worker */
247*61046927SAndroid Build Coastguard Worker static void
EmptyBitmap(struct glx_context * gc,GLint width,GLint height,GLenum format,const GLubyte * sourceImage,GLvoid * userdata)248*61046927SAndroid Build Coastguard Worker EmptyBitmap(struct glx_context * gc, GLint width, GLint height,
249*61046927SAndroid Build Coastguard Worker             GLenum format, const GLubyte * sourceImage, GLvoid * userdata)
250*61046927SAndroid Build Coastguard Worker {
251*61046927SAndroid Build Coastguard Worker    const __GLXattribute *state = gc->client_state_private;
252*61046927SAndroid Build Coastguard Worker    GLint rowLength = state->storePack.rowLength;
253*61046927SAndroid Build Coastguard Worker    GLint alignment = state->storePack.alignment;
254*61046927SAndroid Build Coastguard Worker    GLint skipPixels = state->storePack.skipPixels;
255*61046927SAndroid Build Coastguard Worker    GLint skipRows = state->storePack.skipRows;
256*61046927SAndroid Build Coastguard Worker    GLint lsbFirst = state->storePack.lsbFirst;
257*61046927SAndroid Build Coastguard Worker    GLint components, groupsPerRow, rowSize, padding, elementsPerRow;
258*61046927SAndroid Build Coastguard Worker    GLint sourceRowSize, sourcePadding, sourceSkip;
259*61046927SAndroid Build Coastguard Worker    GLubyte *start, *iter;
260*61046927SAndroid Build Coastguard Worker    GLint elementsLeft, bitOffset, currentByte, highBitMask, lowBitMask;
261*61046927SAndroid Build Coastguard Worker    GLint writeMask, i;
262*61046927SAndroid Build Coastguard Worker    GLubyte writeByte;
263*61046927SAndroid Build Coastguard Worker 
264*61046927SAndroid Build Coastguard Worker    components = __glElementsPerGroup(format, GL_BITMAP);
265*61046927SAndroid Build Coastguard Worker    if (rowLength > 0) {
266*61046927SAndroid Build Coastguard Worker       groupsPerRow = rowLength;
267*61046927SAndroid Build Coastguard Worker    }
268*61046927SAndroid Build Coastguard Worker    else {
269*61046927SAndroid Build Coastguard Worker       groupsPerRow = width;
270*61046927SAndroid Build Coastguard Worker    }
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker    rowSize = (groupsPerRow * components + 7) >> 3;
273*61046927SAndroid Build Coastguard Worker    padding = (rowSize % alignment);
274*61046927SAndroid Build Coastguard Worker    if (padding) {
275*61046927SAndroid Build Coastguard Worker       rowSize += alignment - padding;
276*61046927SAndroid Build Coastguard Worker    }
277*61046927SAndroid Build Coastguard Worker    sourceRowSize = (width * components + 7) >> 3;
278*61046927SAndroid Build Coastguard Worker    sourcePadding = (sourceRowSize % 4);
279*61046927SAndroid Build Coastguard Worker    if (sourcePadding) {
280*61046927SAndroid Build Coastguard Worker       sourceSkip = 4 - sourcePadding;
281*61046927SAndroid Build Coastguard Worker    }
282*61046927SAndroid Build Coastguard Worker    else {
283*61046927SAndroid Build Coastguard Worker       sourceSkip = 0;
284*61046927SAndroid Build Coastguard Worker    }
285*61046927SAndroid Build Coastguard Worker    start = ((GLubyte *) userdata) + skipRows * rowSize +
286*61046927SAndroid Build Coastguard Worker       ((skipPixels * components) >> 3);
287*61046927SAndroid Build Coastguard Worker    bitOffset = (skipPixels * components) & 7;
288*61046927SAndroid Build Coastguard Worker    highBitMask = LowBitsMask[8 - bitOffset];
289*61046927SAndroid Build Coastguard Worker    lowBitMask = HighBitsMask[bitOffset];
290*61046927SAndroid Build Coastguard Worker    elementsPerRow = width * components;
291*61046927SAndroid Build Coastguard Worker    for (i = 0; i < height; i++) {
292*61046927SAndroid Build Coastguard Worker       elementsLeft = elementsPerRow;
293*61046927SAndroid Build Coastguard Worker       iter = start;
294*61046927SAndroid Build Coastguard Worker       writeMask = highBitMask;
295*61046927SAndroid Build Coastguard Worker       writeByte = 0;
296*61046927SAndroid Build Coastguard Worker       while (elementsLeft) {
297*61046927SAndroid Build Coastguard Worker          /* Set up writeMask (to write to current byte) */
298*61046927SAndroid Build Coastguard Worker          if (elementsLeft + bitOffset < 8) {
299*61046927SAndroid Build Coastguard Worker             /* Need to trim writeMask */
300*61046927SAndroid Build Coastguard Worker             writeMask &= HighBitsMask[bitOffset + elementsLeft];
301*61046927SAndroid Build Coastguard Worker          }
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker          if (lsbFirst) {
304*61046927SAndroid Build Coastguard Worker             currentByte = MsbToLsbTable[iter[0]];
305*61046927SAndroid Build Coastguard Worker          }
306*61046927SAndroid Build Coastguard Worker          else {
307*61046927SAndroid Build Coastguard Worker             currentByte = iter[0];
308*61046927SAndroid Build Coastguard Worker          }
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker          if (bitOffset) {
311*61046927SAndroid Build Coastguard Worker             writeByte |= (sourceImage[0] >> bitOffset);
312*61046927SAndroid Build Coastguard Worker             currentByte = (currentByte & ~writeMask) |
313*61046927SAndroid Build Coastguard Worker                (writeByte & writeMask);
314*61046927SAndroid Build Coastguard Worker             writeByte = (sourceImage[0] << (8 - bitOffset));
315*61046927SAndroid Build Coastguard Worker          }
316*61046927SAndroid Build Coastguard Worker          else {
317*61046927SAndroid Build Coastguard Worker             currentByte = (currentByte & ~writeMask) |
318*61046927SAndroid Build Coastguard Worker                (sourceImage[0] & writeMask);
319*61046927SAndroid Build Coastguard Worker          }
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker          if (lsbFirst) {
322*61046927SAndroid Build Coastguard Worker             iter[0] = MsbToLsbTable[currentByte];
323*61046927SAndroid Build Coastguard Worker          }
324*61046927SAndroid Build Coastguard Worker          else {
325*61046927SAndroid Build Coastguard Worker             iter[0] = currentByte;
326*61046927SAndroid Build Coastguard Worker          }
327*61046927SAndroid Build Coastguard Worker 
328*61046927SAndroid Build Coastguard Worker          if (elementsLeft >= 8) {
329*61046927SAndroid Build Coastguard Worker             elementsLeft -= 8;
330*61046927SAndroid Build Coastguard Worker          }
331*61046927SAndroid Build Coastguard Worker          else {
332*61046927SAndroid Build Coastguard Worker             elementsLeft = 0;
333*61046927SAndroid Build Coastguard Worker          }
334*61046927SAndroid Build Coastguard Worker          sourceImage++;
335*61046927SAndroid Build Coastguard Worker          iter++;
336*61046927SAndroid Build Coastguard Worker          writeMask = 0xff;
337*61046927SAndroid Build Coastguard Worker       }
338*61046927SAndroid Build Coastguard Worker       if (writeByte) {
339*61046927SAndroid Build Coastguard Worker          /* Some data left over that still needs writing */
340*61046927SAndroid Build Coastguard Worker          writeMask &= lowBitMask;
341*61046927SAndroid Build Coastguard Worker          if (lsbFirst) {
342*61046927SAndroid Build Coastguard Worker             currentByte = MsbToLsbTable[iter[0]];
343*61046927SAndroid Build Coastguard Worker          }
344*61046927SAndroid Build Coastguard Worker          else {
345*61046927SAndroid Build Coastguard Worker             currentByte = iter[0];
346*61046927SAndroid Build Coastguard Worker          }
347*61046927SAndroid Build Coastguard Worker          currentByte = (currentByte & ~writeMask) | (writeByte & writeMask);
348*61046927SAndroid Build Coastguard Worker          if (lsbFirst) {
349*61046927SAndroid Build Coastguard Worker             iter[0] = MsbToLsbTable[currentByte];
350*61046927SAndroid Build Coastguard Worker          }
351*61046927SAndroid Build Coastguard Worker          else {
352*61046927SAndroid Build Coastguard Worker             iter[0] = currentByte;
353*61046927SAndroid Build Coastguard Worker          }
354*61046927SAndroid Build Coastguard Worker       }
355*61046927SAndroid Build Coastguard Worker       start += rowSize;
356*61046927SAndroid Build Coastguard Worker       sourceImage += sourceSkip;
357*61046927SAndroid Build Coastguard Worker    }
358*61046927SAndroid Build Coastguard Worker }
359*61046927SAndroid Build Coastguard Worker 
360*61046927SAndroid Build Coastguard Worker /*
361*61046927SAndroid Build Coastguard Worker ** Insert array into user's data applying all pixel store modes.
362*61046927SAndroid Build Coastguard Worker ** The packed array format from the server is LSB_FIRST = FALSE,
363*61046927SAndroid Build Coastguard Worker ** SWAP_BYTES = the current pixel storage pack mode, and ALIGNMENT = 4.
364*61046927SAndroid Build Coastguard Worker ** Named __glEmptyImage() because it is the opposite of __glFillImage().
365*61046927SAndroid Build Coastguard Worker */
366*61046927SAndroid Build Coastguard Worker /* ARGSUSED */
367*61046927SAndroid Build Coastguard Worker void
__glEmptyImage(struct glx_context * gc,GLint dim,GLint width,GLint height,GLint depth,GLenum format,GLenum type,const GLubyte * sourceImage,GLvoid * userdata)368*61046927SAndroid Build Coastguard Worker __glEmptyImage(struct glx_context * gc, GLint dim, GLint width, GLint height,
369*61046927SAndroid Build Coastguard Worker                GLint depth, GLenum format, GLenum type,
370*61046927SAndroid Build Coastguard Worker                const GLubyte * sourceImage, GLvoid * userdata)
371*61046927SAndroid Build Coastguard Worker {
372*61046927SAndroid Build Coastguard Worker    const __GLXattribute *state = gc->client_state_private;
373*61046927SAndroid Build Coastguard Worker    GLint rowLength = state->storePack.rowLength;
374*61046927SAndroid Build Coastguard Worker    GLint imageHeight = state->storePack.imageHeight;
375*61046927SAndroid Build Coastguard Worker    GLint alignment = state->storePack.alignment;
376*61046927SAndroid Build Coastguard Worker    GLint skipPixels = state->storePack.skipPixels;
377*61046927SAndroid Build Coastguard Worker    GLint skipRows = state->storePack.skipRows;
378*61046927SAndroid Build Coastguard Worker    GLint skipImages = state->storePack.skipImages;
379*61046927SAndroid Build Coastguard Worker    GLint components, elementSize, rowSize, padding, groupsPerRow, groupSize;
380*61046927SAndroid Build Coastguard Worker    GLint elementsPerRow, sourceRowSize, sourcePadding, h, i;
381*61046927SAndroid Build Coastguard Worker    GLint imageSize, rowsPerImage;
382*61046927SAndroid Build Coastguard Worker    GLubyte *start, *iter, *itera;
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker    if (type == GL_BITMAP) {
385*61046927SAndroid Build Coastguard Worker       EmptyBitmap(gc, width, height, format, sourceImage, userdata);
386*61046927SAndroid Build Coastguard Worker    }
387*61046927SAndroid Build Coastguard Worker    else {
388*61046927SAndroid Build Coastguard Worker       components = __glElementsPerGroup(format, type);
389*61046927SAndroid Build Coastguard Worker       if (rowLength > 0) {
390*61046927SAndroid Build Coastguard Worker          groupsPerRow = rowLength;
391*61046927SAndroid Build Coastguard Worker       }
392*61046927SAndroid Build Coastguard Worker       else {
393*61046927SAndroid Build Coastguard Worker          groupsPerRow = width;
394*61046927SAndroid Build Coastguard Worker       }
395*61046927SAndroid Build Coastguard Worker       if (imageHeight > 0) {
396*61046927SAndroid Build Coastguard Worker          rowsPerImage = imageHeight;
397*61046927SAndroid Build Coastguard Worker       }
398*61046927SAndroid Build Coastguard Worker       else {
399*61046927SAndroid Build Coastguard Worker          rowsPerImage = height;
400*61046927SAndroid Build Coastguard Worker       }
401*61046927SAndroid Build Coastguard Worker       elementSize = __glBytesPerElement(type);
402*61046927SAndroid Build Coastguard Worker       groupSize = elementSize * components;
403*61046927SAndroid Build Coastguard Worker       rowSize = groupsPerRow * groupSize;
404*61046927SAndroid Build Coastguard Worker       padding = (rowSize % alignment);
405*61046927SAndroid Build Coastguard Worker       if (padding) {
406*61046927SAndroid Build Coastguard Worker          rowSize += alignment - padding;
407*61046927SAndroid Build Coastguard Worker       }
408*61046927SAndroid Build Coastguard Worker       sourceRowSize = width * groupSize;
409*61046927SAndroid Build Coastguard Worker       sourcePadding = (sourceRowSize % 4);
410*61046927SAndroid Build Coastguard Worker       if (sourcePadding) {
411*61046927SAndroid Build Coastguard Worker          sourceRowSize += 4 - sourcePadding;
412*61046927SAndroid Build Coastguard Worker       }
413*61046927SAndroid Build Coastguard Worker       imageSize = sourceRowSize * rowsPerImage;
414*61046927SAndroid Build Coastguard Worker       start = ((GLubyte *) userdata) + skipImages * imageSize +
415*61046927SAndroid Build Coastguard Worker          skipRows * rowSize + skipPixels * groupSize;
416*61046927SAndroid Build Coastguard Worker       elementsPerRow = width * components;
417*61046927SAndroid Build Coastguard Worker 
418*61046927SAndroid Build Coastguard Worker       itera = start;
419*61046927SAndroid Build Coastguard Worker       for (h = 0; h < depth; h++) {
420*61046927SAndroid Build Coastguard Worker          if ((rowSize == sourceRowSize) && (sourcePadding == 0)) {
421*61046927SAndroid Build Coastguard Worker             /* Ha!  This is mondo easy! */
422*61046927SAndroid Build Coastguard Worker             __GLX_MEM_COPY(itera, sourceImage,
423*61046927SAndroid Build Coastguard Worker                            elementsPerRow * elementSize * height);
424*61046927SAndroid Build Coastguard Worker             sourceImage += elementsPerRow * elementSize * height;
425*61046927SAndroid Build Coastguard Worker          }
426*61046927SAndroid Build Coastguard Worker          else {
427*61046927SAndroid Build Coastguard Worker             iter = itera;
428*61046927SAndroid Build Coastguard Worker             for (i = 0; i < height; i++) {
429*61046927SAndroid Build Coastguard Worker                __GLX_MEM_COPY(iter, sourceImage,
430*61046927SAndroid Build Coastguard Worker                               elementsPerRow * elementSize);
431*61046927SAndroid Build Coastguard Worker                sourceImage += sourceRowSize;
432*61046927SAndroid Build Coastguard Worker                iter += rowSize;
433*61046927SAndroid Build Coastguard Worker             }
434*61046927SAndroid Build Coastguard Worker          }
435*61046927SAndroid Build Coastguard Worker          itera += imageSize;
436*61046927SAndroid Build Coastguard Worker       }
437*61046927SAndroid Build Coastguard Worker    }
438*61046927SAndroid Build Coastguard Worker }
439