mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 13:07:26 +01:00
201 lines
5.0 KiB
Go
201 lines
5.0 KiB
Go
|
// Copyright 2023 The Ebitengine Authors
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
package directx
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"unsafe"
|
||
|
|
||
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||
|
)
|
||
|
|
||
|
type image11 struct {
|
||
|
graphics *graphics11
|
||
|
id graphicsdriver.ImageID
|
||
|
width int
|
||
|
height int
|
||
|
screen bool
|
||
|
|
||
|
texture *_ID3D11Texture2D
|
||
|
stencil *_ID3D11Texture2D
|
||
|
renderTargetView *_ID3D11RenderTargetView
|
||
|
stencilView *_ID3D11DepthStencilView
|
||
|
shaderResourceView *_ID3D11ShaderResourceView
|
||
|
}
|
||
|
|
||
|
func (i *image11) internalSize() (int, int) {
|
||
|
if i.screen {
|
||
|
return i.width, i.height
|
||
|
}
|
||
|
return graphics.InternalImageSize(i.width), graphics.InternalImageSize(i.height)
|
||
|
}
|
||
|
|
||
|
func (i *image11) ID() graphicsdriver.ImageID {
|
||
|
return i.id
|
||
|
}
|
||
|
|
||
|
func (i *image11) Dispose() {
|
||
|
i.disposeBuffers()
|
||
|
i.graphics.removeImage(i)
|
||
|
}
|
||
|
|
||
|
func (i *image11) disposeBuffers() {
|
||
|
if i.texture != nil {
|
||
|
i.texture.Release()
|
||
|
i.texture = nil
|
||
|
}
|
||
|
if i.stencil != nil {
|
||
|
i.stencil.Release()
|
||
|
i.stencil = nil
|
||
|
}
|
||
|
if i.renderTargetView != nil {
|
||
|
i.renderTargetView.Release()
|
||
|
i.renderTargetView = nil
|
||
|
}
|
||
|
if i.stencilView != nil {
|
||
|
i.stencilView.Release()
|
||
|
i.stencilView = nil
|
||
|
}
|
||
|
if i.shaderResourceView != nil {
|
||
|
i.shaderResourceView.Release()
|
||
|
i.shaderResourceView = nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (i *image11) IsInvalidated() bool {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
func (i *image11) ReadPixels(buf []byte, x, y, width, height int) error {
|
||
|
staging, err := i.graphics.device.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{
|
||
|
Width: uint32(width),
|
||
|
Height: uint32(height),
|
||
|
MipLevels: 0,
|
||
|
ArraySize: 1,
|
||
|
Format: _DXGI_FORMAT_R8G8B8A8_UNORM,
|
||
|
SampleDesc: _DXGI_SAMPLE_DESC{
|
||
|
Count: 1,
|
||
|
Quality: 0,
|
||
|
},
|
||
|
Usage: _D3D11_USAGE_STAGING,
|
||
|
BindFlags: 0,
|
||
|
CPUAccessFlags: uint32(_D3D11_CPU_ACCESS_READ),
|
||
|
MiscFlags: 0,
|
||
|
}, nil)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer staging.Release()
|
||
|
|
||
|
i.graphics.deviceContext.CopySubresourceRegion(unsafe.Pointer(staging), 0, 0, 0, 0, unsafe.Pointer(i.texture), 0, &_D3D11_BOX{
|
||
|
left: uint32(x),
|
||
|
top: uint32(y),
|
||
|
front: 0,
|
||
|
right: uint32(x + width),
|
||
|
bottom: uint32(y + height),
|
||
|
back: 1,
|
||
|
})
|
||
|
|
||
|
var mapped _D3D11_MAPPED_SUBRESOURCE
|
||
|
if err := i.graphics.deviceContext.Map(unsafe.Pointer(staging), 0, _D3D11_MAP_READ, 0, &mapped); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
copy(buf, unsafe.Slice((*byte)(mapped.pData), 4*width*height))
|
||
|
i.graphics.deviceContext.Unmap(unsafe.Pointer(staging), 0)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (i *image11) WritePixels(args []*graphicsdriver.WritePixelsArgs) error {
|
||
|
for _, a := range args {
|
||
|
i.graphics.deviceContext.UpdateSubresource(unsafe.Pointer(i.texture), 0, &_D3D11_BOX{
|
||
|
left: uint32(a.X),
|
||
|
top: uint32(a.Y),
|
||
|
front: 0,
|
||
|
right: uint32(a.X + a.Width),
|
||
|
bottom: uint32(a.Y + a.Height),
|
||
|
back: 1,
|
||
|
}, unsafe.Pointer(&a.Pixels[0]), uint32(4*a.Width), 0)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (i *image11) setAsRenderTarget(useStencil bool) error {
|
||
|
if i.renderTargetView == nil {
|
||
|
rtv, err := i.graphics.device.CreateRenderTargetView(unsafe.Pointer(i.texture), nil)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
i.renderTargetView = rtv
|
||
|
}
|
||
|
|
||
|
if !useStencil {
|
||
|
i.graphics.deviceContext.OMSetRenderTargets([]*_ID3D11RenderTargetView{i.renderTargetView}, nil)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
if i.screen {
|
||
|
return fmt.Errorf("directx: a stencil buffer is not available for a screen image")
|
||
|
}
|
||
|
|
||
|
if i.stencil == nil {
|
||
|
w, h := i.internalSize()
|
||
|
s, err := i.graphics.device.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{
|
||
|
Width: uint32(w),
|
||
|
Height: uint32(h),
|
||
|
MipLevels: 0,
|
||
|
ArraySize: 1,
|
||
|
Format: _DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||
|
SampleDesc: _DXGI_SAMPLE_DESC{
|
||
|
Count: 1,
|
||
|
Quality: 0,
|
||
|
},
|
||
|
Usage: _D3D11_USAGE_DEFAULT,
|
||
|
BindFlags: uint32(_D3D11_BIND_DEPTH_STENCIL),
|
||
|
CPUAccessFlags: 0,
|
||
|
MiscFlags: 0,
|
||
|
}, nil)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
i.stencil = s
|
||
|
}
|
||
|
|
||
|
if i.stencilView == nil {
|
||
|
sv, err := i.graphics.device.CreateDepthStencilView(unsafe.Pointer(i.stencil), nil)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
i.stencilView = sv
|
||
|
}
|
||
|
|
||
|
i.graphics.deviceContext.OMSetRenderTargets([]*_ID3D11RenderTargetView{i.renderTargetView}, i.stencilView)
|
||
|
i.graphics.deviceContext.ClearDepthStencilView(i.stencilView, uint8(_D3D11_CLEAR_STENCIL), 0, 0)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (i *image11) getShaderResourceView() (*_ID3D11ShaderResourceView, error) {
|
||
|
if i.shaderResourceView == nil {
|
||
|
srv, err := i.graphics.device.CreateShaderResourceView(unsafe.Pointer(i.texture), nil)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
i.shaderResourceView = srv
|
||
|
}
|
||
|
return i.shaderResourceView, nil
|
||
|
}
|