Мое приложение имеет несколько представлений, которые используют свои собственные SDL_Window
а также SDL_Renderer
использование средства визуализации для отрисовки всех моих слоев листов в главном виде (основной вид содержит комбинированный результат рендеринга нескольких слоев листов, а другие представления предназначены для отображения каждого отдельного слоя в «панели слоев» в стиле фотошопа). ). Проблема здесь заключается в попытке взять текстуру (или поверхность, рендерер и т. Д.) И отобразить ее в другом автономном представлении. Если я использую SetRenderTarget
а также SDL_RenderCopy
, он терпит неудачу, потому что целевая текстура принадлежит другому рендереру …
Я также пытался заблокировать пиксели текстуры каждого вида, пытаясь вручную скопировать пиксели, но заблокировать пиксели не удалось, если текстура не была создана как потоковая текстура … Кроме того, представления имеют разные размеры, поэтому целевую текстуру нужно будет растянуть, чтобы она соответствовала, вызывая больше работы, чем необходимо.
Это привело меня к использованию SDL_SoftStretch
… который работает, но, конечно, болезненно медленный, так как не может использоваться с аппаратно ускоренными текстурами.
Существует ли какой-либо правдоподобный, достаточно эффективный способ получения результата одного SDL_Window
и рендеринг уменьшенной версии его версии в другую?
РЕДАКТИРОВАТЬ:
Помимо тесного использования SDL_SoftStretch
, это самое близкое, что я пришел, чтобы заставить вещи работать …
Это терпит неудачу, потому что я ударил другую кирпичную стену, когда искал способ получить данные о пикселях от рендерера:
//...
BOOL SDLView::Init()
{
m_sdlWindow = SDL_CreateWindowFrom( (PVOID)m_hWndParent );
if(m_sdlWindow == NULL)
return false;
m_sdlRenderer = SDL_CreateRenderer(m_sdlWindow, -1, SDL_RendererFlags::SDL_RENDERER_ACCELERATED);
if(m_sdlRenderer == NULL)
return false;
memset(&m_rect, 0, sizeof(SDL_Rect));
SDL_GetRendererOutputSize(m_sdlRenderer, &m_rect.w, &m_rect.h);
m_pixelFormat = SDL_GetWindowPixelFormat(m_sdlWindow);
m_sdlTexture = SDL_CreateTexture(m_sdlRenderer, m_pixelFormat, SDL_TEXTUREACCESS_STREAMING, m_rect.w, m_rect.h);
SDL_SetRenderDrawColor(m_sdlRenderer, 0x64, 0x95, 0xED, 0xFF);
return true;
}
BOOL SDLView::Clear()
{
memset(&m_rect, 0, sizeof(SDL_Rect));
SDL_GetRendererOutputSize(m_sdlRenderer, &m_rect.w, &m_rect.h);
return SDL_RenderClear(m_sdlRenderer) == 0;
}
VOID SDLView::Present()
{
// Doesn't work because we still have no way of grabbing the rendered output!!
SDL_RenderPresent(m_sdlRenderer);
int result = SDL_RenderCopy(m_sdlRenderer, m_sdlTexture, NULL, NULL);
if(result != 0) {
std::string err(SDL_GetError());
DebugBreak();
}
}
void CLayerListItem::OnPaint()
{
CWnd::OnPaint();
CRect rc;
GetClientRect(&rc);
if(m_destView != nullptr)
{
m_destView->Clear();
if(m_srcView != nullptr)
{
int srcPitch = 0, destPitch = 0;
void *srcPixels = nullptr, *destPixels = nullptr;
// Lock the source pixels
int ret = SDL_LockTexture(m_srcView->GetTexture(), &m_srcView->GetRect(), &srcPixels, &srcPitch);
if(ret != 0) {
std::string err(SDL_GetError());
DebugBreak();
}
// Lock the destination pixels
ret = SDL_LockTexture(m_destView->GetTexture(), &m_destView->GetRect(), &destPixels, &destPitch);
if(ret != 0) {
std::string err(SDL_GetError());
DebugBreak();
}
// Unlock all pixels
SDL_UnlockTexture(m_destView->GetTexture());
SDL_UnlockTexture(m_srcView->GetTexture());
// Update our destinaition texture
// (I have tried every possible combination for this line, still no dice!)
int result = SDL_UpdateTexture(
m_destView->GetTexture(),
&m_destView->GetRect(),
srcPixels, srcPitch
);
if(ret != 0) {
std::string err(SDL_GetError());
DebugBreak();
}
SDL_RenderCopy(m_destView->GetRenderer(), m_destView->GetTexture(), NULL, NULL);
OutputDebugStringA("[RENDERED!]...\n");
}
m_destView->Present();
}
}
Каждое несколько секунд отправляется событие OnPaint, которое в свою очередь пытается получить обработанный вывод и сохранить его в m_destView
(который, как m_srcView
, является SDLView). В лучшем случае это приводит к правильно отображаемому основному виду («исходному виду»), но к цели как к черному. У меня такое чувство, что я уже все перепробовал, разве что-то помимо того, что я уже пробовал … есть идеи?
Я вроде, как бы, что-то вроде решил это, используя несколько медленно — (все же, все же лучше, чем SDL_SoftRect
) — функция SDL_RenderReadPixels
:
VOID SDLView::CopyTo(SDLView *targetView)
{
int result = SDL_RenderReadPixels(m_sdlRenderer, nullptr, m_pixelFormat, m_sdlSurface->pixels, m_sdlSurface->pitch);
if(result != 0) {
std::string err(SDL_GetError());
OutputDebugStringA(err.c_str());
return;
}
SDL_Texture *destTexture = targetView->GetTexture();
result = SDL_UpdateTexture(destTexture, nullptr, m_sdlSurface->pixels, m_sdlSurface->pitch);
if(result != 0) {
std::string err(SDL_GetError());
OutputDebugStringA(err.c_str());
return;
}
}
Хорошо работает в паре с m_sdlSurface = SDL_GetWindowSurface(m_sdlWindow)
так же как m_pixelFormat = SDL_GetWindowPixelFormat(m_sdlWindow)
…
Тем не менее, обратите внимание, что это НЕ помогает при уменьшении изображения, что, вероятно, означает, что мне все равно нужно будет использовать RenderCopyEx или эквивалент в какой-то момент перед предоставлением окончательного изображения в пункт назначения.
Но пока я отмечу это как ответ, пока кто-то не сможет предложить лучшее решение.