OSDN Git Service

Add full color range support
[android-x86/external-IA-Hardware-Composer.git] / os / linux / pixeluploader.cpp
1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include "pixeluploader.h"
18
19 #include "displayplanemanager.h"
20 #include "framebuffermanager.h"
21 #include "hwctrace.h"
22 #include "hwcutils.h"
23 #include "nativegpuresource.h"
24 #include "nativesurface.h"
25 #include "overlaylayer.h"
26 #include "renderer.h"
27 #include "resourcemanager.h"
28
29 #include <nativebufferhandler.h>
30
31 #include <sys/mman.h>
32
33 namespace hwcomposer {
34
35 #define DMA_BUF_SYNC_READ (1 << 0)
36 #define DMA_BUF_SYNC_WRITE (2 << 0)
37 #define DMA_BUF_SYNC_RW (DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE)
38 #define DMA_BUF_SYNC_START (0 << 2)
39 #define DMA_BUF_SYNC_END (1 << 2)
40 #define DMA_BUF_BASE 'b'
41 #define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
42
43 struct dma_buf_sync {
44   __u64 flags;
45 };
46
47 PixelUploader::PixelUploader(const NativeBufferHandler* buffer_handler)
48     : HWCThread(-8, "PixelUploader"), buffer_handler_(buffer_handler) {
49   if (!cevent_.Initialize())
50     return;
51
52   fd_chandler_.AddFd(cevent_.get_fd());
53   gpu_fd_ = buffer_handler_->GetFd();
54 }
55
56 PixelUploader::~PixelUploader() {
57 }
58
59 void PixelUploader::Initialize() {
60   if (!InitWorker()) {
61     ETRACE("Failed to initalize PixelUploader. %s", PRINTERROR());
62   }
63 }
64
65 void PixelUploader::RegisterPixelUploaderCallback(
66     std::shared_ptr<RawPixelUploadCallback> callback) {
67   callback_ = callback;
68 }
69
70 void PixelUploader::UpdateLayerPixelData(
71     HWCNativeHandle handle, uint32_t original_width, uint32_t original_height,
72     uint32_t original_stride, void* callback_data, uint8_t* byteaddr,
73     PixelUploaderLayerCallback* layer_callback, HwcRect<int> surfaceDamage) {
74   pixel_data_lock_.lock();
75   pixel_data_.emplace_back();
76   PixelData& temp = pixel_data_.back();
77   temp.handle_ = handle;
78   temp.original_width_ = original_width;
79   temp.original_height_ = original_height;
80   temp.original_stride_ = original_stride;
81   temp.callback_data_ = callback_data;
82   temp.data_ = byteaddr;
83   temp.layer_callback_ = layer_callback;
84   temp.surfaceDamage = surfaceDamage;
85
86   tasks_lock_.lock();
87   tasks_ |= kRefreshRawPixelMap;
88   tasks_lock_.unlock();
89   Resume();
90   pixel_data_lock_.unlock();
91   Wait();
92 }
93
94 void PixelUploader::Synchronize() {
95   sync_lock_.lock();
96   sync_lock_.unlock();
97 }
98
99 void PixelUploader::ExitThread() {
100   HWCThread::Exit();
101   std::vector<PixelData>().swap(pixel_data_);
102 }
103
104 void PixelUploader::HandleExit() {
105 }
106
107 void PixelUploader::HandleRoutine() {
108   HandleRawPixelUpdate();
109 }
110
111 void PixelUploader::Wait() {
112   if (fd_chandler_.Poll(-1) <= 0) {
113     ETRACE("Poll Failed in DisplayManager %s", PRINTERROR());
114     return;
115   }
116
117   if (fd_chandler_.IsReady(cevent_.get_fd())) {
118     // If eventfd_ is ready, we need to wait on it (using read()) to clean
119     // the flag that says it is ready.
120     cevent_.Wait();
121   }
122 }
123
124 void PixelUploader::HandleRawPixelUpdate() {
125   tasks_lock_.lock();
126   tasks_ &= ~kRefreshRawPixelMap;
127   tasks_lock_.unlock();
128
129   pixel_data_lock_.lock();
130   sync_lock_.lock();
131   if (pixel_data_.empty()) {
132     pixel_data_lock_.unlock();
133     sync_lock_.unlock();
134     return;
135   }
136
137   std::vector<PixelData> texture_uploads;
138   for (auto& buffer : pixel_data_) {
139     texture_uploads.emplace_back(buffer);
140   }
141
142   std::vector<PixelData>().swap(pixel_data_);
143   pixel_data_lock_.unlock();
144   bool signal = true;
145
146   for (auto& buffer : texture_uploads) {
147     if (callback_) {
148       // Notify everyone that we are going to access this data.
149       callback_->Callback(true, buffer.callback_data_);
150       if (signal) {
151         cevent_.Signal();
152         signal = false;
153       }
154     }
155
156     uint8_t* ptr = NULL;
157     size_t size = buffer.handle_->meta_data_.height_ *
158                   buffer.handle_->meta_data_.pitches_[0];
159     uint32_t prime_fd = buffer.handle_->meta_data_.prime_fds_[0];
160
161     uint32_t mapStride = buffer.original_stride_;
162     uint32_t bpp = mapStride / buffer.original_width_;
163     uint32_t x1 = buffer.surfaceDamage.left, y1 = buffer.surfaceDamage.top;
164     uint32_t x2 = buffer.surfaceDamage.right, y2 = buffer.surfaceDamage.bottom;
165     uint32_t startx = x1 * bpp;
166     uint32_t block_size = (x2 - x1) * bpp;
167
168     if (prime_fd > 0) {
169       ptr = (uint8_t*)Map(buffer.handle_->meta_data_.prime_fds_[0], size);
170     }
171
172     if (!ptr) {
173       // FIXME: Create texture and do texture upload.
174     } else {
175       for (int i = y1; i < y2; i++) {
176         memcpy(ptr + (i * buffer.handle_->meta_data_.pitches_[0] + startx),
177                buffer.data_ + (i * mapStride + startx), block_size);
178       }
179     }
180
181     if (ptr)
182       Unmap(buffer.handle_->meta_data_.prime_fds_[0], ptr, size);
183
184     if (callback_) {
185       // Notify everyone that we are done accessing this data.
186       callback_->Callback(false, buffer.callback_data_);
187     }
188
189     if (buffer.layer_callback_) {
190       buffer.layer_callback_->UploadDone();
191     }
192   }
193
194   sync_lock_.unlock();
195 }
196
197 void* PixelUploader::Map(uint32_t prime_fd, size_t size) {
198   void* addr =
199       mmap(nullptr, size, (PROT_READ | PROT_WRITE), MAP_SHARED, prime_fd, 0);
200   if (addr == MAP_FAILED)
201     return nullptr;
202
203   struct dma_buf_sync sync_start = {0};
204   sync_start.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
205   int rv = ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_start);
206   if (rv) {
207     ETRACE("DMA_BUF_IOCTL_SYNC failed during Map \n");
208     munmap(addr, size);
209     return nullptr;
210   }
211
212   return addr;
213 }
214
215 void PixelUploader::Unmap(uint32_t prime_fd, void* addr, size_t size) {
216   if (addr) {
217     struct dma_buf_sync sync_start = {0};
218     sync_start.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
219     ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_start);
220     munmap(addr, size);
221   }
222 }
223
224 }  // namespace hwcomposer