From 6b89caf030b6b22d9531cea0bcc9f94c9ef5b674 Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Sun, 19 Dec 2004 15:14:22 +0000 Subject: [PATCH] little endian fixes to gamma handling code --- SheepShaver/src/include/video.h | 4 +- SheepShaver/src/include/video_defs.h | 21 ++-- SheepShaver/src/video.cpp | 163 +++++++++++++-------------- 3 files changed, 95 insertions(+), 93 deletions(-) diff --git a/SheepShaver/src/include/video.h b/SheepShaver/src/include/video.h index f45fea1d..af03c257 100644 --- a/SheepShaver/src/include/video.h +++ b/SheepShaver/src/include/video.h @@ -108,14 +108,12 @@ extern rgb_color mac_pal[256]; extern uint8 remap_mac_be[256]; extern uint8 MacCursor[68]; -struct GammaTbl; - struct VidLocals{ uint16 saveMode; uint32 saveData; uint16 savePage; uint32 saveBaseAddr; - GammaTbl *gammaTable; // Current gamma table + uint32 gammaTable; // Mac address of gamma tble uint32 maxGammaTableSize; // Biggest gamma table allocated uint32 saveVidParms; bool luminanceMapping; // Luminance mapping on/off diff --git a/SheepShaver/src/include/video_defs.h b/SheepShaver/src/include/video_defs.h index ab7cd1ee..c0698552 100644 --- a/SheepShaver/src/include/video_defs.h +++ b/SheepShaver/src/include/video_defs.h @@ -216,6 +216,10 @@ enum { // VDSetEntry struct csCount = 6 }; +enum { // VDGammaRecord + csGTable = 0 +}; + enum { // ColorSpec table entry csValue = 0, csRed = 2, @@ -281,14 +285,15 @@ enum { // VDDrawHardwareCursor/VDHardwareCursorDrawState struct csCursorSet = 12 }; -struct GammaTbl { - uint16 gVersion; - uint16 gType; - uint16 gFormulaSize; - uint16 gChanCnt; - uint16 gDataCnt; - uint16 gDataWidth; - uint16 gFormulaData[1]; +enum { // struct GammaTbl + gVersion = 0, + gType = 2, + gFormulaSize = 4, + gChanCnt = 6, + gDataCnt = 8, + gDataWidth = 10, + gFormulaData = 12, // variable size + SIZEOF_GammaTbl = 12 }; enum { diff --git a/SheepShaver/src/video.cpp b/SheepShaver/src/video.cpp index c47311a3..2cbb9261 100644 --- a/SheepShaver/src/video.cpp +++ b/SheepShaver/src/video.cpp @@ -156,15 +156,15 @@ static int16 VideoOpen(uint32 pb, VidLocals *csSave) csSave->saveMode = VModes[cur_mode].viAppleMode; csSave->savePage = 0; csSave->saveVidParms = 0; // Add the right table - csSave->gammaTable = NULL; // No gamma table yet - csSave->maxGammaTableSize = 0; csSave->luminanceMapping = false; csSave->cursorX = 0; csSave->cursorY = 0; csSave->cursorVisible = 0; csSave->cursorSet = 0; - // Activate default gamma table + // Find and set default gamma table + csSave->gammaTable = 0; + csSave->maxGammaTableSize = 0; set_gamma(csSave, 0); // Install and activate interrupt service @@ -182,83 +182,68 @@ static int16 VideoOpen(uint32 pb, VidLocals *csSave) * Video driver control routine */ +static bool allocate_gamma_table(VidLocals *csSave, uint32 size) +{ + if (size > csSave->maxGammaTableSize) { + if (csSave->gammaTable) { + Mac_sysfree(csSave->gammaTable); + csSave->gammaTable = 0; + csSave->maxGammaTableSize = 0; + } + if ((csSave->gammaTable = Mac_sysalloc(size)) == 0) + return false; + csSave->maxGammaTableSize = size; + } + return true; +} + static int16 set_gamma(VidLocals *csSave, uint32 gamma) { -#warning "FIXME: this code is not little endian aware" - GammaTbl *clientGamma = (GammaTbl *)gamma; - GammaTbl *gammaTable = csSave->gammaTable; + return paramErr; - if (clientGamma == NULL) { + if (gamma == 0) { // Build linear ramp, 256 entries - // No gamma table supplied, build linear ramp - uint32 linearRampSize = sizeof(GammaTbl) + 256 - 2; - uint8 *correctionData; + // Allocate new table, if necessary + if (!allocate_gamma_table(csSave, SIZEOF_GammaTbl + 256)) + return memFullErr; - // Allocate new gamma table if existing gamma table is smaller than required. - if (linearRampSize > csSave->maxGammaTableSize) { - delete[] csSave->gammaTable; - csSave->gammaTable = (GammaTbl *)new uint8[linearRampSize]; - csSave->maxGammaTableSize = linearRampSize; - gammaTable = csSave->gammaTable; - } - - gammaTable->gVersion = 0; // A version 0 style of the GammaTbl structure - gammaTable->gType = 0; // Frame buffer hardware invariant - gammaTable->gFormulaSize = 0; // No formula data, just correction data - gammaTable->gChanCnt = 1; // Apply same correction to Red, Green, & Blue - gammaTable->gDataCnt = 256; // gDataCnt == 2^^gDataWidth - gammaTable->gDataWidth = 8; // 8 bits of significant data per entry - - // Find the starting address of the correction data. This can be computed by starting at - // the address of gFormula[0] and adding the gFormulaSize. - correctionData = (uint8 *)((uint32)&gammaTable->gFormulaData[0] + gammaTable->gFormulaSize); + // Initialize header + WriteMacInt16(csSave->gammaTable + gVersion, 0); // A version 0 style of the GammaTbl structure + WriteMacInt16(csSave->gammaTable + gType, 0); // Frame buffer hardware invariant + WriteMacInt16(csSave->gammaTable + gFormulaSize, 0); // No formula data, just correction data + WriteMacInt16(csSave->gammaTable + gChanCnt, 1); // Apply same correction to Red, Green, & Blue + WriteMacInt16(csSave->gammaTable + gDataCnt, 256); // gDataCnt == 2^^gDataWidth + WriteMacInt16(csSave->gammaTable + gDataWidth, 8); // 8 bits of significant data per entry // Build the linear ramp - for (int i=0; igDataCnt; i++) - *correctionData++ = i; + uint32 p = csSave->gammaTable + gFormulaData; + for (int i=0; i<256; i++) + WriteMacInt8(p + i, i); - } else { + } else { // User-supplied gamma table - // User supplied a gamma table, so make sure it is a valid one - if (clientGamma->gVersion != 0) + // Validate header + if (ReadMacInt16(gamma + gVersion) != 0) return paramErr; - if (clientGamma->gType != 0) + if (ReadMacInt16(gamma + gType) != 0) return paramErr; - if ((clientGamma->gChanCnt != 1) && (clientGamma->gChanCnt != 3)) + int chan_cnt = ReadMacInt16(gamma + gChanCnt); + if (chan_cnt != 1 && chan_cnt != 3) return paramErr; - if (clientGamma->gDataWidth > 8) + int data_width = ReadMacInt16(gamma + gDataWidth); + if (data_width > 8) return paramErr; - if (clientGamma->gDataCnt != (1 << clientGamma->gDataWidth)) + int data_cnt = ReadMacInt16(gamma + gDataWidth); + if (data_cnt != (1 << data_width)) return paramErr; - uint32 tableSize = sizeof(GammaTbl) // fixed size header - + clientGamma->gFormulaSize // add formula size - + clientGamma->gChanCnt * clientGamma->gDataCnt // assume 1 byte/entry - - 2; // correct gFormulaData[0] counted twice + // Allocate new table, if necessary + int size = SIZEOF_GammaTbl + ReadMacInt16(gamma + gFormulaSize) + chan_cnt * data_cnt; + if (!allocate_gamma_table(csSave, size)) + return memFullErr; - // Allocate new gamma table if existing gamma table is smaller than required. - if (tableSize > csSave->maxGammaTableSize) { - delete[] csSave->gammaTable; - csSave->gammaTable = (GammaTbl *)new uint8[tableSize]; - csSave->maxGammaTableSize = tableSize; - gammaTable = csSave->gammaTable; - } - - // Copy gamma table header - *gammaTable = *clientGamma; - - // Copy the formula data (if any) - uint8 *newData = (uint8 *)&gammaTable->gFormulaData[0]; // Point to newGamma's formula data - uint8 *clientData = (uint8 *)&clientGamma->gFormulaData[0]; // Point to clientGamma's formula data - for (int i=0; igFormulaSize; i++) - *newData++ = *clientData++; - - // Copy the correction data. Convientiently, after copying the formula data, the 'newData' - // pointer and the 'clientData' pointer are pointing to the their respective starting points - // of their correction data. - for (int i=0; igChanCnt; i++) - for (int j=0; jgDataCnt; j++) - *newData++ = *clientData++; + // Copy table + Mac2Mac_memcpy(csSave->gammaTable, gamma, size); } return noErr; } @@ -299,16 +284,26 @@ static int16 VideoControl(uint32 pb, VidLocals *csSave) uint8 *green_gamma = NULL; uint8 *blue_gamma = NULL; int gamma_data_width = 0; - if (display_type == DIS_SCREEN && csSave->gammaTable != NULL) { // Windows are gamma-corrected by BeOS - do_gamma = true; - GammaTbl *gamma = csSave->gammaTable; - gamma_data_width = gamma->gDataWidth; - red_gamma = (uint8 *)&gamma->gFormulaData + gamma->gFormulaSize; - if (gamma->gChanCnt == 1) { - green_gamma = blue_gamma = red_gamma; - } else { - green_gamma = red_gamma + gamma->gDataCnt; - blue_gamma = red_gamma + 2 * gamma->gDataCnt; + if (csSave->gammaTable) { +#ifdef __BEOS__ + // Windows are gamma-corrected by BeOS + const bool can_do_gamma = (display_type == DIS_SCREEN); +#else + const bool can_do_gamma = true; +#endif + if (can_do_gamma) { + uint32 gamma_table = csSave->gammaTable; + red_gamma = Mac2HostAddr(gamma_table + gFormulaData + ReadMacInt16(gamma_table + gFormulaSize)); + int chan_cnt = ReadMacInt16(gamma_table + gChanCnt); + if (chan_cnt == 1) + green_gamma = blue_gamma = red_gamma; + else { + int ofs = ReadMacInt16(gamma_table + gDataCnt); + green_gamma = red_gamma + ofs; + blue_gamma = green_gamma + ofs; + } + gamma_data_width = ReadMacInt16(gamma_table + gDataWidth); + do_gamma = true; } } @@ -356,9 +351,11 @@ static int16 VideoControl(uint32 pb, VidLocals *csSave) return noErr; } - case cscSetGamma: // SetGamma - D(bug("SetGamma\n")); - return set_gamma(csSave, ReadMacInt32(param)); + case cscSetGamma: { // SetGamma + uint32 user_table = ReadMacInt32(param + csGTable); + D(bug("SetGamma %08x\n", user_table)); + return set_gamma(csSave, ReadMacInt32(user_table)); + } case cscGrayPage: { // GrayPage D(bug("GrayPage %d\n", ReadMacInt16(param + csPage))); @@ -885,8 +882,10 @@ int16 VideoDoDriverIO(uint32 spaceID, uint32 commandID, uint32 commandContents, switch (commandCode) { case kInitializeCommand: case kReplaceCommand: - if (private_data != NULL) // Might be left over from a reboot - delete private_data->gammaTable; + if (private_data != NULL) { // Might be left over from a reboot + if (private_data->gammaTable) + Mac_sysfree(private_data->gammaTable); + } delete private_data; iocic_tvect = FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete"); @@ -926,15 +925,15 @@ int16 VideoDoDriverIO(uint32 spaceID, uint32 commandID, uint32 commandContents, } private_data = new VidLocals; - private_data->gammaTable = NULL; + private_data->gammaTable = 0; Mac2Host_memcpy(&private_data->regEntryID, commandContents + 2, 16); // DriverInitInfo.deviceEntry private_data->interruptsEnabled = false; // Disable interrupts break; case kFinalizeCommand: case kSupersededCommand: - if (private_data != NULL) - delete private_data->gammaTable; + if (private_data != NULL && private_data->gammaTable) + Mac_sysfree(private_data->gammaTable); delete private_data; private_data = NULL; break;