Prepared support for acceleration: there is now a QueueCommands class that should
be used to feed the ring buffers with new commands. It takes care about proper alignment (this shouldn't be necessary in the final version, anymore, though), and locking. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17415 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -77,8 +77,6 @@ extern void set_display_power_mode(uint32 mode);
|
|||||||
|
|
||||||
// engine.cpp
|
// engine.cpp
|
||||||
extern void setup_ring_buffer(ring_buffer &ringBuffer, const char *name);
|
extern void setup_ring_buffer(ring_buffer &ringBuffer, const char *name);
|
||||||
extern void write_to_ring(ring_buffer &ring, uint32 value);
|
|
||||||
extern void ring_command_complete(ring_buffer &ring);
|
|
||||||
|
|
||||||
// modes.cpp
|
// modes.cpp
|
||||||
extern status_t create_mode_list(void);
|
extern status_t create_mode_list(void);
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Axel Dörfler, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef COMMANDS_H
|
||||||
|
#define COMMANDS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "accelerant.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct command {
|
||||||
|
uint32 opcode;
|
||||||
|
|
||||||
|
uint32 *Data() { return &opcode; }
|
||||||
|
virtual size_t Length() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QueueCommands {
|
||||||
|
public:
|
||||||
|
QueueCommands(ring_buffer &ring);
|
||||||
|
~QueueCommands();
|
||||||
|
|
||||||
|
void Put(struct command &command);
|
||||||
|
void PutFlush();
|
||||||
|
void PutWaitFor(uint32 event);
|
||||||
|
void PutOverlayFlip(uint32 code, bool updateCoefficients);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _MakeSpace(uint32 size);
|
||||||
|
void _Write(uint32 data);
|
||||||
|
|
||||||
|
ring_buffer &fRingBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// commands
|
||||||
|
|
||||||
|
|
||||||
|
#endif // COMMANDS_H
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "accelerant.h"
|
#include "accelerant.h"
|
||||||
#include "accelerant_protos.h"
|
#include "accelerant_protos.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_ENGINE
|
#define TRACE_ENGINE
|
||||||
@@ -23,37 +24,96 @@ extern "C" void _sPrintf(const char *format, ...);
|
|||||||
static engine_token sEngineToken = {1, 0 /*B_2D_ACCELERATION*/, NULL};
|
static engine_token sEngineToken = {1, 0 /*B_2D_ACCELERATION*/, NULL};
|
||||||
|
|
||||||
|
|
||||||
/** The ring buffer must be locked when calling this function */
|
QueueCommands::QueueCommands(ring_buffer &ring)
|
||||||
|
:
|
||||||
void
|
fRingBuffer(ring)
|
||||||
write_to_ring(ring_buffer &ring, uint32 value)
|
|
||||||
{
|
{
|
||||||
uint32 *target = (uint32 *)(ring.base + ring.position);
|
acquire_lock(&fRingBuffer.lock);
|
||||||
*target = value;
|
|
||||||
|
|
||||||
ring.position = (ring.position + sizeof(uint32)) & (ring.size - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** The ring buffer must be locked when calling this function */
|
QueueCommands::~QueueCommands()
|
||||||
|
|
||||||
void
|
|
||||||
ring_command_complete(ring_buffer &ring)
|
|
||||||
{
|
{
|
||||||
if (ring.position & 0x07) {
|
if (fRingBuffer.position & 0x07) {
|
||||||
// make sure the command is properly aligned
|
// make sure the command is properly aligned
|
||||||
write_to_ring(ring, COMMAND_NOOP);
|
_Write(COMMAND_NOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
write32(ring.register_base + RING_BUFFER_TAIL, ring.position);
|
write32(fRingBuffer.register_base + RING_BUFFER_TAIL, fRingBuffer.position);
|
||||||
|
|
||||||
// make sure memory is written back in case the ring buffer
|
// We must make sure memory is written back in case the ring buffer
|
||||||
// is in write combining mode
|
// is in write combining mode - releasing the lock does this, as the
|
||||||
int32 test;
|
// buffer is flushed on a locked memory operation (which is what this
|
||||||
atomic_add(&test, 1);
|
// benaphore does)
|
||||||
|
release_lock(&fRingBuffer.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
QueueCommands::Put(struct command &command)
|
||||||
|
{
|
||||||
|
uint32 count = command.Length();
|
||||||
|
uint32 *data = command.Data();
|
||||||
|
|
||||||
|
_MakeSpace(count);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < count; i++) {
|
||||||
|
_Write(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
QueueCommands::PutFlush()
|
||||||
|
{
|
||||||
|
_MakeSpace(2);
|
||||||
|
|
||||||
|
_Write(COMMAND_FLUSH);
|
||||||
|
_Write(COMMAND_NOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
QueueCommands::PutWaitFor(uint32 event)
|
||||||
|
{
|
||||||
|
_MakeSpace(2);
|
||||||
|
|
||||||
|
_Write(COMMAND_WAIT_FOR_EVENT | event);
|
||||||
|
_Write(COMMAND_NOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
QueueCommands::PutOverlayFlip(uint32 mode, bool updateCoefficients)
|
||||||
|
{
|
||||||
|
_MakeSpace(2);
|
||||||
|
|
||||||
|
_Write(COMMAND_OVERLAY_FLIP | mode);
|
||||||
|
_Write((uint32)gInfo->shared_info->physical_overlay_registers
|
||||||
|
| (updateCoefficients ? OVERLAY_UPDATE_COEFFICIENTS : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
QueueCommands::_MakeSpace(uint32 size)
|
||||||
|
{
|
||||||
|
// TODO: make sure there is enough room to write the command!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
QueueCommands::_Write(uint32 data)
|
||||||
|
{
|
||||||
|
uint32 *target = (uint32 *)(fRingBuffer.base + fRingBuffer.position);
|
||||||
|
*target = data;
|
||||||
|
|
||||||
|
fRingBuffer.position = (fRingBuffer.position + sizeof(uint32)) & (fRingBuffer.size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
setup_ring_buffer(ring_buffer &ringBuffer, const char *name)
|
setup_ring_buffer(ring_buffer &ringBuffer, const char *name)
|
||||||
{
|
{
|
||||||
@@ -75,7 +135,7 @@ setup_ring_buffer(ring_buffer &ringBuffer, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark - engine management
|
||||||
|
|
||||||
|
|
||||||
/** Return number of hardware engines */
|
/** Return number of hardware engines */
|
||||||
@@ -132,3 +192,6 @@ intel_sync_to_token(sync_token *syncToken)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - engine acceleration
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "accelerant.h"
|
#include "accelerant.h"
|
||||||
#include "accelerant_protos.h"
|
#include "accelerant_protos.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -225,19 +226,14 @@ update_overlay(bool updateCoefficients)
|
|||||||
if (!gInfo->shared_info->overlay_active)
|
if (!gInfo->shared_info->overlay_active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ring_buffer &ringBuffer = gInfo->shared_info->secondary_ring_buffer;
|
QueueCommands queue(gInfo->shared_info->secondary_ring_buffer);
|
||||||
write_to_ring(ringBuffer, COMMAND_FLUSH);
|
queue.PutFlush();
|
||||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||||
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
queue.PutOverlayFlip(COMMAND_OVERLAY_CONTINUE, updateCoefficients);
|
||||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
|
||||||
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_CONTINUE);
|
|
||||||
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers
|
|
||||||
| (updateCoefficients ? OVERLAY_UPDATE_COEFFICIENTS : 0));
|
|
||||||
ring_command_complete(ringBuffer);
|
|
||||||
|
|
||||||
TRACE(("update overlay: UPDATE: %lx, TEST: %lx, STATUS: %lx, EXTENDED_STATUS: %lx\n",
|
// TRACE(("update overlay: UPDATE: %lx, TEST: %lx, STATUS: %lx, EXTENDED_STATUS: %lx\n",
|
||||||
read32(INTEL_OVERLAY_UPDATE), read32(INTEL_OVERLAY_TEST), read32(INTEL_OVERLAY_STATUS),
|
// read32(INTEL_OVERLAY_UPDATE), read32(INTEL_OVERLAY_TEST), read32(INTEL_OVERLAY_STATUS),
|
||||||
read32(INTEL_OVERLAY_EXTENDED_STATUS)));
|
// read32(INTEL_OVERLAY_EXTENDED_STATUS)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -252,13 +248,9 @@ show_overlay(void)
|
|||||||
gInfo->shared_info->overlay_active = true;
|
gInfo->shared_info->overlay_active = true;
|
||||||
registers->overlay_enabled = true;
|
registers->overlay_enabled = true;
|
||||||
|
|
||||||
ring_buffer &ringBuffer = gInfo->shared_info->secondary_ring_buffer;
|
QueueCommands queue(gInfo->shared_info->secondary_ring_buffer);
|
||||||
write_to_ring(ringBuffer, COMMAND_FLUSH);
|
queue.PutFlush();
|
||||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
queue.PutOverlayFlip(COMMAND_OVERLAY_ON, true);
|
||||||
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_ON);
|
|
||||||
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers
|
|
||||||
| OVERLAY_UPDATE_COEFFICIENTS);
|
|
||||||
ring_command_complete(ringBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -273,26 +265,19 @@ hide_overlay(void)
|
|||||||
gInfo->shared_info->overlay_active = false;
|
gInfo->shared_info->overlay_active = false;
|
||||||
registers->overlay_enabled = false;
|
registers->overlay_enabled = false;
|
||||||
|
|
||||||
ring_buffer &ringBuffer = gInfo->shared_info->secondary_ring_buffer;
|
QueueCommands queue(gInfo->shared_info->secondary_ring_buffer);
|
||||||
|
|
||||||
// flush pending commands
|
// flush pending commands
|
||||||
write_to_ring(ringBuffer, COMMAND_FLUSH);
|
queue.PutFlush();
|
||||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||||
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
|
||||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
|
||||||
|
|
||||||
// clear overlay enabled bit
|
// clear overlay enabled bit
|
||||||
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_CONTINUE);
|
queue.PutOverlayFlip(COMMAND_OVERLAY_CONTINUE, false);
|
||||||
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers);
|
queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||||
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
|
||||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
|
||||||
|
|
||||||
// turn off overlay engine
|
// turn off overlay engine
|
||||||
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_OFF);
|
queue.PutOverlayFlip(COMMAND_OVERLAY_OFF, false);
|
||||||
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers);
|
queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||||
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
|
||||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
|
||||||
ring_command_complete(ringBuffer);
|
|
||||||
|
|
||||||
gInfo->current_overlay = NULL;
|
gInfo->current_overlay = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user