John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1 | // SwiftShader Software Renderer |
| 2 | // |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 3 | // Copyright(c) 2005-2012 TransGaming Inc. |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 4 | // |
| 5 | // All rights reserved. No part of this software may be copied, distributed, transmitted, |
| 6 | // transcribed, stored in a retrieval system, translated into any human or computer |
| 7 | // language by any means, or disclosed to third parties without the explicit written |
| 8 | // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express |
| 9 | // or implied, including but not limited to any patent rights, are granted to you. |
| 10 | // |
| 11 | |
| 12 | #include "FrameBuffer.hpp" |
| 13 | |
| 14 | #include "Timer.hpp" |
| 15 | #include "CPUID.hpp" |
| 16 | #include "serialvalid.h" |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 17 | #include "Register.hpp" |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 18 | #include "Renderer/Surface.hpp" |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 19 | #include "Reactor/Reactor.hpp" |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 20 | #include "Common/Debug.hpp" |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 21 | |
| 22 | #include <stdio.h> |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 23 | #include <string.h> |
| 24 | #include <time.h> |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 25 | |
Nicolas Capens | 135f634 | 2015-11-11 10:49:08 -0500 | [diff] [blame] | 26 | #ifdef __ANDROID__ |
| 27 | #include <cutils/properties.h> |
| 28 | #endif |
| 29 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 30 | #ifndef DISPLAY_LOGO |
Nicolas Capens | 135f634 | 2015-11-11 10:49:08 -0500 | [diff] [blame] | 31 | #define DISPLAY_LOGO ((NDEBUG | __ANDROID__) & 1) |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 32 | #endif |
| 33 | |
| 34 | #define ASYNCHRONOUS_BLIT 0 // FIXME: Currently leads to rare race conditions |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 35 | |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 36 | extern const int logoWidth; |
| 37 | extern const int logoHeight; |
| 38 | extern const unsigned int logoData[]; |
| 39 | |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 40 | namespace sw |
| 41 | { |
| 42 | extern bool forceWindowed; |
| 43 | |
| 44 | Surface *FrameBuffer::logo; |
| 45 | unsigned int *FrameBuffer::logoImage; |
| 46 | void *FrameBuffer::cursor; |
| 47 | int FrameBuffer::cursorWidth = 0; |
| 48 | int FrameBuffer::cursorHeight = 0; |
| 49 | int FrameBuffer::cursorHotspotX; |
| 50 | int FrameBuffer::cursorHotspotY; |
| 51 | int FrameBuffer::cursorPositionX; |
| 52 | int FrameBuffer::cursorPositionY; |
| 53 | int FrameBuffer::cursorX; |
| 54 | int FrameBuffer::cursorY; |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 55 | bool FrameBuffer::topLeftOrigin = false; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 56 | |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 57 | FrameBuffer::FrameBuffer(int width, int height, bool fullscreen, bool topLeftOrigin) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 58 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 59 | this->topLeftOrigin = topLeftOrigin; |
| 60 | |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 61 | locked = 0; |
| 62 | |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 63 | this->width = width; |
| 64 | this->height = height; |
Nicolas Capens | 10219e7 | 2014-05-07 00:17:20 -0400 | [diff] [blame] | 65 | destFormat = FORMAT_X8R8G8B8; |
| 66 | sourceFormat = FORMAT_X8R8G8B8; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 67 | stride = 0; |
| 68 | |
| 69 | if(forceWindowed) |
| 70 | { |
| 71 | fullscreen = false; |
| 72 | } |
| 73 | |
| 74 | windowed = !fullscreen; |
| 75 | |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 76 | blitFunction = 0; |
| 77 | blitRoutine = 0; |
| 78 | |
| 79 | blitState.width = 0; |
| 80 | blitState.height = 0; |
Nicolas Capens | 10219e7 | 2014-05-07 00:17:20 -0400 | [diff] [blame] | 81 | blitState.destFormat = FORMAT_X8R8G8B8; |
| 82 | blitState.sourceFormat = FORMAT_X8R8G8B8; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 83 | blitState.cursorWidth = 0; |
| 84 | blitState.cursorHeight = 0; |
| 85 | |
| 86 | logo = 0; |
| 87 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 88 | if(ASYNCHRONOUS_BLIT) |
| 89 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 90 | terminate = false; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 91 | FrameBuffer *parameters = this; |
| 92 | blitThread = new Thread(threadFunction, ¶meters); |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 93 | } |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 94 | } |
| 95 | |
| 96 | FrameBuffer::~FrameBuffer() |
| 97 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 98 | if(ASYNCHRONOUS_BLIT) |
| 99 | { |
| 100 | terminate = true; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 101 | blitEvent.signal(); |
| 102 | blitThread->join(); |
| 103 | delete blitThread; |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 104 | } |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 105 | |
| 106 | delete blitRoutine; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 107 | } |
| 108 | |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 109 | int FrameBuffer::getWidth() const |
| 110 | { |
| 111 | return width; |
| 112 | } |
| 113 | |
| 114 | int FrameBuffer::getHeight() const |
| 115 | { |
| 116 | return height; |
| 117 | } |
| 118 | |
| 119 | int FrameBuffer::getStride() const |
| 120 | { |
| 121 | return stride; |
| 122 | } |
| 123 | |
| 124 | void FrameBuffer::setCursorImage(sw::Surface *cursorImage) |
| 125 | { |
| 126 | if(cursorImage) |
| 127 | { |
| 128 | cursor = cursorImage->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); |
| 129 | cursorImage->unlockExternal(); |
| 130 | |
Nicolas Capens | 3779ea9 | 2015-06-10 13:43:52 -0400 | [diff] [blame] | 131 | cursorWidth = cursorImage->getWidth(); |
| 132 | cursorHeight = cursorImage->getHeight(); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 133 | } |
| 134 | else |
| 135 | { |
| 136 | cursorWidth = 0; |
| 137 | cursorHeight = 0; |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | void FrameBuffer::setCursorOrigin(int x0, int y0) |
| 142 | { |
| 143 | cursorHotspotX = x0; |
| 144 | cursorHotspotY = y0; |
| 145 | } |
| 146 | |
| 147 | void FrameBuffer::setCursorPosition(int x, int y) |
| 148 | { |
| 149 | cursorPositionX = x; |
| 150 | cursorPositionY = y; |
| 151 | } |
| 152 | |
Nicolas Capens | 22bc79c | 2015-11-30 13:24:24 -0500 | [diff] [blame] | 153 | void FrameBuffer::copy(void *source, Format format, size_t stride) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 154 | { |
| 155 | if(!source) |
| 156 | { |
| 157 | return; |
| 158 | } |
| 159 | |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 160 | if(!lock()) |
| 161 | { |
| 162 | return; |
| 163 | } |
| 164 | |
Nicolas Capens | 8aaf671 | 2015-05-11 15:15:32 -0400 | [diff] [blame] | 165 | sourceFormat = format; |
| 166 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 167 | if(topLeftOrigin) |
| 168 | { |
| 169 | target = source; |
| 170 | } |
| 171 | else |
| 172 | { |
Nicolas Capens | 22bc79c | 2015-11-30 13:24:24 -0500 | [diff] [blame] | 173 | target = (byte*)source + (height - 1) * stride; |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 174 | } |
| 175 | |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 176 | cursorX = cursorPositionX - cursorHotspotX; |
| 177 | cursorY = cursorPositionY - cursorHotspotY; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 178 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 179 | if(ASYNCHRONOUS_BLIT) |
| 180 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 181 | blitEvent.signal(); |
| 182 | syncEvent.wait(); |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 183 | } |
| 184 | else |
| 185 | { |
| 186 | copyLocked(); |
| 187 | } |
Nicolas Capens | 0270476 | 2014-11-24 15:50:51 -0500 | [diff] [blame] | 188 | |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 189 | unlock(); |
Nicolas Capens | 6ef6d2a | 2015-02-23 14:23:11 -0500 | [diff] [blame] | 190 | |
| 191 | profiler.nextFrame(); // Assumes every copy() is a full frame |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 192 | } |
| 193 | |
| 194 | void FrameBuffer::copyLocked() |
| 195 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 196 | BlitState update = {0}; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 197 | |
| 198 | update.width = width; |
| 199 | update.height = height; |
Nicolas Capens | 10219e7 | 2014-05-07 00:17:20 -0400 | [diff] [blame] | 200 | update.destFormat = destFormat; |
| 201 | update.sourceFormat = sourceFormat; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 202 | update.stride = stride; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 203 | update.cursorWidth = cursorWidth; |
| 204 | update.cursorHeight = cursorHeight; |
| 205 | |
| 206 | if(memcmp(&blitState, &update, sizeof(BlitState)) != 0) |
| 207 | { |
| 208 | blitState = update; |
| 209 | delete blitRoutine; |
| 210 | |
| 211 | blitRoutine = copyRoutine(blitState); |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 212 | blitFunction = (void(*)(void*, void*))blitRoutine->getEntry(); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 213 | } |
| 214 | |
| 215 | blitFunction(locked, target); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 216 | } |
| 217 | |
| 218 | Routine *FrameBuffer::copyRoutine(const BlitState &state) |
| 219 | { |
| 220 | initializeLogo(); |
| 221 | |
| 222 | const int width = state.width; |
| 223 | const int height = state.height; |
| 224 | const int width2 = (state.width + 1) & ~1; |
Nicolas Capens | 10219e7 | 2014-05-07 00:17:20 -0400 | [diff] [blame] | 225 | const int dBytes = Surface::bytes(state.destFormat); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 226 | const int dStride = state.stride; |
Nicolas Capens | 10219e7 | 2014-05-07 00:17:20 -0400 | [diff] [blame] | 227 | const int sBytes = Surface::bytes(state.sourceFormat); |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 228 | const int sStride = topLeftOrigin ? (sBytes * width2) : -(sBytes * width2); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 229 | |
Nicolas Capens | 135f634 | 2015-11-11 10:49:08 -0500 | [diff] [blame] | 230 | #ifdef __ANDROID__ |
| 231 | char ro_product_model[PROPERTY_VALUE_MAX] = ""; |
| 232 | property_get("ro.product.model", ro_product_model, nullptr); |
| 233 | bool validKey = strstr(ro_product_model, "Android") != nullptr; |
| 234 | #else |
| 235 | bool validKey = ValidateSerialNumber(validationKey, CHECKSUM_KEY, SERIAL_PREFIX); |
| 236 | #endif |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 237 | |
| 238 | Function<Void, Pointer<Byte>, Pointer<Byte> > function; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 239 | { |
| 240 | Pointer<Byte> dst(function.arg(0)); |
| 241 | Pointer<Byte> src(function.arg(1)); |
| 242 | |
| 243 | For(Int y = 0, y < height, y++) |
| 244 | { |
| 245 | Pointer<Byte> d = dst + y * dStride; |
| 246 | Pointer<Byte> s = src + y * sStride; |
| 247 | |
| 248 | Int x0 = 0; |
| 249 | |
| 250 | #if DISPLAY_LOGO |
| 251 | If(!Bool(validKey)/* || !Bool(validApp)*/) |
| 252 | { |
| 253 | If(y > height - logoHeight) |
| 254 | { |
| 255 | x0 = logoWidth; |
| 256 | s += logoWidth * sBytes; |
| 257 | d += logoWidth * dBytes; |
| 258 | } |
| 259 | } |
| 260 | #endif |
| 261 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 262 | switch(state.destFormat) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 263 | { |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 264 | case FORMAT_X8R8G8B8: |
| 265 | case FORMAT_A8R8G8B8: |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 266 | { |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 267 | Int x = x0; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 268 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 269 | switch(state.sourceFormat) |
| 270 | { |
| 271 | case FORMAT_X8R8G8B8: |
| 272 | case FORMAT_A8R8G8B8: |
| 273 | For(, x < width - 3, x += 4) |
| 274 | { |
| 275 | *Pointer<Int4>(d, 1) = *Pointer<Int4>(s, width % 4 ? 1 : 16); |
| 276 | |
| 277 | s += 4 * sBytes; |
| 278 | d += 4 * dBytes; |
| 279 | } |
| 280 | break; |
| 281 | case FORMAT_X8B8G8R8: |
| 282 | case FORMAT_A8B8G8R8: |
| 283 | For(, x < width - 3, x += 4) |
| 284 | { |
| 285 | Int4 bgra = *Pointer<Int4>(s, width % 4 ? 1 : 16); |
| 286 | |
| 287 | *Pointer<Int4>(d, 1) = ((bgra & Int4(0x00FF0000)) >> 16) | |
| 288 | ((bgra & Int4(0x000000FF)) << 16) | |
| 289 | (bgra & Int4(0xFF00FF00)); |
| 290 | |
| 291 | s += 4 * sBytes; |
| 292 | d += 4 * dBytes; |
| 293 | } |
| 294 | break; |
| 295 | case FORMAT_A16B16G16R16: |
| 296 | For(, x < width - 1, x += 2) |
| 297 | { |
| 298 | UShort4 c0 = As<UShort4>(Swizzle(*Pointer<Short4>(s + 0), 0xC6)) >> 8; |
| 299 | UShort4 c1 = As<UShort4>(Swizzle(*Pointer<Short4>(s + 8), 0xC6)) >> 8; |
| 300 | |
| 301 | *Pointer<Int2>(d) = As<Int2>(Pack(c0, c1)); |
| 302 | |
| 303 | s += 2 * sBytes; |
| 304 | d += 2 * dBytes; |
| 305 | } |
| 306 | break; |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 307 | case FORMAT_R5G6B5: |
| 308 | For(, x < width, x++) |
| 309 | { |
| 310 | Int rgb = Int(*Pointer<Short>(s)); |
| 311 | |
| 312 | *Pointer<Int>(d) = 0xFF000000 | |
Nicolas Capens | cf0cdf6 | 2015-05-26 11:20:46 -0400 | [diff] [blame] | 313 | ((rgb & 0xF800) << 8) | ((rgb & 0xE01F) << 3) | |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 314 | ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) | |
Nicolas Capens | cf0cdf6 | 2015-05-26 11:20:46 -0400 | [diff] [blame] | 315 | ((rgb & 0x001C) >> 2); |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 316 | |
| 317 | s += sBytes; |
| 318 | d += dBytes; |
| 319 | } |
| 320 | break; |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 321 | default: |
| 322 | ASSERT(false); |
| 323 | break; |
| 324 | } |
| 325 | |
| 326 | For(, x < width, x++) |
| 327 | { |
| 328 | switch(state.sourceFormat) |
| 329 | { |
| 330 | case FORMAT_X8R8G8B8: |
| 331 | case FORMAT_A8R8G8B8: |
| 332 | *Pointer<Int>(d) = *Pointer<Int>(s); |
| 333 | break; |
| 334 | case FORMAT_X8B8G8R8: |
| 335 | case FORMAT_A8B8G8R8: |
| 336 | { |
| 337 | Int rgba = *Pointer<Int>(s); |
| 338 | |
| 339 | *Pointer<Int>(d) = ((rgba & Int(0x00FF0000)) >> 16) | |
| 340 | ((rgba & Int(0x000000FF)) << 16) | |
| 341 | (rgba & Int(0xFF00FF00)); |
| 342 | } |
| 343 | break; |
| 344 | case FORMAT_A16B16G16R16: |
| 345 | { |
| 346 | UShort4 c = As<UShort4>(Swizzle(*Pointer<Short4>(s), 0xC6)) >> 8; |
| 347 | |
| 348 | *Pointer<Int>(d) = Int(As<Int2>(Pack(c, c))); |
| 349 | } |
| 350 | break; |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 351 | case FORMAT_R5G6B5: |
| 352 | { |
| 353 | Int rgb = Int(*Pointer<Short>(s)); |
| 354 | |
| 355 | *Pointer<Int>(d) = 0xFF000000 | |
Nicolas Capens | cf0cdf6 | 2015-05-26 11:20:46 -0400 | [diff] [blame] | 356 | ((rgb & 0xF800) << 8) | ((rgb & 0xE01F) << 3) | |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 357 | ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) | |
Nicolas Capens | cf0cdf6 | 2015-05-26 11:20:46 -0400 | [diff] [blame] | 358 | ((rgb & 0x001C) >> 2); |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 359 | } |
| 360 | break; |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 361 | default: |
| 362 | ASSERT(false); |
| 363 | break; |
| 364 | } |
| 365 | |
| 366 | s += sBytes; |
| 367 | d += dBytes; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 368 | } |
| 369 | } |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 370 | break; |
| 371 | case FORMAT_X8B8G8R8: |
| 372 | case FORMAT_A8B8G8R8: |
Nicolas Capens | 4e0d6f6 | 2015-03-27 21:47:49 -0400 | [diff] [blame] | 373 | { |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 374 | Int x = x0; |
| 375 | |
| 376 | switch(state.sourceFormat) |
Nicolas Capens | 4e0d6f6 | 2015-03-27 21:47:49 -0400 | [diff] [blame] | 377 | { |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 378 | case FORMAT_X8B8G8R8: |
| 379 | case FORMAT_A8B8G8R8: |
| 380 | For(, x < width - 3, x += 4) |
| 381 | { |
| 382 | *Pointer<Int4>(d, 1) = *Pointer<Int4>(s, width % 4 ? 1 : 16); |
Nicolas Capens | 4e0d6f6 | 2015-03-27 21:47:49 -0400 | [diff] [blame] | 383 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 384 | s += 4 * sBytes; |
| 385 | d += 4 * dBytes; |
| 386 | } |
| 387 | break; |
| 388 | case FORMAT_X8R8G8B8: |
| 389 | case FORMAT_A8R8G8B8: |
| 390 | For(, x < width - 3, x += 4) |
| 391 | { |
| 392 | Int4 bgra = *Pointer<Int4>(s, width % 4 ? 1 : 16); |
Nicolas Capens | 4e0d6f6 | 2015-03-27 21:47:49 -0400 | [diff] [blame] | 393 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 394 | *Pointer<Int4>(d, 1) = ((bgra & Int4(0x00FF0000)) >> 16) | |
| 395 | ((bgra & Int4(0x000000FF)) << 16) | |
| 396 | (bgra & Int4(0xFF00FF00)); |
| 397 | |
| 398 | s += 4 * sBytes; |
| 399 | d += 4 * dBytes; |
| 400 | } |
| 401 | break; |
| 402 | case FORMAT_A16B16G16R16: |
| 403 | For(, x < width - 1, x += 2) |
| 404 | { |
| 405 | UShort4 c0 = *Pointer<UShort4>(s + 0) >> 8; |
| 406 | UShort4 c1 = *Pointer<UShort4>(s + 8) >> 8; |
| 407 | |
| 408 | *Pointer<Int2>(d) = As<Int2>(Pack(c0, c1)); |
| 409 | |
| 410 | s += 2 * sBytes; |
| 411 | d += 2 * dBytes; |
| 412 | } |
| 413 | break; |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 414 | case FORMAT_R5G6B5: |
| 415 | For(, x < width, x++) |
| 416 | { |
| 417 | Int rgb = Int(*Pointer<Short>(s)); |
| 418 | |
| 419 | *Pointer<Int>(d) = 0xFF000000 | |
| 420 | ((rgb & 0x001F) << 19) | ((rgb & 0x001C) << 14) | |
| 421 | ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) | |
| 422 | ((rgb & 0xF800) >> 8) | ((rgb & 0xE000) >> 13); |
| 423 | |
| 424 | s += sBytes; |
| 425 | d += dBytes; |
| 426 | } |
| 427 | break; |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 428 | default: |
| 429 | ASSERT(false); |
| 430 | break; |
| 431 | } |
| 432 | |
| 433 | For(, x < width, x++) |
| 434 | { |
| 435 | switch(state.sourceFormat) |
| 436 | { |
| 437 | case FORMAT_X8B8G8R8: |
| 438 | case FORMAT_A8B8G8R8: |
| 439 | *Pointer<Int>(d) = *Pointer<Int>(s); |
| 440 | break; |
| 441 | case FORMAT_X8R8G8B8: |
| 442 | case FORMAT_A8R8G8B8: |
| 443 | { |
| 444 | Int bgra = *Pointer<Int>(s); |
| 445 | *Pointer<Int>(d) = ((bgra & Int(0x00FF0000)) >> 16) | |
| 446 | ((bgra & Int(0x000000FF)) << 16) | |
| 447 | (bgra & Int(0xFF00FF00)); |
| 448 | } |
| 449 | break; |
| 450 | case FORMAT_A16B16G16R16: |
| 451 | { |
| 452 | UShort4 c = *Pointer<UShort4>(s) >> 8; |
| 453 | |
| 454 | *Pointer<Int>(d) = Int(As<Int2>(Pack(c, c))); |
| 455 | } |
| 456 | break; |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 457 | case FORMAT_R5G6B5: |
| 458 | { |
| 459 | Int rgb = Int(*Pointer<Short>(s)); |
| 460 | |
| 461 | *Pointer<Int>(d) = 0xFF000000 | |
| 462 | ((rgb & 0x001F) << 19) | ((rgb & 0x001C) << 14) | |
| 463 | ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) | |
| 464 | ((rgb & 0xF800) >> 8) | ((rgb & 0xE000) >> 13); |
| 465 | } |
| 466 | break; |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 467 | default: |
| 468 | ASSERT(false); |
| 469 | break; |
| 470 | } |
| 471 | |
| 472 | s += sBytes; |
| 473 | d += dBytes; |
Nicolas Capens | 4e0d6f6 | 2015-03-27 21:47:49 -0400 | [diff] [blame] | 474 | } |
| 475 | } |
Ping-Hao Wu | e04f28a | 2015-05-26 16:16:00 -0700 | [diff] [blame] | 476 | break; |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 477 | case FORMAT_R8G8B8: |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 478 | { |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 479 | For(Int x = x0, x < width, x++) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 480 | { |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 481 | switch(state.sourceFormat) |
| 482 | { |
| 483 | case FORMAT_X8R8G8B8: |
| 484 | case FORMAT_A8R8G8B8: |
| 485 | *Pointer<Byte>(d + 0) = *Pointer<Byte>(s + 0); |
| 486 | *Pointer<Byte>(d + 1) = *Pointer<Byte>(s + 1); |
| 487 | *Pointer<Byte>(d + 2) = *Pointer<Byte>(s + 2); |
| 488 | break; |
| 489 | case FORMAT_X8B8G8R8: |
| 490 | case FORMAT_A8B8G8R8: |
| 491 | *Pointer<Byte>(d + 0) = *Pointer<Byte>(s + 2); |
| 492 | *Pointer<Byte>(d + 1) = *Pointer<Byte>(s + 1); |
| 493 | *Pointer<Byte>(d + 2) = *Pointer<Byte>(s + 0); |
| 494 | break; |
| 495 | case FORMAT_A16B16G16R16: |
| 496 | *Pointer<Byte>(d + 0) = *Pointer<Byte>(s + 5); |
| 497 | *Pointer<Byte>(d + 1) = *Pointer<Byte>(s + 3); |
| 498 | *Pointer<Byte>(d + 2) = *Pointer<Byte>(s + 1); |
| 499 | break; |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 500 | case FORMAT_R5G6B5: |
| 501 | { |
| 502 | Int rgb = Int(*Pointer<Short>(s)); |
| 503 | |
| 504 | *Pointer<Byte>(d + 0) = Byte(((rgb & 0x001F) << 3) | ((rgb & 0x001C) >> 2)); |
| 505 | *Pointer<Byte>(d + 1) = Byte(((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1)); |
| 506 | *Pointer<Byte>(d + 2) = Byte(((rgb & 0xF800) << 8) | ((rgb & 0xE000) << 3)); |
| 507 | } |
| 508 | break; |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 509 | default: |
| 510 | ASSERT(false); |
| 511 | break; |
| 512 | } |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 513 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 514 | s += sBytes; |
| 515 | d += dBytes; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 516 | } |
| 517 | } |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 518 | break; |
| 519 | case FORMAT_R5G6B5: |
Nicolas Capens | 296e312 | 2014-05-07 00:10:55 -0400 | [diff] [blame] | 520 | { |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 521 | For(Int x = x0, x < width, x++) |
Nicolas Capens | 296e312 | 2014-05-07 00:10:55 -0400 | [diff] [blame] | 522 | { |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 523 | switch(state.sourceFormat) |
| 524 | { |
| 525 | case FORMAT_X8R8G8B8: |
| 526 | case FORMAT_A8R8G8B8: |
| 527 | { |
| 528 | Int c = *Pointer<Int>(s); |
Nicolas Capens | 4e0d6f6 | 2015-03-27 21:47:49 -0400 | [diff] [blame] | 529 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 530 | *Pointer<Short>(d) = Short((c & 0x00F80000) >> 8 | |
| 531 | (c & 0x0000FC00) >> 5 | |
| 532 | (c & 0x000000F8) >> 3); |
| 533 | } |
| 534 | break; |
| 535 | case FORMAT_X8B8G8R8: |
| 536 | case FORMAT_A8B8G8R8: |
| 537 | { |
| 538 | Int c = *Pointer<Int>(s); |
Nicolas Capens | 296e312 | 2014-05-07 00:10:55 -0400 | [diff] [blame] | 539 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 540 | *Pointer<Short>(d) = Short((c & 0x00F80000) >> 19 | |
| 541 | (c & 0x0000FC00) >> 5 | |
| 542 | (c & 0x000000F8) << 8); |
| 543 | } |
| 544 | break; |
| 545 | case FORMAT_A16B16G16R16: |
| 546 | { |
| 547 | UShort4 cc = *Pointer<UShort4>(s) >> 8; |
| 548 | Int c = Int(As<Int2>(Pack(cc, cc))); |
Nicolas Capens | 296e312 | 2014-05-07 00:10:55 -0400 | [diff] [blame] | 549 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 550 | *Pointer<Short>(d) = Short((c & 0x00F80000) >> 19 | |
| 551 | (c & 0x0000FC00) >> 5 | |
| 552 | (c & 0x000000F8) << 8); |
| 553 | } |
| 554 | break; |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 555 | case FORMAT_R5G6B5: |
| 556 | *Pointer<Short>(d) = *Pointer<Short>(s); |
| 557 | break; |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 558 | default: |
| 559 | ASSERT(false); |
| 560 | break; |
| 561 | } |
| 562 | |
| 563 | s += sBytes; |
| 564 | d += dBytes; |
| 565 | } |
Nicolas Capens | 296e312 | 2014-05-07 00:10:55 -0400 | [diff] [blame] | 566 | } |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 567 | break; |
| 568 | default: |
| 569 | ASSERT(false); |
| 570 | break; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 571 | } |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 572 | } |
| 573 | |
| 574 | #if DISPLAY_LOGO |
| 575 | If(!Bool(validKey)/* || !Bool(validApp)*/) |
| 576 | { |
| 577 | UInt hash = UInt(0x0B020C04) + UInt(0xC0F090E0); // Initial value |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 578 | UInt imageHash = S3TC_SUPPORT ? UInt(0x0F0D0700) + UInt(0xA0C0A090) : UInt(0x0207040B) + UInt(0xD0406010); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 579 | |
| 580 | While(hash != imageHash) |
| 581 | { |
| 582 | For(y = (height - 1), height - 1 - y < logoHeight, y--) |
| 583 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 584 | Pointer<Byte> logo = *Pointer<Pointer<Byte> >(&logoImage) + 4 * (logoHeight - height + y) * logoWidth; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 585 | Pointer<Byte> s = src + y * sStride; |
| 586 | Pointer<Byte> d = dst + y * dStride; |
| 587 | |
| 588 | For(Int x = 0, x < logoWidth, x++) |
| 589 | { |
| 590 | hash *= 16777619; |
| 591 | hash ^= *Pointer<UInt>(logo); |
| 592 | |
| 593 | If(y >= 0 && x < width) |
| 594 | { |
| 595 | blend(state, d, s, logo); |
| 596 | } |
| 597 | |
| 598 | logo += 4; |
| 599 | s += sBytes; |
| 600 | d += dBytes; |
| 601 | } |
| 602 | } |
| 603 | } |
| 604 | } |
| 605 | #endif |
| 606 | |
| 607 | Int x0 = *Pointer<Int>(&cursorX); |
| 608 | Int y0 = *Pointer<Int>(&cursorY); |
| 609 | |
| 610 | For(Int y1 = 0, y1 < cursorHeight, y1++) |
| 611 | { |
| 612 | Int y = y0 + y1; |
| 613 | |
| 614 | If(y >= 0 && y < height) |
| 615 | { |
| 616 | Pointer<Byte> d = dst + y * dStride + x0 * dBytes; |
| 617 | Pointer<Byte> s = src + y * sStride + x0 * sBytes; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 618 | Pointer<Byte> c = *Pointer<Pointer<Byte> >(&cursor) + y1 * cursorWidth * 4; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 619 | |
| 620 | For(Int x1 = 0, x1 < cursorWidth, x1++) |
| 621 | { |
| 622 | Int x = x0 + x1; |
| 623 | |
| 624 | If(x >= 0 && x < width) |
| 625 | { |
| 626 | blend(state, d, s, c); |
| 627 | } |
Nicolas Capens | 0270476 | 2014-11-24 15:50:51 -0500 | [diff] [blame] | 628 | |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 629 | c += 4; |
| 630 | s += sBytes; |
| 631 | d += dBytes; |
| 632 | } |
| 633 | } |
| 634 | } |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 635 | } |
| 636 | |
| 637 | return function(L"FrameBuffer"); |
| 638 | } |
| 639 | |
| 640 | void FrameBuffer::blend(const BlitState &state, const Pointer<Byte> &d, const Pointer<Byte> &s, const Pointer<Byte> &c) |
| 641 | { |
| 642 | Short4 c1; |
| 643 | Short4 c2; |
| 644 | |
| 645 | c1 = UnpackLow(As<Byte8>(c1), *Pointer<Byte8>(c)); |
Nicolas Capens | 0270476 | 2014-11-24 15:50:51 -0500 | [diff] [blame] | 646 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 647 | switch(state.sourceFormat) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 648 | { |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 649 | case FORMAT_X8R8G8B8: |
| 650 | case FORMAT_A8R8G8B8: |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 651 | c2 = UnpackLow(As<Byte8>(c2), *Pointer<Byte8>(s)); |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 652 | break; |
| 653 | case FORMAT_X8B8G8R8: |
| 654 | case FORMAT_A8B8G8R8: |
Nicolas Capens | 4e0d6f6 | 2015-03-27 21:47:49 -0400 | [diff] [blame] | 655 | c2 = Swizzle(UnpackLow(As<Byte8>(c2), *Pointer<Byte8>(s)), 0xC6); |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 656 | break; |
| 657 | case FORMAT_A16B16G16R16: |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 658 | c2 = Swizzle(*Pointer<Short4>(s), 0xC6); |
| 659 | break; |
| 660 | case FORMAT_R5G6B5: |
| 661 | { |
| 662 | Int rgb(*Pointer<Short>(s)); |
| 663 | rgb = 0xFF000000 | |
Nicolas Capens | 3e3f536 | 2015-05-26 16:36:35 -0400 | [diff] [blame] | 664 | ((rgb & 0xF800) << 8) | ((rgb & 0xE01F) << 3) | |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 665 | ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) | |
Nicolas Capens | 3e3f536 | 2015-05-26 16:36:35 -0400 | [diff] [blame] | 666 | ((rgb & 0x001C) >> 2); |
Nicolas Capens | e030890 | 2015-05-25 23:47:18 -0400 | [diff] [blame] | 667 | c2 = Unpack(As<Byte4>(rgb)); |
| 668 | } |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 669 | break; |
| 670 | default: |
| 671 | ASSERT(false); |
| 672 | break; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 673 | } |
| 674 | |
| 675 | c1 = As<Short4>(As<UShort4>(c1) >> 9); |
| 676 | c2 = As<Short4>(As<UShort4>(c2) >> 9); |
| 677 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 678 | Short4 alpha = Swizzle(c1, 0xFF) & Short4(0xFFFFu, 0xFFFFu, 0xFFFFu, 0x0000); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 679 | |
| 680 | c1 = (c1 - c2) * alpha; |
| 681 | c1 = c1 >> 7; |
| 682 | c1 = c1 + c2; |
| 683 | c1 = c1 + c1; |
| 684 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 685 | switch(state.destFormat) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 686 | { |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 687 | case FORMAT_X8R8G8B8: |
| 688 | case FORMAT_A8R8G8B8: |
Nicolas Capens | 4e0d6f6 | 2015-03-27 21:47:49 -0400 | [diff] [blame] | 689 | *Pointer<UInt>(d) = UInt(As<Long>(Pack(As<UShort4>(c1), As<UShort4>(c1)))); |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 690 | break; |
| 691 | case FORMAT_X8B8G8R8: |
| 692 | case FORMAT_A8B8G8R8: |
| 693 | { |
| 694 | c1 = Swizzle(c1, 0xC6); |
Nicolas Capens | 4e0d6f6 | 2015-03-27 21:47:49 -0400 | [diff] [blame] | 695 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 696 | *Pointer<UInt>(d) = UInt(As<Long>(Pack(As<UShort4>(c1), As<UShort4>(c1)))); |
| 697 | } |
| 698 | break; |
| 699 | case FORMAT_R8G8B8: |
| 700 | { |
| 701 | Int c = Int(As<Int2>(Pack(As<UShort4>(c1), As<UShort4>(c1)))); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 702 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 703 | *Pointer<Byte>(d + 0) = Byte(c >> 0); |
| 704 | *Pointer<Byte>(d + 1) = Byte(c >> 8); |
| 705 | *Pointer<Byte>(d + 2) = Byte(c >> 16); |
| 706 | } |
| 707 | break; |
| 708 | case FORMAT_R5G6B5: |
| 709 | { |
| 710 | Int c = Int(As<Int2>(Pack(As<UShort4>(c1), As<UShort4>(c1)))); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 711 | |
Alexis Hetu | 3b6c9cf | 2015-05-07 11:41:43 -0400 | [diff] [blame] | 712 | *Pointer<Short>(d) = Short((c & 0x00F80000) >> 8 | |
| 713 | (c & 0x0000FC00) >> 5 | |
| 714 | (c & 0x000000F8) >> 3); |
| 715 | } |
| 716 | break; |
| 717 | default: |
| 718 | ASSERT(false); |
| 719 | break; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 720 | } |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 721 | } |
| 722 | |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 723 | void FrameBuffer::threadFunction(void *parameters) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 724 | { |
| 725 | FrameBuffer *frameBuffer = *static_cast<FrameBuffer**>(parameters); |
| 726 | |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 727 | while(!frameBuffer->terminate) |
| 728 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 729 | frameBuffer->blitEvent.wait(); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 730 | |
| 731 | if(!frameBuffer->terminate) |
| 732 | { |
| 733 | frameBuffer->copyLocked(); |
| 734 | |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 735 | frameBuffer->syncEvent.signal(); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 736 | } |
| 737 | } |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 738 | } |
| 739 | |
| 740 | void FrameBuffer::initializeLogo() |
| 741 | { |
| 742 | #if DISPLAY_LOGO |
| 743 | if(!logo) |
| 744 | { |
| 745 | #if S3TC_SUPPORT |
| 746 | logo = new Surface(0, logoWidth, logoHeight, 1, FORMAT_DXT5, true, false); |
| 747 | void *data = logo->lockExternal(0, 0, 0, LOCK_WRITEONLY, sw::PUBLIC); |
| 748 | memcpy(data, logoData, logoWidth * logoHeight); |
| 749 | logo->unlockExternal(); |
| 750 | #else |
| 751 | logo = new Surface(0, logoWidth, logoHeight, 1, FORMAT_A8R8G8B8, true, false); |
| 752 | void *data = logo->lockExternal(0, 0, 0, LOCK_WRITEONLY, sw::PUBLIC); |
| 753 | memcpy(data, logoData, logoWidth * logoHeight * 4); |
| 754 | logo->unlockExternal(); |
| 755 | #endif |
| 756 | |
| 757 | logoImage = (unsigned int*)logo->lockInternal(0, 0, 0, LOCK_READONLY, sw::PUBLIC); |
| 758 | logo->unlockInternal(); |
| 759 | } |
| 760 | #endif |
| 761 | } |
Nicolas Capens | 0270476 | 2014-11-24 15:50:51 -0500 | [diff] [blame] | 762 | } |