mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-26 22:48:19 +00:00
152 lines
4.9 KiB
C++
152 lines
4.9 KiB
C++
/*
|
|
Copyright (C) 2009 Red Hat, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of
|
|
the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "red_drawable.h"
|
|
#include "pixels_source_p.h"
|
|
#include "utils.h"
|
|
#include "threads.h"
|
|
|
|
static const uint64_t lock_timout = 1000 * 1000 * 10; /*10ms*/
|
|
|
|
void RedDrawable::copy_pixels(const PixelsSource& src, int src_x, int src_y, const Rect& dest)
|
|
{
|
|
PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
|
|
PixelsSource_p* src_p_data = (PixelsSource_p*)src.get_opaque();
|
|
|
|
for (;;) {
|
|
Lock lock(*dest_p_data->_mutex);
|
|
Lock timed_lock(*src_p_data->_mutex, lock_timout);
|
|
if (!timed_lock.is_locked()) {
|
|
continue;
|
|
}
|
|
BitBlt(dest_p_data->dc, dest.left + _origin.x, dest.top + _origin.y,
|
|
dest.right - dest.left, dest.bottom - dest.top,
|
|
src_p_data->dc, src_x + src._origin.x,
|
|
src_y + src._origin.y, SRCCOPY);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void RedDrawable::blend_pixels(const PixelsSource& src, int src_x, int src_y, const Rect& dest)
|
|
{
|
|
static BLENDFUNCTION blend_func = { AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA};
|
|
|
|
int width = dest.right - dest.left;
|
|
int height = dest.bottom - dest.top;
|
|
PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
|
|
PixelsSource_p* src_p_data = (PixelsSource_p*)src.get_opaque();
|
|
for (;;) {
|
|
Lock lock(*dest_p_data->_mutex);
|
|
Lock timed_lock(*src_p_data->_mutex, lock_timout);
|
|
if (!timed_lock.is_locked()) {
|
|
continue;
|
|
}
|
|
AlphaBlend(dest_p_data->dc, dest.left + _origin.x, dest.top + _origin.y, width, height,
|
|
src_p_data->dc, src_x + src._origin.x, src_y + src._origin.y, width, height,
|
|
blend_func);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void RedDrawable::combine_pixels(const PixelsSource& src, int src_x, int src_y, const Rect& dest,
|
|
CombineOP op)
|
|
{
|
|
DWORD rop;
|
|
switch (op) {
|
|
case OP_COPY:
|
|
rop = SRCCOPY;
|
|
break;
|
|
case OP_AND:
|
|
rop = SRCAND;
|
|
break;
|
|
case OP_XOR:
|
|
rop = SRCINVERT;
|
|
break;
|
|
default:
|
|
THROW("invalid op %d", op);
|
|
}
|
|
|
|
PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
|
|
PixelsSource_p* src_p_data = (PixelsSource_p*)src.get_opaque();
|
|
for (;;) {
|
|
Lock lock(*dest_p_data->_mutex);
|
|
Lock timed_lock(*src_p_data->_mutex, lock_timout);
|
|
if (!timed_lock.is_locked()) {
|
|
continue;
|
|
}
|
|
BitBlt(dest_p_data->dc, dest.left + _origin.x, dest.top + _origin.y,
|
|
dest.right - dest.left, dest.bottom - dest.top,
|
|
src_p_data->dc, src_x + src._origin.x,
|
|
src_y + src._origin.y, rop);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void RedDrawable::erase_rect(const Rect& rect, rgb32_t color)
|
|
{
|
|
RECT r;
|
|
r.left = rect.left + _origin.x;
|
|
r.right = rect.right + _origin.x;
|
|
r.top = rect.top + _origin.y;
|
|
r.bottom = rect.bottom + _origin.y;
|
|
|
|
PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
|
|
Lock lock(*dest_p_data->_mutex);
|
|
FillRect(dest_p_data->dc, &r, (HBRUSH)GetStockObject(BLACK_BRUSH));
|
|
}
|
|
|
|
void RedDrawable::fill_rect(const Rect& rect, rgb32_t color)
|
|
{
|
|
RECT r;
|
|
r.left = rect.left + _origin.x;
|
|
r.right = rect.right + _origin.x;
|
|
r.top = rect.top + _origin.y;
|
|
r.bottom = rect.bottom + _origin.y;
|
|
|
|
HBRUSH brush = CreateSolidBrush(RGB(rgb32_get_red(color),
|
|
rgb32_get_green(color),
|
|
rgb32_get_blue(color)));
|
|
for (;;) {
|
|
PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
|
|
Lock lock(*dest_p_data->_mutex);
|
|
FillRect(dest_p_data->dc, &r, brush);
|
|
break;
|
|
}
|
|
DeleteObject(brush);
|
|
}
|
|
|
|
void RedDrawable::frame_rect(const Rect& rect, rgb32_t color)
|
|
{
|
|
RECT r;
|
|
r.left = rect.left + _origin.x;
|
|
r.right = rect.right + _origin.x;
|
|
r.top = rect.top + _origin.y;
|
|
r.bottom = rect.bottom + _origin.y;
|
|
HBRUSH brush = CreateSolidBrush(RGB(rgb32_get_red(color),
|
|
rgb32_get_green(color),
|
|
rgb32_get_blue(color)));
|
|
for (;;) {
|
|
PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
|
|
Lock lock(*dest_p_data->_mutex);
|
|
FrameRect(dest_p_data->dc, &r, brush);
|
|
break;
|
|
}
|
|
DeleteObject(brush);
|
|
}
|
|
|