src/video/haiku/SDL_bframebuffer.cc
author Ryan C. Gordon <icculus@icculus.org>
Tue, 07 Aug 2018 18:07:11 -0400
changeset 12082 09999a0e8f9a
parent 11811 5d94cb6b24d3
child 12201 8bdc4d340419
permissions -rw-r--r--
haiku: Rename internal functions from BE_* to HAIKU_*

Fixes Bugzilla #2349.
nathanheisey@5931
     1
/*
nathanheisey@5931
     2
  Simple DirectMedia Layer
slouken@11811
     3
  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
nathanheisey@5931
     4
nathanheisey@5931
     5
  This software is provided 'as-is', without any express or implied
nathanheisey@5931
     6
  warranty.  In no event will the authors be held liable for any damages
nathanheisey@5931
     7
  arising from the use of this software.
nathanheisey@5931
     8
nathanheisey@5931
     9
  Permission is granted to anyone to use this software for any purpose,
nathanheisey@5931
    10
  including commercial applications, and to alter it and redistribute it
nathanheisey@5931
    11
  freely, subject to the following restrictions:
nathanheisey@5931
    12
nathanheisey@5931
    13
  1. The origin of this software must not be misrepresented; you must not
nathanheisey@5931
    14
     claim that you wrote the original software. If you use this software
nathanheisey@5931
    15
     in a product, an acknowledgment in the product documentation would be
nathanheisey@5931
    16
     appreciated but is not required.
nathanheisey@5931
    17
  2. Altered source versions must be plainly marked as such, and must not be
nathanheisey@5931
    18
     misrepresented as being the original software.
nathanheisey@5931
    19
  3. This notice may not be removed or altered from any source distribution.
nathanheisey@5931
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@6044
    22
icculus@7981
    23
#if SDL_VIDEO_DRIVER_HAIKU
nathanheisey@5931
    24
nathanheisey@5931
    25
#include "SDL_bframebuffer.h"
nathanheisey@5931
    26
nathanheisey@5931
    27
#include <AppKit.h>
nathanheisey@5931
    28
#include <InterfaceKit.h>
nathanheisey@5931
    29
#include "SDL_bmodes.h"
nathanheisey@5931
    30
#include "SDL_BWin.h"
nathanheisey@5931
    31
icculus@7981
    32
#include "../../main/haiku/SDL_BApp.h"
nathanheisey@5931
    33
nathanheisey@5931
    34
#ifdef __cplusplus
nathanheisey@5931
    35
extern "C" {
nathanheisey@5931
    36
#endif
nathanheisey@5931
    37
icculus@11204
    38
#ifndef DRAWTHREAD
icculus@12082
    39
static int32 HAIKU_UpdateOnce(SDL_Window *window);
icculus@11204
    40
#endif
nathanheisey@5936
    41
slouken@7860
    42
static SDL_INLINE SDL_BWin *_ToBeWin(SDL_Window *window) {
nathanheisey@5931
    43
	return ((SDL_BWin*)(window->driverdata));
nathanheisey@5931
    44
}
nathanheisey@5931
    45
slouken@7860
    46
static SDL_INLINE SDL_BApp *_GetBeApp() {
nathanheisey@5931
    47
	return ((SDL_BApp*)be_app);
nathanheisey@5931
    48
}
nathanheisey@5931
    49
icculus@12082
    50
int HAIKU_CreateWindowFramebuffer(_THIS, SDL_Window * window,
nathanheisey@5931
    51
                                       Uint32 * format,
nathanheisey@5931
    52
                                       void ** pixels, int *pitch) {
nathanheisey@5931
    53
	SDL_BWin *bwin = _ToBeWin(window);
nathanheisey@5931
    54
	BScreen bscreen;
nathanheisey@5931
    55
	if(!bscreen.IsValid()) {
nathanheisey@5931
    56
		return -1;
nathanheisey@5931
    57
	}
nathanheisey@5931
    58
nathanheisey@5931
    59
	while(!bwin->Connected()) { snooze(100); }
nathanheisey@5931
    60
	
nathanheisey@5931
    61
	/* Make sure we have exclusive access to frame buffer data */
nathanheisey@5931
    62
	bwin->LockBuffer();
nathanheisey@5932
    63
nathanheisey@5931
    64
	/* format */
nathanheisey@5931
    65
	display_mode bmode;
nathanheisey@5931
    66
	bscreen.GetMode(&bmode);
icculus@12082
    67
	int32 bpp = HAIKU_ColorSpaceToBitsPerPixel(bmode.space);
icculus@12082
    68
	*format = HAIKU_BPPToSDLPxFormat(bpp);
nathanheisey@5931
    69
nathanheisey@5933
    70
	/* Create the new bitmap object */
nathanheisey@5933
    71
	BBitmap *bitmap = bwin->GetBitmap();
nathanheisey@5934
    72
nathanheisey@5933
    73
	if(bitmap) {
nathanheisey@5933
    74
		delete bitmap;
nathanheisey@5933
    75
	}
nathanheisey@5933
    76
	bitmap = new BBitmap(bwin->Bounds(), (color_space)bmode.space,
nathanheisey@5933
    77
			false,	/* Views not accepted */
nathanheisey@5933
    78
			true);	/* Contiguous memory required */
nathanheisey@5934
    79
			
nathanheisey@5934
    80
	if(bitmap->InitCheck() != B_OK) {
philipp@10829
    81
		delete bitmap;
philipp@10945
    82
		return SDL_SetError("Could not initialize back buffer!");
nathanheisey@5934
    83
	}
nathanheisey@5934
    84
nathanheisey@5934
    85
nathanheisey@5933
    86
	bwin->SetBitmap(bitmap);
nathanheisey@5933
    87
	
nathanheisey@5933
    88
	/* Set the pixel pointer */
nathanheisey@5933
    89
	*pixels = bitmap->Bits();
nathanheisey@5931
    90
nathanheisey@5933
    91
	/* pitch = width of window, in bytes */
nathanheisey@5933
    92
	*pitch = bitmap->BytesPerRow();
nathanheisey@5931
    93
nathanheisey@5931
    94
	bwin->SetBufferExists(true);
nathanheisey@5931
    95
	bwin->SetTrashBuffer(false);
nathanheisey@5931
    96
	bwin->UnlockBuffer();
nathanheisey@5931
    97
	return 0;
nathanheisey@5931
    98
}
nathanheisey@5931
    99
nathanheisey@5931
   100
nathanheisey@5931
   101
icculus@12082
   102
int HAIKU_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
slouken@7014
   103
                                      const SDL_Rect * rects, int numrects) {
nathanheisey@5931
   104
	if(!window)
nathanheisey@5931
   105
		return 0;
nathanheisey@5931
   106
nathanheisey@5931
   107
	SDL_BWin *bwin = _ToBeWin(window);
nathanheisey@5936
   108
nathanheisey@5936
   109
#ifdef DRAWTHREAD	
nathanheisey@5931
   110
	bwin->LockBuffer();
nathanheisey@5931
   111
	bwin->SetBufferDirty(true);
nathanheisey@5931
   112
	bwin->UnlockBuffer();
nathanheisey@5936
   113
#else
nathanheisey@5936
   114
	bwin->SetBufferDirty(true);
icculus@12082
   115
	HAIKU_UpdateOnce(window);
nathanheisey@5936
   116
#endif
nathanheisey@5931
   117
nathanheisey@5931
   118
	return 0;
nathanheisey@5931
   119
}
nathanheisey@5931
   120
icculus@12082
   121
int32 HAIKU_DrawThread(void *data) {
nathanheisey@5931
   122
	SDL_BWin *bwin = (SDL_BWin*)data;
nathanheisey@5931
   123
	
nathanheisey@5931
   124
	BScreen bscreen;
nathanheisey@5931
   125
	if(!bscreen.IsValid()) {
nathanheisey@5931
   126
		return -1;
nathanheisey@5931
   127
	}
nathanheisey@5931
   128
nathanheisey@5931
   129
	while(bwin->ConnectionEnabled()) {
nathanheisey@5931
   130
		if( bwin->Connected() && bwin->BufferExists() && bwin->BufferIsDirty() ) {
nathanheisey@5931
   131
			bwin->LockBuffer();
nathanheisey@5938
   132
			BBitmap *bitmap = NULL;
nathanheisey@5939
   133
			bitmap = bwin->GetBitmap();
nathanheisey@5933
   134
			int32 windowPitch = bitmap->BytesPerRow();
nathanheisey@5931
   135
			int32 bufferPitch = bwin->GetRowBytes();
nathanheisey@5931
   136
			uint8 *windowpx;
nathanheisey@5931
   137
			uint8 *bufferpx;
nathanheisey@5931
   138
nathanheisey@5931
   139
			int32 BPP = bwin->GetBytesPerPx();
nathanheisey@5931
   140
			int32 windowSub = bwin->GetFbX() * BPP +
nathanheisey@5931
   141
						  bwin->GetFbY() * windowPitch;
nathanheisey@5931
   142
			clipping_rect *clips = bwin->GetClips();
nathanheisey@5931
   143
			int32 numClips = bwin->GetNumClips();
nathanheisey@5931
   144
			int i, y;
nathanheisey@5931
   145
nathanheisey@5931
   146
			/* Blit each clipping rectangle */
nathanheisey@5931
   147
			bscreen.WaitForRetrace();
nathanheisey@5931
   148
			for(i = 0; i < numClips; ++i) {
nathanheisey@5931
   149
				/* Get addresses of the start of each clipping rectangle */
nathanheisey@5931
   150
				int32 width = clips[i].right - clips[i].left + 1;
nathanheisey@5931
   151
				int32 height = clips[i].bottom - clips[i].top + 1;
nathanheisey@5931
   152
				bufferpx = bwin->GetBufferPx() + 
nathanheisey@5931
   153
					clips[i].top * bufferPitch + clips[i].left * BPP;
nathanheisey@5934
   154
				windowpx = (uint8*)bitmap->Bits() + 
nathanheisey@5933
   155
					clips[i].top * windowPitch + clips[i].left * BPP -
nathanheisey@5933
   156
					windowSub;
nathanheisey@5931
   157
nathanheisey@5931
   158
				/* Copy each row of pixels from the window buffer into the frame
nathanheisey@5931
   159
				   buffer */
nathanheisey@5931
   160
				for(y = 0; y < height; ++y)
nathanheisey@5931
   161
				{
nathanheisey@5936
   162
nathanheisey@5931
   163
					if(bwin->CanTrashWindowBuffer()) {
nathanheisey@5931
   164
						goto escape;	/* Break out before the buffer is killed */
nathanheisey@5931
   165
					}
nathanheisey@5936
   166
nathanheisey@5931
   167
					memcpy(bufferpx, windowpx, width * BPP);
nathanheisey@5931
   168
					bufferpx += bufferPitch;
nathanheisey@5931
   169
					windowpx += windowPitch;
nathanheisey@5931
   170
				}
nathanheisey@5931
   171
			}
nathanheisey@5939
   172
nathanheisey@5931
   173
			bwin->SetBufferDirty(false);
nathanheisey@5931
   174
escape:
nathanheisey@5931
   175
			bwin->UnlockBuffer();
nathanheisey@5931
   176
		} else {
nathanheisey@5931
   177
			snooze(16000);
nathanheisey@5931
   178
		}
nathanheisey@5931
   179
	}
nathanheisey@5931
   180
	
nathanheisey@5931
   181
	return B_OK;
nathanheisey@5931
   182
}
nathanheisey@5931
   183
icculus@12082
   184
void HAIKU_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
nathanheisey@5931
   185
	SDL_BWin *bwin = _ToBeWin(window);
nathanheisey@5931
   186
	
nathanheisey@5931
   187
	bwin->LockBuffer();
nathanheisey@5931
   188
	
nathanheisey@5931
   189
	/* Free and clear the window buffer */
nathanheisey@5933
   190
	BBitmap *bitmap = bwin->GetBitmap();
nathanheisey@5933
   191
	delete bitmap;
nathanheisey@5933
   192
	bwin->SetBitmap(NULL);
nathanheisey@5931
   193
	bwin->SetBufferExists(false);
nathanheisey@5931
   194
	bwin->UnlockBuffer();
nathanheisey@5931
   195
}
nathanheisey@5931
   196
nathanheisey@5936
   197
nathanheisey@5938
   198
/*
nathanheisey@5938
   199
 * TODO:
nathanheisey@5938
   200
 * This was written to test if certain errors were caused by threading issues.
nathanheisey@5938
   201
 * The specific issues have since become rare enough that they may have been
nathanheisey@5938
   202
 * solved, but I doubt it- they were pretty sporadic before now.
nathanheisey@5938
   203
 */
icculus@11198
   204
#ifndef DRAWTHREAD
icculus@12082
   205
static int32 HAIKU_UpdateOnce(SDL_Window *window) {
nathanheisey@5936
   206
	SDL_BWin *bwin = _ToBeWin(window);
nathanheisey@5936
   207
	BScreen bscreen;
nathanheisey@5936
   208
	if(!bscreen.IsValid()) {
nathanheisey@5936
   209
		return -1;
nathanheisey@5936
   210
	}
nathanheisey@5936
   211
nathanheisey@5936
   212
	if(bwin->ConnectionEnabled() && bwin->Connected()) {
nathanheisey@5936
   213
		bwin->LockBuffer();
nathanheisey@5936
   214
		int32 windowPitch = window->surface->pitch;
nathanheisey@5936
   215
		int32 bufferPitch = bwin->GetRowBytes();
nathanheisey@5936
   216
		uint8 *windowpx;
nathanheisey@5936
   217
		uint8 *bufferpx;
nathanheisey@5936
   218
nathanheisey@5936
   219
		int32 BPP = bwin->GetBytesPerPx();
nathanheisey@5936
   220
		uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
nathanheisey@5936
   221
		int32 windowSub = bwin->GetFbX() * BPP +
nathanheisey@5936
   222
						  bwin->GetFbY() * windowPitch;
nathanheisey@5936
   223
		clipping_rect *clips = bwin->GetClips();
nathanheisey@5936
   224
		int32 numClips = bwin->GetNumClips();
nathanheisey@5936
   225
		int i, y;
nathanheisey@5936
   226
nathanheisey@5936
   227
		/* Blit each clipping rectangle */
nathanheisey@5936
   228
		bscreen.WaitForRetrace();
nathanheisey@5936
   229
		for(i = 0; i < numClips; ++i) {
nathanheisey@5936
   230
			/* Get addresses of the start of each clipping rectangle */
nathanheisey@5936
   231
			int32 width = clips[i].right - clips[i].left + 1;
nathanheisey@5936
   232
			int32 height = clips[i].bottom - clips[i].top + 1;
nathanheisey@5936
   233
			bufferpx = bwin->GetBufferPx() + 
nathanheisey@5936
   234
				clips[i].top * bufferPitch + clips[i].left * BPP;
nathanheisey@5936
   235
			windowpx = windowBaseAddress + 
nathanheisey@5936
   236
				clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
nathanheisey@5936
   237
nathanheisey@5936
   238
			/* Copy each row of pixels from the window buffer into the frame
nathanheisey@5936
   239
			   buffer */
nathanheisey@5936
   240
			for(y = 0; y < height; ++y)
nathanheisey@5936
   241
			{
nathanheisey@5936
   242
				memcpy(bufferpx, windowpx, width * BPP);
nathanheisey@5936
   243
				bufferpx += bufferPitch;
nathanheisey@5936
   244
				windowpx += windowPitch;
nathanheisey@5936
   245
			}
nathanheisey@5936
   246
		}
nathanheisey@5936
   247
		bwin->UnlockBuffer();
nathanheisey@5936
   248
	}
nathanheisey@5936
   249
	return 0;
nathanheisey@5936
   250
}
icculus@11198
   251
#endif
nathanheisey@5936
   252
nathanheisey@5931
   253
#ifdef __cplusplus
nathanheisey@5931
   254
}
nathanheisey@5931
   255
#endif
slouken@6044
   256
icculus@7981
   257
#endif /* SDL_VIDEO_DRIVER_HAIKU */
slouken@10690
   258
slouken@10690
   259
/* vi: set ts=4 sw=4 expandtab: */