summaryrefslogtreecommitdiff
path: root/bsd-core/tdfx/Makefile
blob: 12e7d745d7f00ce4084e9c47568b700f2f85e703 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# $FreeBSD$

.PATH:	${.CURDIR}/..
KMOD=	tdfx
NOMAN=	YES
SRCS=	tdfx_drv.c
SRCS+=	device_if.h bus_if.h pci_if.h opt_drm.h
CFLAGS+=	${DEBUG_FLAGS} -I. -I.. 

.if defined(DRM_DEBUG)
DRM_DEBUG_OPT= "\#define DRM_DEBUG 1"
.endif

.if !defined(DRM_NOLINUX)
DRM_LINUX_OPT= "\#define DRM_LINUX 1"
.endif

opt_drm.h:
	touch opt_drm.h
	echo $(DRM_DEBUG_OPT) >> opt_drm.h
	echo $(DRM_LINUX_OPT) >> opt_drm.h

.include <bsd.kmod.mk>
'n73' href='#n73'>73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

#include <cstring>
#include <stdexcept>
#include <sys/mman.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm_fourcc.h>
#include <drm.h>
#include <drm_mode.h>

#include "kms++.h"

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

using namespace std;

namespace kms
{

DumbFramebuffer::DumbFramebuffer(Card &card, uint32_t width, uint32_t height, const string& fourcc)
	:DumbFramebuffer(card, width, height, FourCCToPixelFormat(fourcc))
{
}

DumbFramebuffer::DumbFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format)
	:Framebuffer(card, width, height), m_format(format)
{
	Create();
}

DumbFramebuffer::~DumbFramebuffer()
{
	Destroy();
}

void DumbFramebuffer::print_short() const
{
	printf("DumbFramebuffer %d\n", id());
}

struct FormatPlaneInfo
{
	uint8_t bitspp;	/* bits per (macro) pixel */
	uint8_t xsub;
	uint8_t ysub;
};

struct FormatInfo
{
	uint8_t num_planes;
	struct FormatPlaneInfo planes[4];
};

static const map<PixelFormat, FormatInfo> format_info_array = {
	/* YUV packed */
	{ PixelFormat::UYVY, { 1, { { 32, 2, 1 } }, } },
	{ PixelFormat::YUYV, { 1, { { 32, 2, 1 } }, } },
	{ PixelFormat::YVYU, { 1, { { 32, 2, 1 } }, } },
	{ PixelFormat::VYUY, { 1, { { 32, 2, 1 } }, } },
	/* YUV semi-planar */
	{ PixelFormat::NV12, { 2, { { 8, 1, 1, }, { 16, 2, 2 } }, } },
	{ PixelFormat::NV21, { 2, { { 8, 1, 1, }, { 16, 2, 2 } }, } },
	/* RGB16 */
	{ PixelFormat::RGB565, { 1, { { 16, 1, 1 } }, } },
	/* RGB32 */
	{ PixelFormat::XRGB8888, { 1, { { 32, 1, 1 } }, } },
	{ PixelFormat::XBGR8888, { 1, { { 32, 1, 1 } }, } },
};

void DumbFramebuffer::Create()
{
	int r;

	const FormatInfo& format_info = format_info_array.at(m_format);

	m_num_planes = format_info.num_planes;

	for (int i = 0; i < format_info.num_planes; ++i) {
		const FormatPlaneInfo& pi = format_info.planes[i];
		FramebufferPlane& plane = m_planes[i];

		/* create dumb buffer */
		struct drm_mode_create_dumb creq = drm_mode_create_dumb();
		creq.width = width() / pi.xsub;
		creq.height = height() / pi.ysub;
		creq.bpp = pi.bitspp;
		r = drmIoctl(card().fd(), DRM_IOCTL_MODE_CREATE_DUMB, &creq);
		if (r)
			throw std::invalid_argument("foo");

		plane.handle = creq.handle;
		plane.stride = creq.pitch;
		plane.size = creq.height * creq.pitch;

		/*
		printf("buf %d: %dx%d, bitspp %d, stride %d, size %d\n",
			i, creq.width, creq.height, pi->bitspp, plane->stride, plane->size);
		*/

		/* prepare buffer for memory mapping */
		struct drm_mode_map_dumb mreq = drm_mode_map_dumb();
		mreq.handle = plane.handle;
		r = drmIoctl(card().fd(), DRM_IOCTL_MODE_MAP_DUMB, &mreq);
		if (r)
			throw std::invalid_argument("foo");

		/* perform actual memory mapping */
		m_planes[i].map = (uint8_t *)mmap(0, plane.size, PROT_READ | PROT_WRITE, MAP_SHARED,
						  card().fd(), mreq.offset);
		if (plane.map == MAP_FAILED)
			throw std::invalid_argument("foo");

		/* clear the framebuffer to 0 */
		memset(plane.map, 0, plane.size);
	}

	/* create framebuffer object for the dumb-buffer */
	uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle };
	uint32_t pitches[4] = { m_planes[0].stride, m_planes[1].stride };
	uint32_t offsets[4] = { 0 };
	uint32_t id;
	r = drmModeAddFB2(card().fd(), width(), height(), (uint32_t)format(),
			  bo_handles, pitches, offsets, &id, 0);
	if (r)
		throw std::invalid_argument("foo");

	set_id(id);
}

void DumbFramebuffer::Destroy()
{
	/* delete framebuffer */
	drmModeRmFB(card().fd(), id());

	for (uint i = 0; i < m_num_planes; ++i) {
		FramebufferPlane& plane = m_planes[i];

		/* unmap buffer */
		munmap(plane.map, plane.size);

		/* delete dumb buffer */
		struct drm_mode_destroy_dumb dreq = drm_mode_destroy_dumb();
		dreq.handle = plane.handle;
		drmIoctl(card().fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);

	}
}

void DumbFramebuffer::clear()
{
	for (unsigned i = 0; i < m_num_planes; ++i)
		memset(m_planes[i].map, 0, m_planes[i].size);
}

}