1 /* 2 * Copyright 2008-2009, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stefano Ceccherini <stefano.ceccherini@gmail.com> 7 * Axel Dörfler, axeld@pinc-software.de 8 */ 9 10 11 #include "DirectWindowInfo.h" 12 13 #include <stdio.h> 14 #include <string.h> 15 #include <syslog.h> 16 17 #include <Autolock.h> 18 19 #include "RenderingBuffer.h" 20 #include "clipping.h" 21 22 23 DirectWindowInfo::DirectWindowInfo() 24 : 25 fBufferInfo(NULL), 26 fSem(-1), 27 fAcknowledgeSem(-1), 28 fBufferArea(-1), 29 fOriginalFeel(B_NORMAL_WINDOW_FEEL), 30 fFullScreen(false) 31 { 32 fBufferArea = create_area("direct area", (void**)&fBufferInfo, 33 B_ANY_ADDRESS, DIRECT_BUFFER_INFO_AREA_SIZE, 34 B_NO_LOCK, B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA); 35 36 memset(fBufferInfo, 0, DIRECT_BUFFER_INFO_AREA_SIZE); 37 fBufferInfo->buffer_state = B_DIRECT_STOP; 38 39 fSem = create_sem(0, "direct sem"); 40 fAcknowledgeSem = create_sem(0, "direct sem ack"); 41 } 42 43 44 DirectWindowInfo::~DirectWindowInfo() 45 { 46 // this should make the client die in case it's still running 47 fBufferInfo->bits = NULL; 48 fBufferInfo->bytes_per_row = 0; 49 50 delete_area(fBufferArea); 51 delete_sem(fSem); 52 delete_sem(fAcknowledgeSem); 53 } 54 55 56 status_t 57 DirectWindowInfo::InitCheck() const 58 { 59 if (fBufferArea < B_OK) 60 return fBufferArea; 61 if (fSem < B_OK) 62 return fSem; 63 if (fAcknowledgeSem < B_OK) 64 return fAcknowledgeSem; 65 66 return B_OK; 67 } 68 69 70 status_t 71 DirectWindowInfo::GetSyncData(direct_window_sync_data& data) const 72 { 73 data.area = fBufferArea; 74 data.disable_sem = fSem; 75 data.disable_sem_ack = fAcknowledgeSem; 76 77 return B_OK; 78 } 79 80 81 status_t 82 DirectWindowInfo::SetState(direct_buffer_state bufferState, 83 direct_driver_state driverState, RenderingBuffer* buffer, 84 const BRect& windowFrame, const BRegion& clipRegion) 85 { 86 if ((fBufferInfo->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_STOP 87 && (bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_START) 88 return B_OK; 89 90 fBufferInfo->buffer_state = bufferState; 91 92 if ((int)driverState != -1) 93 fBufferInfo->driver_state = driverState; 94 95 if ((bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_STOP) { 96 fBufferInfo->bits = buffer->Bits(); 97 fBufferInfo->pci_bits = NULL; // TODO 98 fBufferInfo->bytes_per_row = buffer->BytesPerRow(); 99 100 switch (buffer->ColorSpace()) { 101 case B_RGBA64: 102 case B_RGBA64_BIG: 103 fBufferInfo->bits_per_pixel = 64; 104 break; 105 case B_RGB48: 106 case B_RGB48_BIG: 107 fBufferInfo->bits_per_pixel = 48; 108 break; 109 case B_RGB32: 110 case B_RGBA32: 111 case B_RGB32_BIG: 112 case B_RGBA32_BIG: 113 fBufferInfo->bits_per_pixel = 32; 114 break; 115 case B_RGB24: 116 case B_RGB24_BIG: 117 fBufferInfo->bits_per_pixel = 24; 118 break; 119 case B_RGB16: 120 case B_RGB16_BIG: 121 case B_RGB15: 122 case B_RGB15_BIG: 123 fBufferInfo->bits_per_pixel = 16; 124 break; 125 case B_CMAP8: 126 case B_GRAY8: 127 fBufferInfo->bits_per_pixel = 8; 128 break; 129 default: 130 syslog(LOG_ERR, 131 "unknown colorspace in DirectWindowInfo::SetState()!\n"); 132 fBufferInfo->bits_per_pixel = 0; 133 break; 134 } 135 136 fBufferInfo->pixel_format = buffer->ColorSpace(); 137 fBufferInfo->layout = B_BUFFER_NONINTERLEAVED; 138 fBufferInfo->orientation = B_BUFFER_TOP_TO_BOTTOM; 139 // TODO 140 fBufferInfo->window_bounds = to_clipping_rect(windowFrame); 141 142 const int32 kMaxClipRectsCount = (DIRECT_BUFFER_INFO_AREA_SIZE 143 - sizeof(direct_buffer_info)) / sizeof(clipping_rect); 144 145 fBufferInfo->clip_list_count = min_c(clipRegion.CountRects(), 146 kMaxClipRectsCount); 147 fBufferInfo->clip_bounds = clipRegion.FrameInt(); 148 149 for (uint32 i = 0; i < fBufferInfo->clip_list_count; i++) 150 fBufferInfo->clip_list[i] = clipRegion.RectAtInt(i); 151 } 152 153 return _SyncronizeWithClient(); 154 } 155 156 157 void 158 DirectWindowInfo::EnableFullScreen(const BRect& frame, window_feel feel) 159 { 160 fOriginalFrame = frame; 161 fOriginalFeel = feel; 162 fFullScreen = true; 163 } 164 165 166 void 167 DirectWindowInfo::DisableFullScreen() 168 { 169 fFullScreen = false; 170 } 171 172 173 status_t 174 DirectWindowInfo::_SyncronizeWithClient() 175 { 176 // Releasing this semaphore causes the client to call 177 // BDirectWindow::DirectConnected() 178 status_t status = release_sem(fSem); 179 if (status != B_OK) 180 return status; 181 182 // Wait with a timeout of half a second until the client exits 183 // from its DirectConnected() implementation 184 do { 185 status = acquire_sem_etc(fAcknowledgeSem, 1, B_TIMEOUT, 500000); 186 } while (status == B_INTERRUPTED); 187 188 return status; 189 } 190