DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 14.02.09 20:22
Оценка:
В общем возникла проблема.
Есть программа которая гонит видеопоток с нескольких камер в RGB32.

И отрисовывает каждый кадр. Т.е используется самописный рендерер. Работает хорошо НО.

Если область отображения близка по размерам к исходному фрейму, если же кадр 640 на 480 отрисовать на весь экран FPS падает с 25 до 2-3!

при этом загрузка процессора не растет , такое впечатление что серьёзно задумывается видео карта. Особенно видно проблему если программа выводит изображение на 4 отдельных монитора. Загрузка процессора 30%, 4фпс, снижение разрешение уменьшает проблему но не снимает.

Скажите что я могу потенциально делать неправильно?

Или Какими функциями директХ лучше пользоваться для рендеринга маленьких картинок на всю площадь монитора (т.е чтоб их сразу и масштабировало), либо может какие то особенности видеокарты использовать карты GeForce последних моделей в основном.

Заранее спасибо.
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re: DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 14.02.09 20:33
Оценка:
т.е я рисую полученные из семпл граббера кадры сам, без использования VMR9.
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re: DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 14.02.09 21:37
Оценка:
На сколько использование Оверлеев может упростить жизнь? Или это не то?
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re: DirectX тормоза при масштабировании картинки
От: 8bit  
Дата: 15.02.09 11:21
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

Вы через DirectX рисуете? Каким способом?
Re[2]: DirectX тормоза при масштабировании картинки
От: CTpaHHoe Россия http://ctpahhoe.blogspot.com/
Дата: 15.02.09 12:23
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

>> т.е я рисую полученные из семпл граббера кадры сам, без использования VMR9


не одного меня твой способ рисования озадачил. можно было бы и кусочек кода показать


AS>На сколько использование Оверлеев может упростить жизнь? Или это не то?


жизнь оно не упростит, но производительность поднимет. только это уже не direct show, а direct draw.

расскажу вкратце, как это было сделано у нас.

у нас картинка приходит с различной частотой из разных источников. приходит и остаётся в буфере. при этом выставляется соответствующий флажок на обновление. рисование на внеэкранной поверхности осуществляет отдельный поток, обладающий знанием о z-порядке буферов — ведь в случае обновления "нижней" картинки приходится вспомнить и про верхнюю. в итоге имеем источники с 2fps и 80fps, а отображение происходит со стабильной частотой 20-25fps, что положительно влияет на загрузку cpu (точней, частота отображения определяется наиболее активным источником, но не превосходит заданную границу).
сразу к делу, без приветов. осторожно, злой антиспам
Re[3]: DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 16.02.09 13:56
Оценка:
CTH>не одного меня твой способ рисования озадачил. можно было бы и кусочек кода показать

Сейчас каждый кадр отрисовывается через DirectX поверхность, с ресайзом. После, накладывается текстура, содержащая элементы управления.

CTH>жизнь оно не упростит, но производительность поднимет. только это уже не direct show, а direct draw.


а директХ это ж, по идее более продвинутый вариант, почему он менее производительный?


CTH>расскажу вкратце, как это было сделано у нас.


CTH>у нас картинка приходит с различной частотой из разных источников. приходит и остаётся в буфере. при этом выставляется соответствующий флажок на обновление. рисование на внеэкранной поверхности осуществляет отдельный поток, обладающий знанием о z-порядке буферов — ведь в случае обновления "нижней" картинки приходится вспомнить и про верхнюю. в итоге имеем источники с 2fps и 80fps, а отображение происходит со стабильной частотой 20-25fps, что положительно влияет на загрузку cpu (точней, частота отображения определяется наиболее активным источником, но не превосходит заданную границу).



о спасибо, тут подумаю. Но сначала надо с первым вопросом разобраться.
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re: DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 16.02.09 14:22
Оценка:
d3d_dev_->Clear( 0, NULL, D3DCLEAR_TARGET, aRenderer->bg_color_, 1.0f, 0 );
d3d_dev_->BeginScene();
d3d_dev_->EndScene();
HRESULT hr = d3d_dev_->Present( NULL, NULL, NULL, NULL );


пообрезал код, обнаружил что загрузка процессора растет при росте площади, хотя не должна, ведь сайзит то видяха. Т.е что то не так с этим директХ сайзом. Жаэе если я ничего реально не рисую вот этот блок грузит проц
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[2]: DirectX тормоза при масштабировании картинки
От: 8bit  
Дата: 16.02.09 15:34
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

AS>Жаэе если я ничего реально не рисую вот этот блок грузит проц

Любой код грузит проц.

Адексей, покажите код которым вы рисуете и как загоняете данные.

через DirectX поверхность

Это что Вы под этим имеете ввиду? Через текстуру?
Re[3]: DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 16.02.09 20:59
Оценка:
AS>>Жаэе если я ничего реально не рисую вот этот блок грузит проц
8>Любой код грузит проц.

Это да, но почему при большей области рендерера РАСТЕТ загрузка если реально ничего не рисуется.

8>Адексей, покажите код которым вы рисуете и как загоняете данные.

8>

8> через DirectX поверхность

8>Это что Вы под этим имеете ввиду? Через текстуру?


RetStatus
VideoRenderer::RTSurface::DrawInProjection(
    VideoRenderer* aRenderer, RECT* aSrcRect, RECT* aDestRect)
{
    assert(aRenderer != 0);
    if (surface_ ==0 )
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    IDirect3DDevice9* device = 0;
    if (RS_OK != ((HWStateDirctX*)(aRenderer->getCurrentState()))->getD3DDevice(&device))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    IDirect3DSurface9* backBuf = 0;
    if (device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuf) != D3D_OK)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    HRESULT hr;
    hr = device->StretchRect(surface_, aSrcRect, backBuf, aDestRect, D3DTEXF_LINEAR);
    if(D3D_OK != hr) {
        hr = device->StretchRect(surface_, aSrcRect, backBuf, aDestRect, D3DTEXF_NONE);
    }

    backBuf->Release();
    return hr == D3D_OK? RS_OK: RS_ERR;
}



RetStatus
VideoRenderer::RTTexture::DrawInProjection(
    VideoRenderer* aRenderer, RECT* srcRect, RECT* destRect)
{
    assert(aRenderer != 0);

    if ((texture_ == 0) || (vert_buffer_ == 0))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    IDirect3DDevice9* device = 0;
    if (RS_OK != ((HWStateDirctX*)(aRenderer->getCurrentState()))->getD3DDevice(&device))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }


    HRESULT hr;

    {
        SquareVertexBuffer squareVerts=
        {{
            {(float)destRect->left, (float)destRect->top,        0.0f,    1.0f,
                (float)(((double)srcRect->left + 0.5f) / texture_width_),
                (float)(((double)srcRect->top + 0.5f) / texture_height_)},
            {(float)destRect->right, (float)destRect->top,        0.0f,    1.0f,
                (float)(((double)srcRect->right + 0.5f) / texture_width_),
                (float)(((double)srcRect->top + 0.5f) / texture_height_)},
            {(float)destRect->left, (float)destRect->bottom,    0.0f,    1.0f,
                (float)(((double)srcRect->left + 0.5f) / texture_width_),
                (float)(((double)srcRect->bottom + 0.5f) / texture_height_)},
            {(float)destRect->right, (float)destRect->bottom,    0.0f,    1.0f,
                (float)(((double)srcRect->right + 0.5f) / texture_width_),
                (float)(((double)srcRect->bottom + 0.5f) / texture_height_)}
        }};

        void* pBuf;
        hr = vert_buffer_->Lock(0, sizeof(squareVerts), &pBuf, 0);
        if(D3D_OK == hr) {
            memcpy(pBuf, &squareVerts, sizeof(squareVerts));
            vert_buffer_->Unlock();
        } else {
            return hr == D3D_OK? RS_OK: RS_ERR;
            //NOTREACHED
        }
    }

    hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, TRIANGLES_COUNT);

    return hr == D3D_OK? RS_OK: RS_ERR;
}



ниже привожу, на всякий случай, файл целиком, там основа чужая и какая то горбатая, вот сижу разбираюсь пока шефы по голове стучат думаю может проще все сделать проще но хочу понять НА ЧЕМ и КАК делать то надо. потому что при отображении видео на втором мониторе (если монитров два) уже приводит к тормозам. На крутом серваке запутсил загрузка вообще около 5% и фпс такойже... не могу понять куда копать, думаю что неправильная идея в целом... но почему?


//
// -*- Mode: c++; tab-width: 4; -*-
// -*- ex: ts=4 -*-
//

//
// Copyright 2007 VIT Ltd. All rights reserved.
// VIT PROPRIETARY/CONFIDENTIAL.
//
// $Id$
//

#ifdef _DEBUG
# define D3D_DEBUG_INFO
#endif

#define MULTITHREADED_D3D

#ifdef MULTITHREADED_D3D
# define _D3DDEV_FLAGS (D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED)
#else
# define _D3DDEV_FLAGS (D3DCREATE_SOFTWARE_VERTEXPROCESSING)
#endif


#include <Vombat/VideoRenderer.h>
#include <assert.h>
#include "include/VResWin32Lib.h"
using namespace std;

namespace VR
{
/////////
VideoRenderer::VRResource::VRResource()
{

}

VideoRenderer::VRResource::~VRResource()
{

}

/////////


VideoRenderer::ProjectableResource::ProjArray::iterator
VideoRenderer::ProjectableResource::FindProjection(ProjectionID aProjID)
{
    ProjArray::iterator curRes;
    for(curRes = projections_.begin(); curRes != projections_.end(); ++curRes)
    {
        if (curRes->proj_id_ == aProjID)
        {
            return curRes;
            /*NOTREACHED*/
        }
    }
    return curRes;
}

RetStatus
VideoRenderer::ProjectableResource::controlResource(
    VideoRenderer* aRenderer, ControlStruct* aControlStruct)
{
    ProjArray::iterator curProj;
    assert(aRenderer != 0);
    assert(aControlStruct != 0);

    switch (aControlStruct->code_)
    {
    case (VR_CC_SET_PROJECTION_RECTS):
        {
            cmdSetProjectionRects* setRects = (cmdSetProjectionRects*)aControlStruct;
            curProj = FindProjection(setRects->projection_);
            if (curProj != projections_.end())
            {
                projections_.erase(curProj);
            }
            ProjDesc projDesc;
            projDesc.proj_id_ = setRects->projection_;

            projDesc.is_dest_valid_ = false;
            if (setRects->dest_rect_ != 0)
            {
                projDesc.is_dest_valid_ = true;
                projDesc.dest_rect_ = *setRects->dest_rect_;
            }
            projDesc.is_src_valid_ = false;
            if (setRects->src_rect_ != 0)
            {
                projDesc.is_src_valid_ = true;
                projDesc.src_rect_ = *setRects->src_rect_;
            }

            projections_.push_back(projDesc);

            return RS_OK;
            /*NOTREACHED*/
        }
    case (VR_CC_DELETE_PROJECTION):
        curProj = FindProjection(((cmdDeleteProjection*)aControlStruct)->projection_);
        if (curProj == projections_.end())
        {
            return RS_ERR;
            /*NOTREACHED*/
        }
        projections_.erase(curProj);
        return RS_OK;
        /*NOTREACHED*/
    default:
        return controlProjectedResource(aRenderer, aControlStruct);
        /*NOTREACHED*/
    }
    return RS_OK;
}

RetStatus
VideoRenderer::ProjectableResource::ApplyToScene(VideoRenderer* aRenderer)
{
    assert(aRenderer != 0);

    if (projections_.empty())
    {
        return RS_OK;
        /*NOTREACHED*/
    }

    RetStatus rs = BeforeDraw(aRenderer);
    if (rs != RS_OK)
    {
        return rs;
        /*NOTREACHED*/
    }

    ProjArray::iterator curProj;
    for(curProj = projections_.begin(); curProj != projections_.end(); ++curProj)
    {
        RECT srcRect, destRect;
        if (curProj->is_dest_valid_)
        {
            destRect = curProj->dest_rect_;
        }
        else
        {
            //aRenderer->getDeviceSize(&destRect);
            //GetWindowRect
            GetClientRect
                (aRenderer->hwnd_, &destRect);
            destRect.right -= destRect.left;
            destRect.bottom -= destRect.top;
            destRect.left = destRect.top = 0;
        }

        if (curProj->is_src_valid_)
        {
            srcRect = curProj->src_rect_;
        }
        else
        {
            cmdGetImageType imgType;
            if (controlProjectedResource(aRenderer, &imgType) != RS_OK)
                continue;
                /*NOTREACHED*/
            srcRect.left = srcRect.top = 0;
            srcRect.right = imgType.width_;
            srcRect.bottom = imgType.height_;
        }

        {
            cmdGetImageType imgType;
            if (RS_OK == controlProjectedResource(aRenderer, &imgType))
            {
                if(D3DFMT_UYVY == imgType.format_ || D3DFMT_YUY2 == imgType.format_)
                {
                    srcRect.left -= srcRect.left % 2;
                    srcRect.right -= srcRect.right % 2;
                }
            }
            }
        DrawInProjection(aRenderer, &srcRect, &destRect);
    }

    return AfterDraw(aRenderer);
}

/////////

#define UNDEFINED_SURF_PARAM ((ImgFormat)-1)
VideoRenderer::AbstractImage::AbstractImage()
    : img_draw_proc_(0)
    , format_(UNDEFINED_SURF_PARAM)
{

}

RetStatus
VideoRenderer::AbstractImage::CallCallback(VideoRenderer* aRenderer)
{
    assert(aRenderer != 0);

    ResID curID;
    if (!aRenderer->getResourceID(this, curID))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    if (img_draw_proc_ != 0)
        img_draw_proc_(aRenderer, curID, proc_param_);

    return  RS_OK;
}


RetStatus
VideoRenderer::AbstractImage::controlProjectedResource(
    VideoRenderer* aRenderer, ControlStruct* controlStruct)
{
    assert(aRenderer != 0);
    switch (controlStruct->code_)
    {
    case (VR_CC_SET_IMAGE_TYPE):
        {
            cmdSetImageType* imgType = (cmdSetImageType*)controlStruct;
            if ((format_ == imgType->format_) &&
                (width_ == imgType->width_) &&
                (height_ == imgType->height_) &&
                (format_ != UNDEFINED_SURF_PARAM) &&
                isRestored()
            )
            {
                return RS_OK;
                /*NOTREACHED*/
            }
            freeResources();
            format_ = imgType->format_;
            width_ = imgType->width_;
            height_ = imgType->height_;

            return restoreResource(aRenderer);
            /*NOTREACHED*/
        }
    case (VR_CC_GET_IMAGE_TYPE):
        {
            if (format_ == (ImgFormat)UNDEFINED_SURF_PARAM)
                return RS_ERR;
                /*NOTREACHED*/
            cmdGetImageType* imgType = (cmdGetImageType*)controlStruct;
            imgType->format_ = format_;
            imgType->width_ = width_;
            imgType->height_ = height_;
            return RS_OK;
            /*NOTREACHED*/
        }
    case (VR_CC_LOCK_IMAGE):
        {
            cmdLockImage* cmdLock = (cmdLockImage*)controlStruct;
            RetStatus rs;
            cmdLock->p_bits_ = 0;
            RECT allImgRect;
            allImgRect.left = allImgRect.top = 0;
            allImgRect.right = width_;
            allImgRect.bottom = height_;
            RECT* lockRect = &allImgRect;
            if(cmdLock->lock_rect_ != 0)
            {
                lockRect = cmdLock->lock_rect_;
            }
            rs = LockImageProc(lockRect, &cmdLock->pitch_, &cmdLock->p_bits_);
            if (rs != RS_OK)
            {
                return rs;
                /*NOTREACHED*/
            }
            return RS_OK;
            /*NOTREACHED*/
        }
    case (VR_CC_UNLOCK_IMAGE):
        {
            RetStatus rs;
            rs = UnlockImageProc();
            return rs;
            /*NOTREACHED*/
        }
    case (VR_CC_SET_IMG_DRAW_PROC):
        {
            img_draw_proc_ = ((cmdSetImgDrawProc*)controlStruct)->draw_proc_;
            proc_param_ = ((cmdSetImgDrawProc*)controlStruct)->proc_param_;
            return RS_OK;
            /*NOTREACHED*/
        }
    default:
        return RS_NOTIMPLEMENTED;
        /*NOTREACHED*/
    }
    return RS_OK;
}

//////////

bool
VideoRenderer::RTGDIImage::isRestored()
{
    return (NULL != compatible_dc_) && (NULL != dib_section_);
}

VideoRenderer::RTGDIImage::RTGDIImage(bool hasAlpha)
{
    RTGDIImage();
    has_alpha_ = hasAlpha;
}

VideoRenderer::RTGDIImage::RTGDIImage()
    :compatible_dc_(0), dib_section_(0),prev_bitmap_(0), img_data_(0)
{
    unlock_called_ = false;
}

RetStatus
VideoRenderer::RTGDIImage::BeforeDraw(VideoRenderer* aRenderer)
{
    return RS_OK;
}

RetStatus
VideoRenderer::RTGDIImage::AfterDraw(VideoRenderer* aRenderer)
{
    return RS_OK;
}

RetStatus
VideoRenderer::RTGDIImage::DrawInProjection(
    VideoRenderer* aRenderer, RECT* aSrcRect, RECT* aDestRect)
{
    assert(aRenderer != 0);
    if (NULL == compatible_dc_ || NULL == dib_section_)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    HDC wndDC = ((HWStateGDI*)aRenderer->current_state_)->mem_dc_;
    SetStretchBltMode(wndDC, HALFTONE);
    if(has_alpha_)
    {
        BLENDFUNCTION bf;
        bf.BlendOp = AC_SRC_OVER;
        bf.BlendFlags = 0;
        bf.SourceConstantAlpha = 0xFF;
        bf.AlphaFormat = AC_SRC_ALPHA;

        AlphaBlend(
            wndDC,
            aDestRect->left, aDestRect->top, aDestRect->right - aDestRect->left, aDestRect->bottom - aDestRect->top,
            compatible_dc_,
            aSrcRect->left, aSrcRect->top, aSrcRect->right - aSrcRect->left, aSrcRect->bottom - aSrcRect->top,
            bf
        );
    }
    else
    {
        StretchBlt(
            wndDC,
            aDestRect->left, aDestRect->top, aDestRect->right - aDestRect->left, aDestRect->bottom - aDestRect->top,
            compatible_dc_,
            aSrcRect->left, aSrcRect->top, aSrcRect->right - aSrcRect->left, aSrcRect->bottom - aSrcRect->top,
            SRCCOPY
        );
    }

    return RS_OK;
}


RetStatus
VideoRenderer::RTGDIImage::restoreResource(VideoRenderer* aRenderer)
{
    assert(aRenderer != 0);
    if (compatible_dc_ != 0 && dib_section_ != 0)
    {
        if(!unlock_called_) {
            CallCallback(aRenderer);
        }
        return RS_OK;
        /*NOTREACHED*/
    }

    freeResources();
    if(D3DFMT_A8R8G8B8 != format_) {
        return RS_ERR;
    }

    compatible_dc_ = CreateCompatibleDC(0);

    if (compatible_dc_ == 0)
        return RS_ERR;

        BITMAPINFO bmi;
        bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
        bmi.bmiHeader.biWidth = (LONG)width_;
        bmi.bmiHeader.biHeight = -(LONG)height_;
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biBitCount = 32;            //@todo:
        bmi.bmiHeader.biCompression = BI_RGB;
        bmi.bmiHeader.biSizeImage = 0;
        bmi.bmiHeader.biXPelsPerMeter = 0;
        bmi.bmiHeader.biYPelsPerMeter = 0;
        bmi.bmiHeader.biClrUsed = 0;
        bmi.bmiHeader.biClrImportant = 0;

        dib_section_ = CreateDIBSection(compatible_dc_, &bmi, DIB_RGB_COLORS, &img_data_, NULL, 0);

        prev_bitmap_ = SelectObject(compatible_dc_, (HGDIOBJ)dib_section_);
    return CallCallback(aRenderer);
}

RetStatus
VideoRenderer::RTGDIImage::LockImageProc(RECT *aLockRect, int *aPitch, void **apBits)
{
    if (img_data_ == 0)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    *aPitch = width_ * 4;            //@todo:
    *apBits = img_data_;

    return RS_OK;
}

RetStatus
VideoRenderer::RTGDIImage::UnlockImageProc()
{
    if (img_data_ == 0)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }
    unlock_called_ = true;
    return RS_OK;
}

VideoRenderer::RTGDIImage::~RTGDIImage()
{
    freeResources();
}

void
VideoRenderer::RTGDIImage::freeResources()
{
    unlock_called_ = false;
    if(compatible_dc_){
        SelectObject(compatible_dc_, prev_bitmap_);
        if(dib_section_) {
            DeleteObject(dib_section_);
            dib_section_ = 0;
        }
        DeleteObject(compatible_dc_);
        compatible_dc_ = 0;
    }
}

////////////

bool
VideoRenderer::RTSurface::isRestored()
{
    return surface_ != 0;
}

VideoRenderer::RTSurface::RTSurface()
    :surface_(0)
{
    unlock_called_ = false;
}

RetStatus
VideoRenderer::RTSurface::BeforeDraw(VideoRenderer* aRenderer)
{
    assert(aRenderer != 0);

    IDirect3DDevice9* device;
    if (RS_OK != ((HWStateDirctX*)(aRenderer->getCurrentState()))->getD3DDevice(&device))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    device->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
    device->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
    return RS_OK;
}

RetStatus
VideoRenderer::RTSurface::AfterDraw(VideoRenderer* aRenderer)
{
    assert(aRenderer != 0);
    return RS_OK;
}

RetStatus
VideoRenderer::RTSurface::DrawInProjection(
    VideoRenderer* aRenderer, RECT* aSrcRect, RECT* aDestRect)
{
    assert(aRenderer != 0);
    if (surface_ ==0 )
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    IDirect3DDevice9* device = 0;
    if (RS_OK != ((HWStateDirctX*)(aRenderer->getCurrentState()))->getD3DDevice(&device))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    IDirect3DSurface9* backBuf = 0;
    if (device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuf) != D3D_OK)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    HRESULT hr;
    hr = device->StretchRect(surface_, aSrcRect, backBuf, aDestRect, D3DTEXF_LINEAR);
    if(D3D_OK != hr) {
        hr = device->StretchRect(surface_, aSrcRect, backBuf, aDestRect, D3DTEXF_NONE);
    }

    backBuf->Release();
    return hr == D3D_OK? RS_OK: RS_ERR;
}


RetStatus
VideoRenderer::RTSurface::restoreResource(VideoRenderer* aRenderer)
{
    assert(aRenderer != 0);
    IDirect3DDevice9* device = 0;
    if (RS_OK != ((HWStateDirctX*)(aRenderer->getCurrentState()))->getD3DDevice(&device))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    if (surface_ != 0)
    {
        if(!unlock_called_) {
            CallCallback(aRenderer);
        }
        return RS_OK;
        /*NOTREACHED*/
    }

    freeResources();

    if(UNDEFINED_SURF_PARAM == format_)
    {
        return RS_ERR;
    }

    IDirect3DSurface9* newSurf;
    HRESULT hr = device->CreateOffscreenPlainSurface(
        width_,
        height_,
        (D3DFORMAT)format_,
        D3DPOOL_DEFAULT,
        &newSurf,
        0
    );

    if (hr != D3D_OK)
        return RS_ERR;

    surface_ = newSurf;
    return CallCallback(aRenderer);
}

RetStatus
VideoRenderer::RTSurface::LockImageProc(RECT *aLockRect, int *aPitch, void **apBits)
{
    if (surface_ == 0)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    D3DLOCKED_RECT lockedRect;
    if (surface_->LockRect(&lockedRect, aLockRect, D3DLOCK_DISCARD) != D3D_OK)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    *aPitch = lockedRect.Pitch;
    *apBits = lockedRect.pBits;

    return RS_OK;
}

RetStatus
VideoRenderer::RTSurface::UnlockImageProc()
{
    if (surface_ == 0)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }
    unlock_called_ = true;
    surface_->UnlockRect();

    return RS_OK;
}

VideoRenderer::RTSurface::~RTSurface()
{
    freeResources();
}

void
VideoRenderer::RTSurface::freeResources()
{
    unlock_called_ = false;
    RELEASE_COM_OBJ(surface_);
}

///////////////////

bool
VideoRenderer::RTTexture::isRestored()
{
    return ((texture_ != 0) && (vert_buffer_ != 0));
}

VideoRenderer::RTTexture::RTTexture()
    :texture_(0)
    ,vert_buffer_(0)
{
    unlock_called_ = false;
}

struct TexVertex_
{
    float x,y,z, rh;
    float tu,tv;
};
typedef TexVertex_ CurVertFmt;
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1)

struct SquareVertexBuffer
{
    CurVertFmt corners_[4];
};

#define VERTS_COUNT 4
#define TRIANGLES_COUNT 2


RetStatus
VideoRenderer::RTTexture::BeforeDraw(VideoRenderer* aRenderer)
{
    assert(aRenderer != 0);

    IDirect3DDevice9* device = 0;
    if (RS_OK != ((HWStateDirctX*)(aRenderer->getCurrentState()))->getD3DDevice(&device))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }


    if ((texture_ == 0) || (vert_buffer_ == 0))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }
    device->SetStreamSource(0, vert_buffer_, 0, sizeof(CurVertFmt));

    device->SetTexture(0, texture_);
    return RS_OK;
}

RetStatus
VideoRenderer::RTTexture::AfterDraw(VideoRenderer* aRenderer)
{
    assert(aRenderer != 0);
    return RS_OK;
}

RetStatus
VideoRenderer::RTTexture::DrawInProjection(
    VideoRenderer* aRenderer, RECT* srcRect, RECT* destRect)
{
    assert(aRenderer != 0);

    if ((texture_ == 0) || (vert_buffer_ == 0))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    IDirect3DDevice9* device = 0;
    if (RS_OK != ((HWStateDirctX*)(aRenderer->getCurrentState()))->getD3DDevice(&device))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }


    HRESULT hr;

    {
        SquareVertexBuffer squareVerts=
        {{
            {(float)destRect->left, (float)destRect->top,        0.0f,    1.0f,
                (float)(((double)srcRect->left + 0.5f) / texture_width_),
                (float)(((double)srcRect->top + 0.5f) / texture_height_)},
            {(float)destRect->right, (float)destRect->top,        0.0f,    1.0f,
                (float)(((double)srcRect->right + 0.5f) / texture_width_),
                (float)(((double)srcRect->top + 0.5f) / texture_height_)},
            {(float)destRect->left, (float)destRect->bottom,    0.0f,    1.0f,
                (float)(((double)srcRect->left + 0.5f) / texture_width_),
                (float)(((double)srcRect->bottom + 0.5f) / texture_height_)},
            {(float)destRect->right, (float)destRect->bottom,    0.0f,    1.0f,
                (float)(((double)srcRect->right + 0.5f) / texture_width_),
                (float)(((double)srcRect->bottom + 0.5f) / texture_height_)}
        }};

        void* pBuf;
        hr = vert_buffer_->Lock(0, sizeof(squareVerts), &pBuf, 0);
        if(D3D_OK == hr) {
            memcpy(pBuf, &squareVerts, sizeof(squareVerts));
            vert_buffer_->Unlock();
        } else {
            return hr == D3D_OK? RS_OK: RS_ERR;
            //NOTREACHED
        }
    }

    hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, TRIANGLES_COUNT);

    return hr == D3D_OK? RS_OK: RS_ERR;
}

RetStatus
VideoRenderer::RTTexture::restoreResource(VideoRenderer* aRenderer)
{
    IDirect3DDevice9* device = 0;
    if (RS_OK != ((HWStateDirctX*)(aRenderer->getCurrentState()))->getD3DDevice(&device))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    if (texture_ != 0)
    {
        if(!unlock_called_)
        {
            CallCallback(aRenderer);
        }
        return RS_OK;
        /*NOTREACHED*/
    }

    freeResources();

    IDirect3DTexture9* Texture = 0;

    if(UNDEFINED_SURF_PARAM == format_)
    {
        return RS_ERR;
    }

    if (D3DXCreateTexture(device, width_, height_, 1, 0,
                            format_, D3DPOOL_MANAGED, &Texture)    != D3D_OK)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    IDirect3DSurface9* surf;
    Texture->GetSurfaceLevel(0,&surf);
    D3DSURFACE_DESC desc;
    surf->GetDesc(&desc);
    surf->Release();

    texture_width_ = desc.Width;
    texture_height_ = desc.Height;
    if (desc.Format != format_)
    {
        RELEASE_COM_OBJ(Texture);
        return RS_ERR;
        /*NOTREACHED*/
    }

    IDirect3DVertexBuffer9* vertBuffer = 0;
    if (device->CreateVertexBuffer(
        sizeof(SquareVertexBuffer),
        0,
        D3DFVF_CUSTOMVERTEX,
        D3DPOOL_DEFAULT,
        &vertBuffer,
        0
    ) != D3D_OK)
    {
        RELEASE_COM_OBJ(Texture);
        return RS_ERR;
        /*NOTREACHED*/
    }


    vert_buffer_ = vertBuffer;
    texture_ = Texture;

    return CallCallback(aRenderer);
}

RetStatus
VideoRenderer::RTTexture::LockImageProc(RECT *lockRect, int *pitch, void **pBits)
{
    if (texture_ == 0)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    D3DLOCKED_RECT lockedRect;
    if (texture_->LockRect(0,&lockedRect, lockRect, 0) != S_OK)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    *pitch = lockedRect.Pitch;
    *pBits = lockedRect.pBits;
    return RS_OK;
}

RetStatus
VideoRenderer::RTTexture::UnlockImageProc()
{
    if (0 == texture_)
        return RS_ERR;

    unlock_called_ = true;
    texture_->UnlockRect(0);
    return RS_OK;
}

VideoRenderer::RTTexture::~RTTexture()
{
    freeResources();
}

void
VideoRenderer::RTTexture::freeResources()
{
    unlock_called_ = false;
    RELEASE_COM_OBJ(texture_);
    RELEASE_COM_OBJ(vert_buffer_);
}


///////////////////////

#define D3D_MSG (WM_USER + 13)

LRESULT CALLBACK D3DCreateProc(
    HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
)
{
    RendererState state = RST_NOTPRESENT;

    if(uMsg != D3D_MSG)
    {
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }

    D3DPRESENT_PARAMETERS d3dpp;
    memset(&d3dpp, 0, sizeof(d3dpp));

    d3dpp.Windowed                 = TRUE;
    d3dpp.SwapEffect               = D3DSWAPEFFECT_FLIP;
    d3dpp.BackBufferFormat         = D3DFMT_UNKNOWN;
    d3dpp.hDeviceWindow                = hwnd;

    IDirect3D9* d3d9 = (IDirect3D9*)wParam;
    IDirect3DDevice9** device = (IDirect3DDevice9**)lParam;
    assert(d3d9 != 0);
    assert(device != 0);

    RECT tstRect;
    GetClientRect(hwnd,&tstRect);

    *device = 0;
    if(D3D_OK ==
        d3d9->CreateDevice(
            D3DADAPTER_DEFAULT,
            D3DDEVTYPE_HAL,
            hwnd,
            _D3DDEV_FLAGS,
            &d3dpp,
            device
        )
    ){
            state = RST_HAL;
    }
    else
    {
        state = 
            D3D_OK == d3d9->CreateDevice(
                D3DADAPTER_DEFAULT,
                D3DDEVTYPE_REF,
                hwnd,
                _D3DDEV_FLAGS,
                &d3dpp,
                device
            ) ? RST_REF : RST_NOTPRESENT;
    }

    IDirect3DDevice9* tst = *device;
    return state;
}

VideoRenderer::HWStateDirctX::HWStateDirctX():
     d3d_(0),
     d3d_dev_(0)
{ 
#ifdef MULTITHREADED_D3D
# define COM_INIT COINIT_MULTITHREADED
#else
# define COM_INIT COINIT_APARTMENTTHREADED
#endif

    coinited_ = SUCCEEDED(CoInitializeEx(0, COM_INIT));
    if(coinited_)
    {
        d3d_ = Direct3DCreate9(D3D_SDK_VERSION);
    }
}

VideoRenderer::HWStateDirctX::~HWStateDirctX()
{
    fini();
    RELEASE_COM_OBJ(d3d_);
    if(coinited_){
        CoUninitialize();
    }
}

RetStatus VideoRenderer::HWStateDirctX::init(HWND hWnd)
{
    if (d3d_ == 0 || !coinited_)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    if (!IsWindow(hWnd))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    RECT clientRect;
    GetClientRect(hWnd, &clientRect);

    fini();

    d3d_dev_ = 0;

//#ifdef MULTITHREADED_D3D
    RendererState state = (RendererState)D3DCreateProc(hWnd, D3D_MSG, (WPARAM)d3d_, (LPARAM)&d3d_dev_);
//#else        //переключение в поток окна.
//    LONG prevProc = SetWindowLong(hWnd, GWL_WNDPROC, (LONG)&D3DCreateProc);
//    RendererState state = (RendererState)SendMessage(hWnd, D3D_MSG, (WPARAM)d3d_, (LPARAM)&d3d_dev_);
//    SetWindowLong(hWnd, GWL_WNDPROC, prevProc);
//#endif

    if (NULL == d3d_dev_ || RST_HAL != state)
    {
        fini();
        return RS_ERR;
        /*NOTREACHED*/
    }

    return RS_OK;
}

void VideoRenderer::HWStateDirctX::fini()
{
    RELEASE_COM_OBJ(d3d_dev_);
}

RendererState VideoRenderer::HWStateDirctX::getState(){
    return RST_HAL;
}


RetStatus VideoRenderer::HWStateDirctX::getD3DDevice(IDirect3DDevice9** aDevice)
{
    assert (0 != aDevice);

    *aDevice = d3d_dev_;
    if (NULL == d3d_dev_)
    {
        return RS_NODEVICE;
        /*NOTREACHED*/
    }

    return RS_OK;
}

RetStatus VideoRenderer::HWStateDirctX::draw(VideoRenderer* aRenderer)
{
    if(NULL == d3d_dev_)
    {
        return RS_ERR;
    }
    RetStatus result = RS_OK;

    VideoRenderer::ResArray::iterator curRes;
    d3d_dev_->Clear( 0, NULL, D3DCLEAR_TARGET, aRenderer->bg_color_, 1.0f, 0 );
    d3d_dev_->BeginScene();

    d3d_dev_->SetFVF(D3DFVF_CUSTOMVERTEX);

//    d3d_dev_->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
    
    d3d_dev_->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    d3d_dev_->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
    d3d_dev_->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

//    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

    for(curRes = aRenderer->res_array_.begin(); curRes != aRenderer->res_array_.end(); ++curRes)
    {
        if(NULL != curRes->resource_)
        {
            result = curRes->resource_->restoreResource(aRenderer);
            if (result != RS_OK)
            {
                break;
                /*NOTREACHED*/
            }
            result = curRes->resource_->ApplyToScene(aRenderer);
            if (result != RS_OK)
            {
                break;
                /*NOTREACHED*/
            }
        }
    }

    d3d_dev_->EndScene();
    {
        HRESULT hr = d3d_dev_->Present( NULL, NULL, NULL, NULL );
        result = D3D_OK == hr && RS_OK == result ? RS_OK : RS_ERR;    //D3DERR_DEVICELOST
    }
    return result;
}

VideoRenderer::VRResource* VideoRenderer::HWStateDirctX::createResource(ResourceType aType)
{
    switch (aType)
    {
    case (RT_OPAQUE_SURF):
        return new RTSurface;
            /*NOTREACHED*/
    case (RT_TRANSPARENT_SURF):
        return new RTTexture;
            /*NOTREACHED*/
    default:
        return NULL;
        /*NOTREACHED*/
    }
    return NULL;
}

//////////////////

VideoRenderer::HWStateGDI::HWStateGDI()
{
}

VideoRenderer::HWStateGDI::~HWStateGDI()
{
}

RetStatus VideoRenderer::HWStateGDI::init(HWND hWnd)
{
    if (!IsWindow(hWnd))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    RECT clientRect;
    GetClientRect(hWnd, &clientRect);

    fini();

    HDC wndDC = GetDC(hWnd);
    mem_dc_ = CreateCompatibleDC(wndDC);
    HBITMAP bitmap_ = CreateCompatibleBitmap(wndDC, clientRect.right, clientRect.bottom);
    prev_bitmap_ = SelectObject(mem_dc_, bitmap_);
    ReleaseDC(hWnd, wndDC);

    return RS_OK;
}

void VideoRenderer::HWStateGDI::fini()
{

    if(NULL != prev_bitmap_) {
        SelectObject(mem_dc_, prev_bitmap_);
    }
    DeleteObject(bitmap_);
    DeleteDC(mem_dc_);
}

RendererState VideoRenderer::HWStateGDI::getState(){
    return RST_REF;
}


RetStatus VideoRenderer::HWStateGDI::draw(VideoRenderer* aRenderer)
{
    RetStatus result = RS_OK;

    RECT rect;
    GetClientRect(aRenderer->hwnd_, &rect);

    {
        HBRUSH hbr = VCreateSolidBrush(aRenderer->bg_color_, NULL);
        FillRect(mem_dc_, &rect, hbr);
        VUnLoadHandle(hbr);
    }

    for(
        ResArray::iterator curRes = aRenderer->res_array_.begin();
        curRes != aRenderer->res_array_.end();
        ++curRes
    )
    {
        result = curRes->resource_->restoreResource(aRenderer);
        if (result != RS_OK)
        {
            break;
            /*NOTREACHED*/
        }
        result = curRes->resource_->ApplyToScene(aRenderer);
        if (result != RS_OK)
        {
            break;
            /*NOTREACHED*/
        }
    }

    {
        HDC wndDC = GetDC(aRenderer->hwnd_);
        BitBlt(
            wndDC,
            rect.left, rect.top, rect.right, rect.bottom,
            mem_dc_,
            0, 0,
            SRCCOPY
        );

        ReleaseDC(aRenderer->hwnd_, wndDC);
    }
    return result;
}

VideoRenderer::VRResource* VideoRenderer::HWStateGDI::createResource(ResourceType aType)
{
    if(RT_OPAQUE_SURF == aType)
    {
        return new RTGDIImage(false);
            /*NOTREACHED*/
    }else if(RT_TRANSPARENT_SURF == aType)
    {
        return new RTGDIImage(true);
            /*NOTREACHED*/
    }

    return NULL;
}

//////////////////

VideoRenderer::HWStateNULL::~HWStateNULL(){
}

RetStatus VideoRenderer::HWStateNULL::init(HWND hwnd){
    return RS_OK;
}
void VideoRenderer::HWStateNULL::fini(){}
RetStatus VideoRenderer::HWStateNULL::draw(VideoRenderer* aRenderer)
{
    return RS_OK;
}
VideoRenderer::VRResource* VideoRenderer::HWStateNULL::createResource(ResourceType aType)
{
    return NULL;
}
RendererState VideoRenderer::HWStateNULL::getState(){
    return RST_NOTPRESENT;
}

//////////////////

VideoRenderer::VideoRenderer()
    :hwnd_(0)
    , bg_color_(VR_RGB_COLOR(0,0,0))
{
    current_state_ = new HWStateNULL;
}

VideoRenderer::~VideoRenderer()
{

    current_state_->fini();
    while(!res_array_.empty())
    {
        deleteResource(res_array_.begin()->res_id_);
    }

    delete current_state_;
}

void
VideoRenderer::freeObj()
{
    ResArray::iterator curRes;
    for (curRes = res_array_.begin(); curRes != res_array_.end(); ++curRes)
    {
        if(NULL != curRes->resource_){
            delete curRes->resource_;
        }
        curRes->resource_ = NULL;
    }

    current_state_->fini();
    delete current_state_;
    current_state_ = new HWStateNULL;
//    hwnd_ = 0;
}


//переинициализация устройств. должна быть синхронизирована с вызовами ф-ций работы с устройствами.
RetStatus
VideoRenderer::setWindow(HWND hWnd)
{
    if (!IsWindow(hWnd))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    RECT clientRect;
    GetClientRect(hWnd, &clientRect);
    if ((hwnd_ == hWnd) && (clientRect.right == wnd_width_) && (clientRect.bottom == wnd_height_))
    {
        return RS_OK;
        /*NOTREACHED*/
    }
    return absSetWindow(hWnd);
}

RetStatus
VideoRenderer::absSetWindow(HWND hWnd)
{
    if (!IsWindow(hWnd))
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    RECT clientRect;
    GetClientRect(hWnd, &clientRect);

    RetStatus status = RS_ERR;

    CurrentHWState* newstate = new HWStateDirctX;
    status = newstate->init(hWnd);
    if(RS_OK != status)
    {
        newstate->fini();
        delete newstate;
        newstate = new HWStateGDI;
        status = newstate->init(hWnd);
        if(RS_OK != status)
        {
            newstate->fini();
            delete newstate;
            newstate = new HWStateNULL;
            /*status =*/ newstate->init(hWnd);
        }
    }

    {
        if(RS_OK == status)
        {
            if(newstate->getState() != current_state_->getState())
            {    //пересоздать
                freeObj();
                for(ResArray::iterator curRes = res_array_.begin(); curRes != res_array_.end(); curRes++)
                {
                    curRes->resource_ = newstate->createResource(curRes->res_type_);
                }
            }else
            {    //восстанвоить.
                ResArray::iterator curRes;
                for (curRes = res_array_.begin(); curRes != res_array_.end(); ++curRes)
                {
                    if(NULL == curRes->resource_)
                    {
                        curRes->resource_ = newstate->createResource(curRes->res_type_);
                    }
                    if(NULL != curRes->resource_){
                        curRes->resource_->freeResources();
    //                    curRes->resource_->restoreResource(this);
                    }
    //                curRes->resource_ = NULL;
                }
            }
        }
        current_state_->fini();
        delete current_state_;
        current_state_ = newstate;

        if(RS_OK == status){
            hwnd_ = hWnd;
            wnd_width_ = clientRect.right;
            wnd_height_ = clientRect.bottom;
        } else {
            hwnd_ = 0;
            wnd_width_ = wnd_height_ = 0;
        }
    }
    return status;
}

RetStatus
VideoRenderer::setBgColor(ColorID BGColor)
{
    bg_color_ = BGColor;
    return RS_OK;
}

RetStatus
VideoRenderer::draw()
{
    RetStatus status = current_state_->draw(this);
    if(RS_OK == status)
    {
        return RS_OK;
    }

    absSetWindow(hwnd_);        //reinit renderer
    return current_state_->draw(this);


    //}
    //else
    //{
    //    for(curRes = res_array_.begin(); curRes != res_array_.end(); ++curRes)
    //    {
    //        RetStatus rs = curRes->resource_->restoreResource(this);
    //        if (rs != RS_OK)
    //        {
    //            continue;
    //            /*NOTREACHED*/
    //        }
    //        rs = curRes->resource_->ApplyToScene(this);
    //    }
    //}
    //return RS_OK;
}

//RetStatus
//VideoRenderer::getDeviceSize(RECT* aDeviceRect)
//{
//    assert(0 != aDeviceRect);
//    if (d3d_dev_ == 0)
//    {
//        return RS_NODEVICE;
//        /*NOTREACHED*/
//    }
//
//    aDeviceRect->left = aDeviceRect->top = 0;
//    aDeviceRect->right = wnd_width_;
//    aDeviceRect->bottom = wnd_height_;
//
//#ifdef _DEBUG
//    {
//        RECT clientRect;
//        GetClientRect(hwnd_, &clientRect);
//        if(0 != memcmp(aDeviceRect, &clientRect, sizeof(RECT)))
//        {
//            DebugBreak();
//            //если aDeviceRect постоянно некоректный, - где-то баг.
//            return RS_ERR;
//        }
//    }
//#endif
//
//    return RS_OK;
//}

RendererState VideoRenderer::getState()
{
    return current_state_->getState();
}

VideoRenderer::ResArray::iterator
VideoRenderer::FindResource(ResID aResID)
{
    ResArray::iterator curRes;
    for(curRes = res_array_.begin(); curRes != res_array_.end(); ++curRes)
    {
        if (curRes->res_id_ == aResID)
        {
            return curRes;
            /*NOTREACHED*/
        }
    }
    return curRes;
}

RetStatus
VideoRenderer::createResource(ResID aCallerResID, ResourceType aType)
{
    ResArray::iterator curRes;
    curRes = FindResource(aCallerResID);
    if (curRes != res_array_.end())
    {
        if(curRes->res_type_ == aType)
        {
            return RS_OK;
            /*NOTREACHED*/
        }
        res_array_.erase(curRes);
    }

    VRResource* resource = current_state_->createResource(aType);
//    if(NULL != resource) {
        res_array_.push_back(
            ResDesc(
                aCallerResID,
                aType,
                resource
            )
        );
//    }

    return NULL != resource ? RS_OK :RS_ERR;
}

RetStatus
VideoRenderer::controlResource(ResID aCallerResID, ControlStruct* aControlStruct)
{
    assert(0 != aControlStruct);

    ResArray::iterator curRes;

    curRes = FindResource(aCallerResID);
    if (curRes == res_array_.end() || NULL == curRes->resource_)
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    return curRes->resource_->controlResource(this, aControlStruct);
}

RetStatus
VideoRenderer::deleteResource(ResID aCallerResID)
{
    ResArray::iterator curRes;
    curRes = FindResource(aCallerResID);
    if (curRes == res_array_.end())
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    if(NULL != curRes->resource_)
    {
        delete curRes->resource_;
    }
    res_array_.erase(curRes);
    return RS_OK;
}

RetStatus
VideoRenderer::bringToFrontResource(ResID aCallerResID)
{
    ResArray::iterator curRes;
    curRes = FindResource(aCallerResID);
    if (curRes == res_array_.end())
    {
        return RS_ERR;
        /*NOTREACHED*/
    }

    res_array_.push_back(*curRes);
    res_array_.erase(FindResource(aCallerResID));

    return RS_OK;
}

bool
VideoRenderer::getResourceID(VRResource* aResource, ResID& aResId)
{
    ResArray::iterator curRes;
    for(curRes = res_array_.begin(); curRes != res_array_.end(); ++curRes)
    {
        if (curRes->resource_ == aResource)
        {
            aResId = curRes->res_id_;
            return true;
            /*NOTREACHED*/
        }
    }
    return false;
}

} // namespace VR
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[4]: DirectX тормоза при масштабировании картинки
От: 8bit  
Дата: 17.02.09 10:42
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

При отрисовке с помощью текстуры есть падение fps?

У StretchRect есть ограничения
http://msdn.microsoft.com/en-us/library/bb174471(VS.85).aspx
смотрите таблицу Direct3D 9 Driver (stretching)
У вас получается (могу ошибаться)
Src format: Off-screen plain (ваша поверхность с видео данными)
Dst format: Off-screen plain (Back buffer)
Попробуйте создать свой render target, текущий запомнить, выставить свой,
сделать в него StretchRect видео, отрисовать все остальное, потом выставить назад родной
render target и в него сделать StretchRect своего render target в оригинальный, один к одному без фильтров (D3DTEXF_NONE).
По типу такого http://www.gamedev.net/reference/articles/article2585.asp

Еще можно попробовать использовать две поверхности и чередовать их.
Т.е у вас будет surface_1 и surface_2.
Аналогично и при отрисовке текстурой, тоже можно их две иметь и чередовать.

Еще можно попробовать обновить драйвера



Вот это не надо делать на каждый фрейм, только если у вас меняются значения.
AS>
AS>    HRESULT hr;

AS>    {
AS>        SquareVertexBuffer squareVerts=
AS>        {{
AS>            {(float)destRect->left, (float)destRect->top,        0.0f,    1.0f,
AS>                (float)(((double)srcRect->left + 0.5f) / texture_width_),
AS>                (float)(((double)srcRect->top + 0.5f) / texture_height_)},
AS>            {(float)destRect->right, (float)destRect->top,        0.0f,    1.0f,
AS>                (float)(((double)srcRect->right + 0.5f) / texture_width_),
AS>                (float)(((double)srcRect->top + 0.5f) / texture_height_)},
AS>            {(float)destRect->left, (float)destRect->bottom,    0.0f,    1.0f,
AS>                (float)(((double)srcRect->left + 0.5f) / texture_width_),
AS>                (float)(((double)srcRect->bottom + 0.5f) / texture_height_)},
AS>            {(float)destRect->right, (float)destRect->bottom,    0.0f,    1.0f,
AS>                (float)(((double)srcRect->right + 0.5f) / texture_width_),
AS>                (float)(((double)srcRect->bottom + 0.5f) / texture_height_)}
AS>        }};

AS>        void* pBuf;
AS>        hr = vert_buffer_->Lock(0, sizeof(squareVerts), &pBuf, 0);
AS>        if(D3D_OK == hr) {
AS>            memcpy(pBuf, &squareVerts, sizeof(squareVerts));
AS>            vert_buffer_->Unlock();
AS>        } else {
AS>            return hr == D3D_OK? RS_OK: RS_ERR;
AS>            //NOTREACHED
AS>        }
AS>    }
AS>
Re[5]: DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 17.02.09 11:00
Оценка:
Здравствуйте, 8bit, Вы писали:

8>Здравствуйте, Aleksey Skurihin, Вы писали:


пошел проверять и читать спасибо. разберусь отпишусь.


а как VMR9 работает? у него на полный єкран загрузка проца 4% против моих 12%
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[5]: DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 17.02.09 11:24
Оценка:
а еще проблема что при рисовании например ДВУХ кадров одновременно на разных хендлах, скорость падает в 4-5 раза
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[6]: DirectX тормоза при масштабировании картинки
От: 8bit  
Дата: 17.02.09 12:43
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

Еще проверьте что у вас создается D3DDEVTYPE_HAL, а не D3DDEVTYPE_REF устройство.
Re[7]: DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 17.02.09 16:14
Оценка:
Здравствуйте, 8bit, Вы писали:

8>Здравствуйте, Aleksey Skurihin, Вы писали:


8>Еще проверьте что у вас создается D3DDEVTYPE_HAL, а не D3DDEVTYPE_REF устройство.



проверили D3DDEVTYPE_HAL а вот с двумя вьюпортами (либо с увеличением площади) явно в итоге трабла, куда копать не знаю, то что Вы советовали ник чему не привело.
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[8]: DirectX тормоза при масштабировании картинки
От: 8bit  
Дата: 17.02.09 17:08
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

AS>проверили D3DDEVTYPE_HAL а вот с двумя вьюпортами (либо с увеличением площади) явно в итоге трабла, куда копать не знаю, то что Вы советовали ник чему не привело.


Я у себя практически ваш код запустил, все в порядке. Делал stretch поверхности 640x480 на 990x730.
в оконном режиме 60фпс (частота обновления экрана, т.е все как и должно быть), загрузка ~10%

Какой формат у вас для surface_ ?
Что за видеокарточка?
Драйвера обновленные?
Re[9]: DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 18.02.09 12:17
Оценка:
8>Я у себя практически ваш код запустил, все в порядке. Делал stretch поверхности 640x480 на 990x730.
8>в оконном режиме 60фпс (частота обновления экрана, т.е все как и должно быть), загрузка ~10%

можете прислать Ваш код?

а если будет ДВА вьюпорта? или один но разрешение 1600 на 1000.

8>Какой формат у вас для surface_ ?

ргб32

8>Что за видеокарточка?

гефорсе двухмониторный но без разницы.

8>Драйвера обновленные?


да
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[9]: DirectX тормоза при масштабировании картинки
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 18.02.09 12:17
Оценка:
а у текстуры с алертами — D3DFMT_A8R8G8B8
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[10]: DirectX тормоза при масштабировании картинки
От: 8bit  
Дата: 19.02.09 08:13
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

8>>Я у себя практически ваш код запустил, все в порядке. Делал stretch поверхности 640x480 на 990x730.

8>>в оконном режиме 60фпс (частота обновления экрана, т.е все как и должно быть), загрузка ~10%

AS>можете прислать Ваш код?


bool cDXRender::Open(const wchar_t *inWindowTitle, int inWidth, int inHeight, bool inFullScreen, tWndProc inWindowProcedure)
{
    Close();

    windowProcedure = inWindowProcedure;

    fullScreen = inFullScreen;
    width = inWidth;
    height = inHeight;
    midleWidth = width/2;
    midleHeight = height/2;

    instance = GetModuleHandle(NULL);

    WNDCLASS wc;
    int style1;
    int style2;

    wc.style          = CS_OWNDC;
    wc.lpfnWndProc    = (WNDPROC)WindowProc;
    wc.cbClsExtra     = 0;
    wc.cbWndExtra     = 0;
    wc.hInstance      = (HINSTANCE)instance;
    wc.hIcon          = LoadIcon((HINSTANCE)instance, MAKEINTRESOURCE(IDI_APPLICATION));
    wc.hCursor        = LoadCursor(0, IDC_ARROW);
    wc.hbrBackground  = 0;
    wc.lpszMenuName   = 0;
    wc.lpszClassName  = L"dx9render wc";

    if (!RegisterClass(&wc))
    {
        return (false);
    }

    int winPosX = 0;
    int winPosY = 0;

    if (fullScreen)
    {
        style2 = WS_EX_TOPMOST;
        style1 = WS_POPUP | WS_VISIBLE;
    }
    else
    {
        winPosX = (GetSystemMetrics(SM_CXSCREEN) - inWidth)/2;
        winPosY = (GetSystemMetrics(SM_CYSCREEN) - inHeight)/2;
        style2 = 0;
        style1 = WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE;
    }


    wnd = CreateWindowEx(
                    style2,
                    L"dx9render wc",
                    (LPCTSTR)inWindowTitle,
                    style1,
                    winPosX, winPosY, inWidth, inHeight,
                    NULL,
                    NULL,
                    instance,
                    NULL);

    if (!wnd)
    {
        return (false);
    }

    SetWindowLong(wnd, GWL_USERDATA, (long)this);

    ShowWindow(wnd, SW_NORMAL);

    if ((d3d = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
    {
        return (false);
    }

#define MULTITHREADED_D3D

#ifdef MULTITHREADED_D3D
# define _D3DDEV_FLAGS (D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED)
#else
# define _D3DDEV_FLAGS (D3DCREATE_SOFTWARE_VERTEXPROCESSING)
#endif

D3DPRESENT_PARAMETERS d3dpp;
    memset(&d3dpp, 0, sizeof(d3dpp));

    d3dpp.Windowed                 = TRUE;
    d3dpp.SwapEffect               = D3DSWAPEFFECT_FLIP;
    d3dpp.BackBufferFormat         = D3DFMT_UNKNOWN;
    d3dpp.hDeviceWindow                = wnd;

    if(D3D_OK !=
        d3d->CreateDevice(
            D3DADAPTER_DEFAULT,
            D3DDEVTYPE_HAL,
            wnd,
            _D3DDEV_FLAGS,
            &d3dpp,
            &device
        )
    )
    {
        return (false);
    }
    return true;
}




int APIENTRY WinMain(HINSTANCE inInstance, HINSTANCE inPrevInstance, LPSTR inCmdLine, int inCmdShow)
{
    HRESULT hr;
    cDXRender r;


    DWORD time = GetTickCount();
    DWORD stime = GetTickCount();
    DWORD tmil;
    int frames = 0;
    int fps = 0;


    r.Open(L"asd", 1600, 1000, false, 0);

    IDirect3DDevice9 *d3d_dev_ = r.device;

    IDirect3DSurface9* surface_;
    hr = d3d_dev_->CreateOffscreenPlainSurface(
        640,
        480,
        (D3DFORMAT)D3DFMT_A8R8G8B8,
        D3DPOOL_DEFAULT,
        &surface_,
        0
    );


    while (true)
    {
        MSG wmsg;
        if (PeekMessage((LPMSG)&wmsg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage((LPMSG)&wmsg);
            DispatchMessage((LPMSG)&wmsg); 
        }

        D3DLOCKED_RECT lockedRect;
        if (surface_->LockRect(&lockedRect, 0, D3DLOCK_DISCARD) != D3D_OK)
        {
            return -1;
        }
        for (int i = 0; i < 200; ++i)
        {
            memset((char*)lockedRect.pBits+lockedRect.Pitch*i, 127, lockedRect.Pitch);
        }
        surface_->UnlockRect();


        d3d_dev_->Clear( 0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0 );
        d3d_dev_->BeginScene();

                frames++;
                DWORD ctime = GetTickCount();
                tmil = ctime - stime;
                DWORD dtime = ctime-time;
                time = ctime;

        //d3d_dev_->SetFVF(D3DFVF_CUSTOMVERTEX);

        //    d3d_dev_->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
    
        d3d_dev_->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
        d3d_dev_->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
        d3d_dev_->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

    //    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

        IDirect3DSurface9* backBuf = 0;
        if (d3d_dev_->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuf) != D3D_OK)
        {
            return -1;
        }


        //IDirect3DSurface9* backBuf;
        //d3d_dev_->GetRenderTarget(0,&backBuf);


        RECT aSrcRect;
        aSrcRect.left = 0;
        aSrcRect.right = 320;
        aSrcRect.top = 0;
        aSrcRect.bottom = 200;
        RECT aDestRect;
        aDestRect.left = 0;
        aDestRect.right = 1590;
        aDestRect.top = 0;
        aDestRect.bottom = 960;

        hr = d3d_dev_->StretchRect(surface_, &aSrcRect, backBuf, &aDestRect, D3DTEXF_LINEAR);
        if(D3D_OK != hr)
        {
            hr = d3d_dev_->StretchRect(surface_, &aSrcRect, backBuf, &aDestRect, D3DTEXF_NONE);
            if(D3D_OK != hr)
            {
                return -1;
            }

        }

        backBuf->Release();

                if (tmil > 2000)
                {
                    fps = (int)((float)frames/((float)tmil/1000.0f));
                    stime = GetTickCount();
                    frames = 0;
                }

                //r.DrawFps(fps);

        d3d_dev_->EndScene();
        {
            HRESULT hr = d3d_dev_->Present( NULL, NULL, NULL, NULL );
        }


    }

}



AS>или один но разрешение 1600 на 1000.

Все в порядке. ~57 фпс
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.