From 6c67d64cad2f5e2bc8c57cfbcb5b8f3a6014051f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 10 May 2006 16:09:28 +0000 Subject: [PATCH] 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 --- .../accelerants/intel_extreme/accelerant.h | 2 - .../accelerants/intel_extreme/commands.h | 43 ++++++++ .../accelerants/intel_extreme/engine.cpp | 103 ++++++++++++++---- .../accelerants/intel_extreme/overlay.cpp | 51 +++------ 4 files changed, 144 insertions(+), 55 deletions(-) create mode 100644 src/add-ons/accelerants/intel_extreme/commands.h diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h index 573f3d099c..86ce0a68a7 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.h +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -77,8 +77,6 @@ extern void set_display_power_mode(uint32 mode); // engine.cpp 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 extern status_t create_mode_list(void); diff --git a/src/add-ons/accelerants/intel_extreme/commands.h b/src/add-ons/accelerants/intel_extreme/commands.h new file mode 100644 index 0000000000..aabdd9ecf4 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/commands.h @@ -0,0 +1,43 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#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 diff --git a/src/add-ons/accelerants/intel_extreme/engine.cpp b/src/add-ons/accelerants/intel_extreme/engine.cpp index 6fd9bac195..a7e5ab894e 100644 --- a/src/add-ons/accelerants/intel_extreme/engine.cpp +++ b/src/add-ons/accelerants/intel_extreme/engine.cpp @@ -9,6 +9,7 @@ #include "accelerant.h" #include "accelerant_protos.h" +#include "commands.h" #define TRACE_ENGINE @@ -23,37 +24,96 @@ extern "C" void _sPrintf(const char *format, ...); static engine_token sEngineToken = {1, 0 /*B_2D_ACCELERATION*/, NULL}; -/** The ring buffer must be locked when calling this function */ - -void -write_to_ring(ring_buffer &ring, uint32 value) +QueueCommands::QueueCommands(ring_buffer &ring) + : + fRingBuffer(ring) { - uint32 *target = (uint32 *)(ring.base + ring.position); - *target = value; - - ring.position = (ring.position + sizeof(uint32)) & (ring.size - 1); + acquire_lock(&fRingBuffer.lock); } -/** The ring buffer must be locked when calling this function */ - -void -ring_command_complete(ring_buffer &ring) +QueueCommands::~QueueCommands() { - if (ring.position & 0x07) { + if (fRingBuffer.position & 0x07) { // 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 - // is in write combining mode - int32 test; - atomic_add(&test, 1); + // We must make sure memory is written back in case the ring buffer + // is in write combining mode - releasing the lock does this, as the + // buffer is flushed on a locked memory operation (which is what this + // 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 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 */ @@ -132,3 +192,6 @@ intel_sync_to_token(sync_token *syncToken) return B_OK; } + +// #pragma mark - engine acceleration + diff --git a/src/add-ons/accelerants/intel_extreme/overlay.cpp b/src/add-ons/accelerants/intel_extreme/overlay.cpp index e4af605fa2..aa6697cd98 100644 --- a/src/add-ons/accelerants/intel_extreme/overlay.cpp +++ b/src/add-ons/accelerants/intel_extreme/overlay.cpp @@ -12,6 +12,7 @@ #include "accelerant.h" #include "accelerant_protos.h" +#include "commands.h" #include #include @@ -225,19 +226,14 @@ update_overlay(bool updateCoefficients) if (!gInfo->shared_info->overlay_active) return; - ring_buffer &ringBuffer = gInfo->shared_info->secondary_ring_buffer; - write_to_ring(ringBuffer, COMMAND_FLUSH); - write_to_ring(ringBuffer, COMMAND_NOOP); - write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP); - 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); + QueueCommands queue(gInfo->shared_info->secondary_ring_buffer); + queue.PutFlush(); + queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP); + queue.PutOverlayFlip(COMMAND_OVERLAY_CONTINUE, updateCoefficients); - 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_EXTENDED_STATUS))); +// 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_EXTENDED_STATUS))); } @@ -252,13 +248,9 @@ show_overlay(void) gInfo->shared_info->overlay_active = true; registers->overlay_enabled = true; - ring_buffer &ringBuffer = gInfo->shared_info->secondary_ring_buffer; - write_to_ring(ringBuffer, COMMAND_FLUSH); - write_to_ring(ringBuffer, COMMAND_NOOP); - 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); + QueueCommands queue(gInfo->shared_info->secondary_ring_buffer); + queue.PutFlush(); + queue.PutOverlayFlip(COMMAND_OVERLAY_ON, true); } @@ -273,26 +265,19 @@ hide_overlay(void) gInfo->shared_info->overlay_active = 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 - write_to_ring(ringBuffer, COMMAND_FLUSH); - write_to_ring(ringBuffer, COMMAND_NOOP); - write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP); - write_to_ring(ringBuffer, COMMAND_NOOP); + queue.PutFlush(); + queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP); // clear overlay enabled bit - write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_CONTINUE); - write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers); - write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP); - write_to_ring(ringBuffer, COMMAND_NOOP); + queue.PutOverlayFlip(COMMAND_OVERLAY_CONTINUE, false); + queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP); // turn off overlay engine - write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_OFF); - write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers); - write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP); - write_to_ring(ringBuffer, COMMAND_NOOP); - ring_command_complete(ringBuffer); + queue.PutOverlayFlip(COMMAND_OVERLAY_OFF, false); + queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP); gInfo->current_overlay = NULL; }