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