1848b8605Smrg/* 2848b8605Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) 3848b8605Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. 4848b8605Smrg * 5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6848b8605Smrg * copy of this software and associated documentation files (the "Software"), 7848b8605Smrg * to deal in the Software without restriction, including without limitation 8848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 10848b8605Smrg * Software is furnished to do so, subject to the following conditions: 11848b8605Smrg * 12848b8605Smrg * The above copyright notice including the dates of first publication and 13848b8605Smrg * either this permission notice or a reference to 14848b8605Smrg * http://oss.sgi.com/projects/FreeB/ 15848b8605Smrg * shall be included in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21848b8605Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22848b8605Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23848b8605Smrg * SOFTWARE. 24848b8605Smrg * 25848b8605Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc. 26848b8605Smrg * shall not be used in advertising or otherwise to promote the sale, use or 27848b8605Smrg * other dealings in this Software without prior written authorization from 28848b8605Smrg * Silicon Graphics, Inc. 29848b8605Smrg */ 30848b8605Smrg 31848b8605Smrg#include "packrender.h" 32848b8605Smrg 33848b8605Smrgstatic const GLubyte MsbToLsbTable[256] = { 34848b8605Smrg 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 35848b8605Smrg 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 36848b8605Smrg 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 37848b8605Smrg 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 38848b8605Smrg 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 39848b8605Smrg 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 40848b8605Smrg 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 41848b8605Smrg 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 42848b8605Smrg 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 43848b8605Smrg 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 44848b8605Smrg 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 45848b8605Smrg 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 46848b8605Smrg 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 47848b8605Smrg 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 48848b8605Smrg 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 49848b8605Smrg 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 50848b8605Smrg 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 51848b8605Smrg 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 52848b8605Smrg 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 53848b8605Smrg 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 54848b8605Smrg 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 55848b8605Smrg 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 56848b8605Smrg 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 57848b8605Smrg 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 58848b8605Smrg 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 59848b8605Smrg 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 60848b8605Smrg 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 61848b8605Smrg 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 62848b8605Smrg 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 63848b8605Smrg 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 64848b8605Smrg 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 65848b8605Smrg 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 66848b8605Smrg}; 67848b8605Smrg 68848b8605Smrgstatic const GLubyte LowBitsMask[9] = { 69848b8605Smrg 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 70848b8605Smrg}; 71848b8605Smrg 72848b8605Smrgstatic const GLubyte HighBitsMask[9] = { 73848b8605Smrg 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 74848b8605Smrg}; 75848b8605Smrg 76848b8605Smrg 77848b8605Smrg/* 78848b8605Smrg** Copy bitmap data from clients packed memory applying unpacking modes as the 79848b8605Smrg** data is transfered into the destImage buffer. Return in modes the 80848b8605Smrg** set of pixel modes that are to be done by the server. 81848b8605Smrg*/ 82848b8605Smrgstatic void 83848b8605SmrgFillBitmap(struct glx_context * gc, GLint width, GLint height, 84848b8605Smrg GLenum format, const GLvoid * userdata, GLubyte * destImage) 85848b8605Smrg{ 86848b8605Smrg const __GLXattribute *state = gc->client_state_private; 87848b8605Smrg GLint rowLength = state->storeUnpack.rowLength; 88848b8605Smrg GLint alignment = state->storeUnpack.alignment; 89848b8605Smrg GLint skipPixels = state->storeUnpack.skipPixels; 90848b8605Smrg GLint skipRows = state->storeUnpack.skipRows; 91848b8605Smrg GLint lsbFirst = state->storeUnpack.lsbFirst; 92848b8605Smrg GLint elementsLeft, bitOffset, currentByte, nextByte, highBitMask; 93848b8605Smrg GLint lowBitMask, i; 94848b8605Smrg GLint components, groupsPerRow, rowSize, padding, elementsPerRow; 95848b8605Smrg const GLubyte *start, *iter; 96848b8605Smrg 97848b8605Smrg if (rowLength > 0) { 98848b8605Smrg groupsPerRow = rowLength; 99848b8605Smrg } 100848b8605Smrg else { 101848b8605Smrg groupsPerRow = width; 102848b8605Smrg } 103848b8605Smrg components = __glElementsPerGroup(format, GL_BITMAP); 104848b8605Smrg rowSize = (groupsPerRow * components + 7) >> 3; 105848b8605Smrg padding = (rowSize % alignment); 106848b8605Smrg if (padding) { 107848b8605Smrg rowSize += alignment - padding; 108848b8605Smrg } 109848b8605Smrg start = ((const GLubyte *) userdata) + skipRows * rowSize + 110848b8605Smrg ((skipPixels * components) >> 3); 111848b8605Smrg bitOffset = (skipPixels * components) & 7; 112848b8605Smrg highBitMask = LowBitsMask[8 - bitOffset]; 113848b8605Smrg lowBitMask = HighBitsMask[bitOffset]; 114848b8605Smrg elementsPerRow = width * components; 115848b8605Smrg for (i = 0; i < height; i++) { 116848b8605Smrg elementsLeft = elementsPerRow; 117848b8605Smrg iter = start; 118848b8605Smrg while (elementsLeft) { 119848b8605Smrg /* First retrieve low bits from current byte */ 120848b8605Smrg if (lsbFirst) { 121848b8605Smrg currentByte = MsbToLsbTable[iter[0]]; 122848b8605Smrg } 123848b8605Smrg else { 124848b8605Smrg currentByte = iter[0]; 125848b8605Smrg } 126848b8605Smrg if (bitOffset) { 127848b8605Smrg /* Need to read next byte to finish current byte */ 128848b8605Smrg if (elementsLeft > (8 - bitOffset)) { 129848b8605Smrg if (lsbFirst) { 130848b8605Smrg nextByte = MsbToLsbTable[iter[1]]; 131848b8605Smrg } 132848b8605Smrg else { 133848b8605Smrg nextByte = iter[1]; 134848b8605Smrg } 135848b8605Smrg currentByte = 136848b8605Smrg ((currentByte & highBitMask) << bitOffset) | 137848b8605Smrg ((nextByte & lowBitMask) >> (8 - bitOffset)); 138848b8605Smrg } 139848b8605Smrg else { 140848b8605Smrg currentByte = ((currentByte & highBitMask) << bitOffset); 141848b8605Smrg } 142848b8605Smrg } 143848b8605Smrg if (elementsLeft >= 8) { 144848b8605Smrg *destImage = currentByte; 145848b8605Smrg elementsLeft -= 8; 146848b8605Smrg } 147848b8605Smrg else { 148848b8605Smrg *destImage = currentByte & HighBitsMask[elementsLeft]; 149848b8605Smrg elementsLeft = 0; 150848b8605Smrg } 151848b8605Smrg destImage++; 152848b8605Smrg iter++; 153848b8605Smrg } 154848b8605Smrg start += rowSize; 155848b8605Smrg } 156848b8605Smrg} 157848b8605Smrg 158848b8605Smrg/* 159848b8605Smrg** Extract array from user's data applying all pixel store modes. 160848b8605Smrg** The internal packed array format used has LSB_FIRST = FALSE and 161848b8605Smrg** ALIGNMENT = 1. 162848b8605Smrg*/ 163848b8605Smrgvoid 164848b8605Smrg__glFillImage(struct glx_context * gc, GLint dim, GLint width, GLint height, 165848b8605Smrg GLint depth, GLenum format, GLenum type, 166848b8605Smrg const GLvoid * userdata, GLubyte * newimage, GLubyte * modes) 167848b8605Smrg{ 168848b8605Smrg const __GLXattribute *state = gc->client_state_private; 169848b8605Smrg GLint rowLength = state->storeUnpack.rowLength; 170848b8605Smrg GLint imageHeight = state->storeUnpack.imageHeight; 171848b8605Smrg GLint alignment = state->storeUnpack.alignment; 172848b8605Smrg GLint skipPixels = state->storeUnpack.skipPixels; 173848b8605Smrg GLint skipRows = state->storeUnpack.skipRows; 174848b8605Smrg GLint skipImages = state->storeUnpack.skipImages; 175848b8605Smrg GLint swapBytes = state->storeUnpack.swapEndian; 176848b8605Smrg GLint components, elementSize, rowSize, padding, groupsPerRow, groupSize; 177848b8605Smrg GLint elementsPerRow, imageSize, rowsPerImage, h, i, j, k; 178848b8605Smrg const GLubyte *start, *iter, *itera, *iterb, *iterc; 179848b8605Smrg GLubyte *iter2; 180848b8605Smrg 181848b8605Smrg if (type == GL_BITMAP) { 182848b8605Smrg FillBitmap(gc, width, height, format, userdata, newimage); 183848b8605Smrg } 184848b8605Smrg else { 185848b8605Smrg components = __glElementsPerGroup(format, type); 186848b8605Smrg if (rowLength > 0) { 187848b8605Smrg groupsPerRow = rowLength; 188848b8605Smrg } 189848b8605Smrg else { 190848b8605Smrg groupsPerRow = width; 191848b8605Smrg } 192848b8605Smrg if (imageHeight > 0) { 193848b8605Smrg rowsPerImage = imageHeight; 194848b8605Smrg } 195848b8605Smrg else { 196848b8605Smrg rowsPerImage = height; 197848b8605Smrg } 198848b8605Smrg 199848b8605Smrg elementSize = __glBytesPerElement(type); 200848b8605Smrg groupSize = elementSize * components; 201848b8605Smrg if (elementSize == 1) 202848b8605Smrg swapBytes = 0; 203848b8605Smrg 204848b8605Smrg rowSize = groupsPerRow * groupSize; 205848b8605Smrg padding = (rowSize % alignment); 206848b8605Smrg if (padding) { 207848b8605Smrg rowSize += alignment - padding; 208848b8605Smrg } 209848b8605Smrg imageSize = rowSize * rowsPerImage; 210848b8605Smrg start = ((const GLubyte *) userdata) + skipImages * imageSize + 211848b8605Smrg skipRows * rowSize + skipPixels * groupSize; 212848b8605Smrg iter2 = newimage; 213848b8605Smrg elementsPerRow = width * components; 214848b8605Smrg 215848b8605Smrg if (swapBytes) { 216848b8605Smrg itera = start; 217848b8605Smrg for (h = 0; h < depth; h++) { 218848b8605Smrg iterb = itera; 219848b8605Smrg for (i = 0; i < height; i++) { 220848b8605Smrg iterc = iterb; 221848b8605Smrg for (j = 0; j < elementsPerRow; j++) { 222848b8605Smrg for (k = 1; k <= elementSize; k++) { 223848b8605Smrg iter2[k - 1] = iterc[elementSize - k]; 224848b8605Smrg } 225848b8605Smrg iter2 += elementSize; 226848b8605Smrg iterc += elementSize; 227848b8605Smrg } 228848b8605Smrg iterb += rowSize; 229848b8605Smrg } 230848b8605Smrg itera += imageSize; 231848b8605Smrg } 232848b8605Smrg } 233848b8605Smrg else { 234848b8605Smrg itera = start; 235848b8605Smrg for (h = 0; h < depth; h++) { 236848b8605Smrg if (rowSize == elementsPerRow * elementSize) { 237848b8605Smrg /* Ha! This is mondo easy! */ 238848b8605Smrg __GLX_MEM_COPY(iter2, itera, 239848b8605Smrg elementsPerRow * elementSize * height); 240848b8605Smrg iter2 += elementsPerRow * elementSize * height; 241848b8605Smrg } 242848b8605Smrg else { 243848b8605Smrg iter = itera; 244848b8605Smrg for (i = 0; i < height; i++) { 245848b8605Smrg __GLX_MEM_COPY(iter2, iter, elementsPerRow * elementSize); 246848b8605Smrg iter2 += elementsPerRow * elementSize; 247848b8605Smrg iter += rowSize; 248848b8605Smrg } 249848b8605Smrg } 250848b8605Smrg itera += imageSize; 251848b8605Smrg } 252848b8605Smrg } 253848b8605Smrg } 254848b8605Smrg 255848b8605Smrg /* Setup store modes that describe what we just did */ 256848b8605Smrg if (modes) { 257848b8605Smrg if (dim < 3) { 258848b8605Smrg (void) memcpy(modes, __glXDefaultPixelStore + 4, 20); 259848b8605Smrg } 260848b8605Smrg else { 261848b8605Smrg (void) memcpy(modes, __glXDefaultPixelStore + 0, 36); 262848b8605Smrg } 263848b8605Smrg } 264848b8605Smrg} 265848b8605Smrg 266848b8605Smrg/* 267848b8605Smrg** Empty a bitmap in LSB_FIRST=GL_FALSE and ALIGNMENT=4 format packing it 268848b8605Smrg** into the clients memory using the pixel store PACK modes. 269848b8605Smrg*/ 270848b8605Smrgstatic void 271848b8605SmrgEmptyBitmap(struct glx_context * gc, GLint width, GLint height, 272848b8605Smrg GLenum format, const GLubyte * sourceImage, GLvoid * userdata) 273848b8605Smrg{ 274848b8605Smrg const __GLXattribute *state = gc->client_state_private; 275848b8605Smrg GLint rowLength = state->storePack.rowLength; 276848b8605Smrg GLint alignment = state->storePack.alignment; 277848b8605Smrg GLint skipPixels = state->storePack.skipPixels; 278848b8605Smrg GLint skipRows = state->storePack.skipRows; 279848b8605Smrg GLint lsbFirst = state->storePack.lsbFirst; 280848b8605Smrg GLint components, groupsPerRow, rowSize, padding, elementsPerRow; 281848b8605Smrg GLint sourceRowSize, sourcePadding, sourceSkip; 282848b8605Smrg GLubyte *start, *iter; 283848b8605Smrg GLint elementsLeft, bitOffset, currentByte, highBitMask, lowBitMask; 284848b8605Smrg GLint writeMask, i; 285848b8605Smrg GLubyte writeByte; 286848b8605Smrg 287848b8605Smrg components = __glElementsPerGroup(format, GL_BITMAP); 288848b8605Smrg if (rowLength > 0) { 289848b8605Smrg groupsPerRow = rowLength; 290848b8605Smrg } 291848b8605Smrg else { 292848b8605Smrg groupsPerRow = width; 293848b8605Smrg } 294848b8605Smrg 295848b8605Smrg rowSize = (groupsPerRow * components + 7) >> 3; 296848b8605Smrg padding = (rowSize % alignment); 297848b8605Smrg if (padding) { 298848b8605Smrg rowSize += alignment - padding; 299848b8605Smrg } 300848b8605Smrg sourceRowSize = (width * components + 7) >> 3; 301848b8605Smrg sourcePadding = (sourceRowSize % 4); 302848b8605Smrg if (sourcePadding) { 303848b8605Smrg sourceSkip = 4 - sourcePadding; 304848b8605Smrg } 305848b8605Smrg else { 306848b8605Smrg sourceSkip = 0; 307848b8605Smrg } 308848b8605Smrg start = ((GLubyte *) userdata) + skipRows * rowSize + 309848b8605Smrg ((skipPixels * components) >> 3); 310848b8605Smrg bitOffset = (skipPixels * components) & 7; 311848b8605Smrg highBitMask = LowBitsMask[8 - bitOffset]; 312848b8605Smrg lowBitMask = HighBitsMask[bitOffset]; 313848b8605Smrg elementsPerRow = width * components; 314848b8605Smrg for (i = 0; i < height; i++) { 315848b8605Smrg elementsLeft = elementsPerRow; 316848b8605Smrg iter = start; 317848b8605Smrg writeMask = highBitMask; 318848b8605Smrg writeByte = 0; 319848b8605Smrg while (elementsLeft) { 320848b8605Smrg /* Set up writeMask (to write to current byte) */ 321848b8605Smrg if (elementsLeft + bitOffset < 8) { 322848b8605Smrg /* Need to trim writeMask */ 323848b8605Smrg writeMask &= HighBitsMask[bitOffset + elementsLeft]; 324848b8605Smrg } 325848b8605Smrg 326848b8605Smrg if (lsbFirst) { 327848b8605Smrg currentByte = MsbToLsbTable[iter[0]]; 328848b8605Smrg } 329848b8605Smrg else { 330848b8605Smrg currentByte = iter[0]; 331848b8605Smrg } 332848b8605Smrg 333848b8605Smrg if (bitOffset) { 334848b8605Smrg writeByte |= (sourceImage[0] >> bitOffset); 335848b8605Smrg currentByte = (currentByte & ~writeMask) | 336848b8605Smrg (writeByte & writeMask); 337848b8605Smrg writeByte = (sourceImage[0] << (8 - bitOffset)); 338848b8605Smrg } 339848b8605Smrg else { 340848b8605Smrg currentByte = (currentByte & ~writeMask) | 341848b8605Smrg (sourceImage[0] & writeMask); 342848b8605Smrg } 343848b8605Smrg 344848b8605Smrg if (lsbFirst) { 345848b8605Smrg iter[0] = MsbToLsbTable[currentByte]; 346848b8605Smrg } 347848b8605Smrg else { 348848b8605Smrg iter[0] = currentByte; 349848b8605Smrg } 350848b8605Smrg 351848b8605Smrg if (elementsLeft >= 8) { 352848b8605Smrg elementsLeft -= 8; 353848b8605Smrg } 354848b8605Smrg else { 355848b8605Smrg elementsLeft = 0; 356848b8605Smrg } 357848b8605Smrg sourceImage++; 358848b8605Smrg iter++; 359848b8605Smrg writeMask = 0xff; 360848b8605Smrg } 361848b8605Smrg if (writeByte) { 362848b8605Smrg /* Some data left over that still needs writing */ 363848b8605Smrg writeMask &= lowBitMask; 364848b8605Smrg if (lsbFirst) { 365848b8605Smrg currentByte = MsbToLsbTable[iter[0]]; 366848b8605Smrg } 367848b8605Smrg else { 368848b8605Smrg currentByte = iter[0]; 369848b8605Smrg } 370848b8605Smrg currentByte = (currentByte & ~writeMask) | (writeByte & writeMask); 371848b8605Smrg if (lsbFirst) { 372848b8605Smrg iter[0] = MsbToLsbTable[currentByte]; 373848b8605Smrg } 374848b8605Smrg else { 375848b8605Smrg iter[0] = currentByte; 376848b8605Smrg } 377848b8605Smrg } 378848b8605Smrg start += rowSize; 379848b8605Smrg sourceImage += sourceSkip; 380848b8605Smrg } 381848b8605Smrg} 382848b8605Smrg 383848b8605Smrg/* 384848b8605Smrg** Insert array into user's data applying all pixel store modes. 385848b8605Smrg** The packed array format from the server is LSB_FIRST = FALSE, 386848b8605Smrg** SWAP_BYTES = the current pixel storage pack mode, and ALIGNMENT = 4. 387848b8605Smrg** Named __glEmptyImage() because it is the opposite of __glFillImage(). 388848b8605Smrg*/ 389848b8605Smrg/* ARGSUSED */ 390848b8605Smrgvoid 391848b8605Smrg__glEmptyImage(struct glx_context * gc, GLint dim, GLint width, GLint height, 392848b8605Smrg GLint depth, GLenum format, GLenum type, 393848b8605Smrg const GLubyte * sourceImage, GLvoid * userdata) 394848b8605Smrg{ 395848b8605Smrg const __GLXattribute *state = gc->client_state_private; 396848b8605Smrg GLint rowLength = state->storePack.rowLength; 397848b8605Smrg GLint imageHeight = state->storePack.imageHeight; 398848b8605Smrg GLint alignment = state->storePack.alignment; 399848b8605Smrg GLint skipPixels = state->storePack.skipPixels; 400848b8605Smrg GLint skipRows = state->storePack.skipRows; 401848b8605Smrg GLint skipImages = state->storePack.skipImages; 402848b8605Smrg GLint components, elementSize, rowSize, padding, groupsPerRow, groupSize; 403848b8605Smrg GLint elementsPerRow, sourceRowSize, sourcePadding, h, i; 404848b8605Smrg GLint imageSize, rowsPerImage; 405848b8605Smrg GLubyte *start, *iter, *itera; 406848b8605Smrg 407848b8605Smrg if (type == GL_BITMAP) { 408848b8605Smrg EmptyBitmap(gc, width, height, format, sourceImage, userdata); 409848b8605Smrg } 410848b8605Smrg else { 411848b8605Smrg components = __glElementsPerGroup(format, type); 412848b8605Smrg if (rowLength > 0) { 413848b8605Smrg groupsPerRow = rowLength; 414848b8605Smrg } 415848b8605Smrg else { 416848b8605Smrg groupsPerRow = width; 417848b8605Smrg } 418848b8605Smrg if (imageHeight > 0) { 419848b8605Smrg rowsPerImage = imageHeight; 420848b8605Smrg } 421848b8605Smrg else { 422848b8605Smrg rowsPerImage = height; 423848b8605Smrg } 424848b8605Smrg elementSize = __glBytesPerElement(type); 425848b8605Smrg groupSize = elementSize * components; 426848b8605Smrg rowSize = groupsPerRow * groupSize; 427848b8605Smrg padding = (rowSize % alignment); 428848b8605Smrg if (padding) { 429848b8605Smrg rowSize += alignment - padding; 430848b8605Smrg } 431848b8605Smrg sourceRowSize = width * groupSize; 432848b8605Smrg sourcePadding = (sourceRowSize % 4); 433848b8605Smrg if (sourcePadding) { 434848b8605Smrg sourceRowSize += 4 - sourcePadding; 435848b8605Smrg } 436848b8605Smrg imageSize = sourceRowSize * rowsPerImage; 437848b8605Smrg start = ((GLubyte *) userdata) + skipImages * imageSize + 438848b8605Smrg skipRows * rowSize + skipPixels * groupSize; 439848b8605Smrg elementsPerRow = width * components; 440848b8605Smrg 441848b8605Smrg itera = start; 442848b8605Smrg for (h = 0; h < depth; h++) { 443848b8605Smrg if ((rowSize == sourceRowSize) && (sourcePadding == 0)) { 444848b8605Smrg /* Ha! This is mondo easy! */ 445848b8605Smrg __GLX_MEM_COPY(itera, sourceImage, 446848b8605Smrg elementsPerRow * elementSize * height); 447848b8605Smrg sourceImage += elementsPerRow * elementSize * height; 448848b8605Smrg } 449848b8605Smrg else { 450848b8605Smrg iter = itera; 451848b8605Smrg for (i = 0; i < height; i++) { 452848b8605Smrg __GLX_MEM_COPY(iter, sourceImage, 453848b8605Smrg elementsPerRow * elementSize); 454848b8605Smrg sourceImage += sourceRowSize; 455848b8605Smrg iter += rowSize; 456848b8605Smrg } 457848b8605Smrg } 458848b8605Smrg itera += imageSize; 459848b8605Smrg } 460848b8605Smrg } 461848b8605Smrg} 462